Archive for the 'Software Engineering' Category



Scala 2.9.1, sbt 0.10 and ScalaTest step-by-step

Some while ago, I wrote a post about getting Scala 2.8.0.RC1, sbt and ScalaTest to work together. Well, things have moved on somewhat since then, so I thought it was time to update it.

  1. Install sbt 0.10.1
  2. Create the root directory for your project:
    $ mkdir aproject
  3. Create a settings file in this directory called build.sbt containing:
    name := "A Project"
    
    version := "0.1"
    
    scalaVersion := "2.9.1"
    
    libraryDependencies ++= Seq(
      "org.scalatest" %% "scalatest" % "1.6.1" % "test"
    )
  4. Create src/main/scala/Widget.scala containing:
    package com.example
    
    class Widget {
      def colour = "Blue"
      def disposition = "Awesome"
    }
  5. Create src/test/scala/WidgetTest.scala containing:
    package com.example.test
    
    import org.scalatest.FunSuite
    import com.example.Widget
    
    class WidgetTest extends FunSuite {
    
      test("colour") {
        expect("Blue") { new Widget().colour }
      }
    
      test("disposition") {
        expect("Awesome") { new Widget().disposition }
      }
    }
  6. Run your tests with sbt test. You should see:
    [info] WidgetTest:
    [info] - colour
    [info] - disposition
    [info] Passed: : Total 2, Failed 0, Errors 0, Passed 2, Skipped 0
  7. Create src/main/scala/Main.scala containing:
    package com.example
    
    object Main {
      def main(args: Array[String]) {
        val w = new Widget()
        println("My new widget is "+ w.colour)
      }
    }
  8. Run your program with sbt run. You should see:
    [info] Running com.example.Main
    My new widget is Blue

"Power" mocking in Scala with Borachio

The work described in this post has now been released in ScalaMock.

Over the last few weeks, I’ve been working on major enhancements for Borachio (my native mocking library for Scala) to add facilities similar to those provided by PowerMock for Java. As well as interfaces and functions, it can now mock:

  • Classes
  • Final classes and classes with final methods
  • Classes with private constructors
  • Singleton (companion) objects
  • Object creation (i.e. new)

And, as an extra bonus, mocks are now typesafe :-).

It’s not completely finished yet, but it is close enough that it’s worth soliciting feedback. The code is available on GitHub and a snapshot is available on scala-tools.

Warning: Although this is getting close to “done”, the details may change slightly before final release.

So what does this look like in action? I’m going to demonstrate with a slightly modified version of Martin Fowler’s “warehouse” example from Mocks Aren’t Stubs. This example is available on GitHub. First, here’s a Warehouse object (a Scala singleton object):

object Warehouse {
  val products = Map(("Talisker" -> 5), ("Lagavulin" -> 2))

  def hasInventory(product: String, quantity: Int) =
    inStock(product) >= quantity

  def remove(product: String, quantity: Int) =
    products += (product -> (inStock(product) - quantity))

  def inStock(product: String) = products.getOrElse(product, 0)
}

And here’s an Order class that removes things from the warehouse:

class Order(product: String, quantity: Int) {
  var filled = false

  def fill() {
    if (Warehouse.hasInventory(product, quantity)) {
      Warehouse.remove(product, quantity)
      filled = true
    }
  }
}

object Order {
  def apply(product: String, quantity: Int) =
    new Order(product, quantity)

  def largestPossible(product: String) = {
    val quantity = Warehouse.inStock(product)
    new Order(product, quantity)
  }
}

First, let’s see how we can go about testing the Order class by mocking the Warehouse object:

test("Enough stock") {
  val mockWarehouse = mockObject(Warehouse)

  mockWarehouse.expects.hasInventory("Talisker", 50) returning true
  mockWarehouse.expects.remove("Talisker", 50)

  val order = Order("Talisker", 50)
  order.fill

  assert(order.filled)
}

The “magic” happens in the mockObject call:

  val mockWarehouse = mockObject(Warehouse)

