← Back to team overview

launchpad-dev team mailing list archive

Writing stubs made easy

 

Greetings fellow hackers,

ever had to do this in test code?


class FakeClass(ClassThatIWantToTest):
    """Version of ClassThatIWantToTest mocked up for testing."""
    def _getTime(self):
        """Faking this so the test gets predictable timestamps."""
        return datetime.datetime(2010, 02, 14)


Or this?


class MockSlave:
    """Pretend build-farm slave for testing.

    Can't invoke a real build-farm slave from the test suite.
    """
    run_has_been_called = False
    def run(self):
        """Pretend to run."""
        self.run_has_been_called = True


Or this?


class FakeTalkToServer(RealTalkToServer):
    def talk(self):
        """Simulate protocol failure for testing."""
        raise HttpException("Bet you can't catch this!")


I got tired of doing that, so I just landed a branch that makes it all a bit easier. In lp.testing.fakemethod you'll find a new class FakeMethod. Objects of this type are stub functions/methods. (But I didn't call them that so we can discuss them without making Stuart's IRC client go off :).

A FakeMethod can take the place of any function or method, and:

 - Return a constant value.
 - Raise an exception instead.
 - Tell you how many times it's been invoked.

The tests you needed those fake classes for are now much shorter:

    objectiwanttotest._getTime = FakeMethod(
        result=datetime.datetime(2010, 02, 14))

or

    slave.run = FakeMethod()

    do_stuff_with(slave)

    # The slave has been run exactly once.
    self.assertEqual(1, slave.run.call_count)

or

    realtalktoserver.talk = FakeMethod(failure=HttpException(
        "Bet you can't catch this!"))

respectively. It saves time writing tests, but also lets your test get to parts it couldn't normally reach because you can mock up so many things so quickly. Plus you can unit-test more classes in fast tests using fewer layers, with all the complex work ripped out and exercised only in integration tests.

An ancestor of this class allowed me to write unit tests for our failing EC2 scripts a few months back, and this time I hit a second big use-case with the buildfarm work. Hope you enjoy it as I do!


Jeroen



Follow ups