Tofu – Test Fixtures and other handy testing utilities (reahl.tofu)

Tofu started out its life as a complete test framework. Tofu has since been rewritten as independently usable test utilities, some of which are integrated to work as a plugin with nosetests.

The defining feature of Tofu is its ability to let you write a hierarchy of test fixtures that is completely decoupled from your hierarchy of tests or test suites.

Tofu also gobbled up another little test project, called tut which implemented a few utilities for testing exceptions, dealing with temporary files, etc. All this functionality is now also part of Tofu.

Test Fixtures

Fixture

class reahl.tofu.Fixture(fixture, scenario=<reahl.tofu.fixture.DefaultScenario object at 0x5000b90>)

A test Fixture is a collection of objects defined and set up to be used together in a test.

Programmers should extend this class by creating subclasses of Fixture. On such a subclass, a new member of the Fixture is defined by a specially named method that is able to create the object.

The name of such a ‘factory method’ is new_ with the name of the object appended.

When an object is referenced by name on the fixture, the corresponding new_ method is called, and the resulting object cached as a singleton for future accesses.

A Fixture instance can be used as a context manager. It is set up before entering the block of code it manages, and torn down upon exiting it.

A Fixture has a default reahl.component.context.ExecutionContext instance available as its .context attribute, which can be overridden by creating a method named new_context on a subclass.

clear()

Clears all existing singleton objects.

scenario

reahl.tofu.scenario

alias of Scenario

class reahl.tofu.fixture.Scenario(function)

A Scenario is a variation on a Fixture.

A Scenario is defined as a Fixture method which is decorated with @scenario. The Scenario method is run after setup of the Fixture, to provide some extra setup pertaining to that scenario only.

When a Fixture that contains more than one scenario is used with nosetests, the test will be run once for every Scenario defined on the Fixture. Before each run of the Fixture, a new Fixture instance is set up, and only the current scenario method is called to provide the needed variation on the Fixture.

set_up

reahl.tofu.set_up

alias of SetUp

class reahl.tofu.fixture.SetUp(function)

Methods on a Fixture marked as @set_up are run when the Fixture is set up.

tear_down

reahl.tofu.tear_down

alias of TearDown

class reahl.tofu.fixture.TearDown(function)

Methods on a Fixture marked as @tear_down are run when the Fixture is torn down.

Integration with nose

@test

reahl.tofu.test

alias of IsTestWithFixture

class reahl.tofu.nosesupport.IsTestWithFixture(fixture_class)

Use as decorator to mark a method or function as being a test that nose should run. The given Fixture class will be instantiated and setup before the test is run, and passed to to the method as its single argument.

For example:

class MyFixture(Fixture):
    def new_something(self):
        return 'something'

@test(MyFixture)
def some_function(self, fixture):
    assert fixture.something == 'something'

RunFixturePlugin

class reahl.tofu.nosesupport.RunFixturePlugin

A plugin for nose which creates and sets up a run fixture during the test run. Enable this plugin by passing --with-run-fixture=<locator> to nosetests on the commandline.

<locator> is a string specifying how to find a Fixture class. It starts with the name of the Python package where the class is defined, followed by a colon and then the name of the class. For example: “reahl.webdev.fixtures:WebFixture”

LongOutputPlugin

class reahl.tofu.nosesupport.LongOutputPlugin

A plugin for nose which lets nose output the name of each test before it starts running it. Enable this plugin by passing --with-long-output to nosetests on the commandline.

TestDirectoryPlugin

class reahl.tofu.nosesupport.TestDirectoryPlugin

A plugin for nose which changes how nose finds tests to run. It lets you specify a test directory and will search all modules (recursively) inside that test directory only. Each python file is searched, and anything marked with an @test or nose’s @istest is run as a test.

Enable this plugin by passing --with-test-directory=<directory path relative to current dir> to nosetests on the commandline.

LogLevelPlugin

class reahl.tofu.nosesupport.LogLevelPlugin

A plugin for nose which sets the log level for the test run.

Enable this plugin by passing --with-log-level=(ERROR|WARNING|INFO|DEBUG) to nosetests on the commandline.

SetUpFixturePlugin

class reahl.tofu.nosesupport.SetUpFixturePlugin

A plugin for nose which only runs the setup of a given Fixture, no tests, and no tear down. This is useful for creating a demo database with useful contents.

Enable this plugin by passing --with-setup-fixture=<locator> to nosetests on the commandline.

<locator> is a string specifying how to find a Fixture class. It starts with the name of the Python package where the class is defined, followed by a colon and then the name of the class. For example: “reahl.webdev.fixtures:WebFixture”

Testing for exceptions

expected

reahl.tofu.expected(*args, **kwds)

Returns a context manager that can be used to check that the code in the managed context does indeed raise the given exception.

Parameters:
  • exception – The class of exception to expect
  • test – A function that takes a single argument. Upon catching the expected exception, this callable is called, passing the exception instance as argument. A programmer can do more checks on the specific exception instance in this function, such as check its arguments.

For example, the following code will execute without letting a test break:

with expected(AssertionError):
    # some code here
    # .....
    # then at some point an exception is raised
    raise AssertionError()
    #.....

NoException

class reahl.tofu.NoException

A special exception class used with expected() to indicate that no exception is expected at all.

For example, the following code will break a test:

with expected(NoException):
    # some code here
    # .....
    # then at some point an exception is raised
    raise AssertionError()
    #.....

check_limitation

reahl.tofu.check_limitation(coded_version, msg)

Warns that a newer Python version is now used, which may have a fix for a limitation which had to be worked around previously.

Parameters:
  • coded_version – The version of Python originally used to write the code being tested. The limitation is present in this version and the test will only break for newer versions than coded_version.
  • msg – The message to be shown if a newer Python version is used for running the code.

vassert

class reahl.tofu.vassert(expression)

A replacement for the Python assert statement which shows the values of some variables if the assertion fails.

Parameters:expression – A boolean expression. The assertion will fail if this expression does not evaluate to True.

For example, the following code will yield the stack trace shown below it:

i = 123
vassert( i == 1 )
AssertionError: vassert( i == 1 )

----- values were -----
i: 123 (<type 'int'>)       

Temporary files and directories

file_with

reahl.tofu.file_with(name, contents)

Creates a file with the given name and contents. The file will be deleted automatically when it is garbage collected. The file is opened after creation, ready to be read.

Parameters:
  • name – The full path name of the file to be created.
  • contents – The contents of the file.

temp_dir

reahl.tofu.temp_dir()

Creates an AutomaticallyDeletedDirectory.

temp_file_name

reahl.tofu.temp_file_name()

Returns a name that may be used for a temporary file that may be created and removed by a programmer.

temp_file_with

reahl.tofu.temp_file_with(contents, name=None)

Returns an opened, named temp file with contents as supplied. If name is supplied, the file is created inside a temporary directory.

Parameters:
  • contents – The contents of the file.
  • name – If given, the the name of the file (not including the file system path to it).

AutomaticallyDeletedDirectory

class reahl.tofu.AutomaticallyDeletedDirectory(name)

A directory that is deleted upon being garbage collected.

Parameters:name – The full path name of the directory.
file_with(name, contents)

Returns a file inside this directory with the given name and contents.

temp_dir()

Returns a directory inside this directory.

sub_dir(name)

Returns a directory inside this directory with the given name.