This returns a mock version of the Warehouse object upon which expectations can be set. From that point onwards, the code should be pretty self-explanatory.

Another example, this time of mocking object creation:

test("Order everything") {
  val mockWarehouse = mockObject(Warehouse)
  val mockOrder = mock[Order]

  mockWarehouse.expects.inStock("Laphroig") returning 10
  mockOrder.expects.newInstance("Laphroig", 10)

  Order.largestPossible("Laphroig")
}

This uses two mock objects, one representing the Warehouse object and one representing an (as yet uncreated) instance of the Order class:

  val mockWarehouse = mockObject(Warehouse)
  val mockOrder = mock[Order]

The interesting line is this one:

  mockOrder.expects.newInstance("Laphroig", 10)

Which sets an expectation that a new instance of the Order class will be created with constructor arguments ("Laphroig", 10).

Building

Most of the cleverness happens within a Scala compiler plugin. Compiling tests that use mocks requires three steps:

  1. Compile the code you want to test as normal.
  2. Compile this code again with the Borachio compiler plugin enabled. The plugin will generate mock source code for any classes and objects mentioned in @mock @mockObject annotations.
  3. Compile this code together with your test code

These steps have all been collected into an sbt plugin, so all you need to do is mix the GenerateMocks trait into your project definition and everything else should happen automagically.

Under the hood

Given the Order class in our example above, the compiler plugin generates two different classes, one with the same name (i.e. Order) and one called Mock$Order. Here’s (a simplified version of) what they look like:

class Order(dummy: MockConstructorDummy) extends Mock$Order {

  def fill(): Unit = mock$0()
  def this(product: String, quantity: Int) = {
    this(new MockConstructorDummy)
    mock$1(product, quantity)
  }

  lazy val mock$0 = new MockFunction0[Unit]
  lazy val mock$1 = new MockConstructor2[String, Int, Order]
}

trait Mock$Order {

  val expects = new {
    def fill() = mock$0.expects()
    def newInstance(product: String, quantity: Int) =
      mock$1.expects(product, quantity)

    lazy val mock$0 = // reference to mock$0 in Order
    lazy val mock$1 = // reference to mock$1 in Order
  }
}

Borachio then uses a custom class loader to ensure that, when the code being tested tries to load the Order class, it gets the generated version above (calls get forwarded to the “real” Order class if mocking isn’t in force).

To do

I hope that this code is complete enough to be useful. Certainly it’s complete enough that I’d welcome feedback on anything that doesn’t work or could be done better. The things that still need doing are:

  • Android and JUnit3 integration
  • Support for mocking private constructors and methods
  • Forwarding to non-mock singleton functionality (this is in place for classes, not yet for singleton objects)
  • Static method (Java) support
  • Support for type-parameterised methods

Video: Mocking, Testing and Dependency Injection

A video of Chetan Padia talking about Mocking, Testing and Dependency Injection at Londroid.

Android, Dependency Injection and Mock Testing

James Aley has written up a great worked example of using Borachio on Android with RoboGuice for Dependency Injection.

Towards typesafe native Scala mocks in Borachio

The work described in this post has now been released in ScalaMock.

Borachio, my native mocking library for Scala, works well enough but has a couple of annoying limitations:

  • It can only mock functions and traits (interfaces). No support for classes, companion objects, constructors, etc. etc. etc.
  • It’s not typesafe.

I’ve been working to address those limitations and, although I’m far from done, I’ve made enough progress to be worth reporting.

Warning: The code described here is experimental and very likely to change. Use at your own risk, and don’t be surprised if things break in the future.

This experimental version of Borachio (the code is in the typesafemocks branch and a compiled snapshot is available here) uses a Scala compiler plugin to generate typesafe mock objects. These mock objects can extend traits or classes.

Unfortunately, current limitations of the Scala compiler plugin architecture mean that it’s effectively impossible to generate methods within a compiler plugin (see this discussion to understand why). So the Borachio plugin instead requires two passes – one pass to generate the source and then a second pass to compile it.

There’s an example of its use (an updated version of the Turtle example) available on GitHub.

The key class in this example is Turtle:

class Turtle {
  def penUp() { ... }
  def penDown() { ... }
  def forward(distance: Double) { ... }
  def turn(angle: Double) { ... }
  def getAngle = { ... }
  def getPosition = { ... }
}

In the first pass, the compiler is called with the -P:borachio:generatemocks argument. This causes the plugin to look for @mock annotations to determine which classes it needs to generate mocks for. Here’s how we specify that we want to create mock turtles:

@mock(classOf[Turtle])
class Dummy

And here’s what the plugin generates as a result:

class MockTurtle(factory: com.borachio.AbstractMockFactory) extends com.example.Turtle {
  override def getPosition = mock$getPosition()
  override def getAngle = mock$getAngle()
  override def turn(angle: Double) = mock$turn(angle)
  override def forward(distance: Double) = mock$forward(distance)
  override def penDown() = mock$penDown()
  override def penUp() = mock$penUp()

  val expects = new {
    def getPosition: com.borachio.TypeSafeExpectation[(Double, Double)] = mock$getPosition.expects()
    def getAngle: com.borachio.TypeSafeExpectation[Double] = mock$getAngle.expects()
    def turn(angle: com.borachio.MockParameter[Double]): com.borachio.TypeSafeExpectation[Unit] = mock$turn.expects(angle)
    def forward(distance: com.borachio.MockParameter[Double]): com.borachio.TypeSafeExpectation[Unit] = mock$forward.expects(distance)
    def penDown(): com.borachio.TypeSafeExpectation[Unit] = mock$penDown.expects()
    def penUp(): com.borachio.TypeSafeExpectation[Unit] = mock$penUp.expects()
  }

  private val mock$getPosition = new com.borachio.MockFunction0[(Double, Double)](factory, 'getPosition)
  private val mock$getAngle = new com.borachio.MockFunction0[Double](factory, 'getAngle)
  private val mock$turn = new com.borachio.MockFunction1[Double, Unit](factory, 'turn)
  private val mock$forward = new com.borachio.MockFunction1[Double, Unit](factory, 'forward)
  private val mock$penDown = new com.borachio.MockFunction0[Unit](factory, 'penDown)
  private val mock$penUp = new com.borachio.MockFunction0[Unit](factory, 'penUp)
}

This can then be used in tests like this:

class ControllerTest extends Suite with MockFactory {

  val mockTurtle = new MockTurtle(this)
  val controller = new Controller(mockTurtle)

  def testDrawLine() {
    inSequence {
      mockTurtle.expects.getPosition.returning((0.0, 0.0))
      mockTurtle.expects.getAngle.returning(0.0)
      mockTurtle.expects.penUp
      mockTurtle.expects.turn(~(Pi / 4))
      mockTurtle.expects.forward(~sqrt(2.0))
      mockTurtle.expects.getAngle.returning(Pi / 4)
      mockTurtle.expects.turn(~(-Pi / 4))
      mockTurtle.expects.penDown
      mockTurtle.expects.forward(1.0)
    }

    controller.drawLine((1.0, 1.0), (2.0, 1.0))
  }
}

There’s still a huge amount left to do:

  • Support for type-parameterised methods
  • Support for classes with non-trivial constructors
  • Support for final classes or classes with final methods or private constructors
  • Support for companion objects
  • etc. etc. etc.

And hopefully the limitations on code generation in Scala compiler plugins will be lifted soon, meaning that the two-stage compilation process won’t be necessary either.

Mock objects on Android with Borachio: Part 3

As we saw in part 2 of this series, mocking Android’s PowerManager service directly is impossible. But there is an alternative approach that gives us something close enough. This article describes that approach.

The code of the application described here is checked into GitHub.

Given that we can’t mock PowerManager directly, instead we’re going to create an interface that we can mock:

public interface PowerControl
{
    void disablePowerOff();
    void enablePowerOff();
}

Together with an implementation which will be used in production code:

public class PowerControlImpl implements PowerControl
{
    public PowerControlImpl(Context context) {
        PowerManager powerManager = (PowerManager)
            context.getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(
            PowerManager.FULL_WAKE_LOCK, "PowerControl");
    }

    public void disablePowerOff() {
        wakeLock.acquire();
    }

    public void enablePowerOff() {
        wakeLock.release();
    }

    private PowerManager.WakeLock wakeLock;
}

We won’t be able to test this implementation, but hopefully it’s so simple that (as Hoare puts it) it obviously contains no deficiencies (as opposed to contains no obvious deficiencies).

But we do now have something that we can mock, so we can test that the code that calls it does so correctly.

The first challenge we’re going to have to overcome is how to inject a PowerControl implementation (the real one or the mock) into the code under test. We could use a dependency injection framework like RoboGuice, but for the purposes of this article I’m going to keep things simple and use a custom Application class which implements a getPowerControl method:

public class PowerControlApplication extends Application
{
    public void onCreate() {
        powerControl = new PowerControlImpl(this);
    }

    public PowerControl getPowerControl() {
        return powerControl;
    }

    protected PowerControl powerControl;
}

Our activity calls this during onCreate:

public class PowerActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        PowerControlApplication app =
            (PowerControlApplication)getApplication();
        powerControl = app.getPowerControl();
    }

    public void startImportant(View button) {
        powerControl.disablePowerOff();
    }

    public void stopImportant(View button) {
        powerControl.enablePowerOff();
    }

    private PowerControl powerControl;
}

We can now write a test to verify that startImportant calls disablePowerOff:

class PowerActivityTest
  extends ActivityUnitTestCase[PowerActivity](classOf[PowerActivity])
  with MockFactory {

  val startIntent = new Intent(Intent.ACTION_MAIN)

  def testStartImportant {
    val mockPowerControl = mock[PowerControl]
    val application = new PowerControlApplication {
      powerControl = mockPowerControl
    }
    setApplication(application)
    startActivity(startIntent, null, null)

    withExpectations {
      mockPowerControl expects 'disablePowerOff once

      getActivity.startImportant(null)
    }
  }
}

Our test first creates a mock PowerControl object:

    val mockPowerControl = mock[PowerControl]

And then creates an application object that returns this mock instead of a “real” PowerControl instance:

    val application = new PowerControlApplication {
      powerControl = mockPowerControl
    }

We tell Android’s test framework to use this application object by calling setApplication:

    setApplication(application)

Finally, we set our expectation (that disablePowerOff is called once) and call startImportant:

    mockPowerControl expects 'disablePowerOff once

    getActivity.startImportant(null)

Updated 2011-04-15

Updated to Borachio 0.6.

Mock objects on Android with Borachio: Part 2

In part 1 of this series, I showed how to mock an interface that we created ourselves under Android. That’s useful, but mocking really pays dividends when mocking OS services—doing so allows us to test our code in isolation, verify that it interacts with the OS correctly and that it handles errors properly.

But there’s a wrinkle. Android is the most test-hostile environment I’ve ever had the misfortune to find myself working in. I wonder sometimes if its designers deliberately designed it to make testing as difficult as they possibly could. It can be done, and I’ll show how in part 3, but if you’ll forgive me a digression, in this article I’m going to try the simple, “obvious” solution and demonstrate why it doesn’t work.

I’m going to try to write a simple test of an application that uses Android’s PowerManager service. PowerManager allows us to control when the device switches on or off. If we’re about to start some critical operation that must complete without the device switching off, we can obtain a WakeLock, which is what this sample app does.

The code is checked into GitHub. Here’s the code that we want to test:

package com.paulbutcher.powercontrol;

import android.app.Activity;
import android.os.Bundle;
import android.os.PowerManager;
import android.view.View;

public class PowerControl extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void startImportant(View button) {
        PowerManager powerManager =
            (PowerManager)getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(
            PowerManager.FULL_WAKE_LOCK, "PowerControl");
        wakeLock.acquire();
    }

    public void stopImportant(View button) {
        wakeLock.release();
    }

    private PowerManager.WakeLock wakeLock;
}

Let’s try to write a test that verifies that startImportant calls PowerManager.newWakeLock. Our first task is going to be working out how to inject a mock PowerManager into the code under test.

That code obtains its PowerManager instance by calling Context.getSystemService. Happily, Android provides MockContext and ActivityUnitTestCase.setActivityContext, so we should be all set.

Before we get carried away, let’s just verify that we can get a test using a MockContext to run at all:

  def testAttempt1 {
    val mockContext = new MockContext;
    setActivityContext(mockContext)
    startActivity(startIntent, null, null)
  }

Let’s see what happens when we run that:

Failure in testAttempt1:
junit.framework.AssertionFailedError
  at android.test.ActivityUnitTestCase.startActivity(ActivityUnitTestCase.java:148)

Hmm—apparently this isn’t going to be as easy as we hoped.

The problem is that startActivity calls our MockContext. Specifically it calls getSystemService("layout_inflater") which fails because MockContext‘s methods are non-functional and throw UnsupportedOperationException.

It turns out that what Android means by “mock” isn’t what the rest of the world means. As Martin Fowler says in Mocks Aren’t Stubs, mocks are:

objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

Never mind—there is another way. Android’s ContextWrapper allows us to wrap an existing context, only changing those bits of functionality we’re interested in for the purposes of our test:

  def testAttempt2 {
    val testContext =
        new ContextWrapper(getInstrumentation.getTargetContext);
    setActivityContext(testContext)
    startActivity(startIntent, null, null)
  }

That works, so now we just need to modify it to return a mock PowerManager when getSystemService is called:

  def testAttempt3 {
    val mockPowerManager = mock[PowerManager]
    val testContext =
      new ContextWrapper(getInstrumentation.getTargetContext) {
        override def getSystemService(name: String) = name match {
          case "power" => mockPowerManager
          case _ => super.getSystemService(name)
        }
      }
    setActivityContext(testContext)
    startActivity(startIntent, null, null)
  }

Which looks great, right up until we run it:

Error in testAttempt3:
java.lang.IllegalArgumentException: android.os.PowerManager is not an interface

Borachio, in common with most other mocking frameworks, can only mock interfaces, and PowerManager is a class, not an interface. There are mocking frameworks that can mock classes, for example PowerMock, but they rely on code generation, which Android’s Dalvik VM doesn’t (yet) support. So that’s not going to be any help 😦

There’s one final thing we can try. As well as mocking interfaces, Borachio can also mock functions. So we can derive from PowerManager and just mock the single method we’re interested in like this:

  def testAttempt4 {
    val mockNewWakeLock =
      mockFunction[Int, String, PowerManager#WakeLock]
    val mockPowerManager = new PowerManager {
      override def newWakeLock(flags: Int, tag: String) =
        mockNewWakeLock(flags, tag)
    }
    val testContext =
      new ContextWrapper(getInstrumentation.getTargetContext) {
        override def getSystemService(name: String) = name match {
          case "power" => mockPowerManager
          case _ => super.getSystemService(name)
        }
      }
    setActivityContext(testContext)
    startActivity(startIntent, null, null)
  }

But, when we compile this, we get:

PowerControlTest.scala:53: error: constructor PowerManager cannot be accessed in anonymous class $anon
    val mockPowerManager = new PowerManager {
                               ^

PowerManager‘s constructor is private 😦

And at this point, we’re out of easy options. We can’t play the same trick with PowerManager as we played with Context, as there’s no PowerManagerWrapper or similar.

We’re not beaten yet—I’ll show how to get around this problem in part 3 of this series. Small wonder, however, that most of the Android code I’ve seen has virtually no tests!