Documentation versions

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>)

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.

If a corresponding del_ method exists for a given new_ method, it will be called when the Fixture is torn down. This mechanism exists so you can dispose of the singleton created by the new_ method. These del_ methods are called only for singleton instances that were actually created, and in reverse order of creation of each instance. Singleton instances are also torn down before any other tear down logic happens (because, presumably the instances are all created after all other setup occurs).

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 instance also has a context manager available as its ‘.context’ attribute. Setup, test run and tear down code is run within the context of ‘.context’ as well. The default context manager does not do anything, but you can supply your own by creating a method named new_context on a subclass. If no custom context is given and the fixture has a run_fixture, the run_fixture.context is used.

Changed in version 3.2: Added support for del_ methods.

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'

set_run_fixture

reahl.tofu.nosesupport.set_run_fixture(fixture, namespace)

Adds setup and teardown methods to the calling context that will set a fixture as the run fixture for tests in that context.

The run fixture is set up only once: before any tests are run in the calling context, and torn down once after all tests in this context have run. Fixtures used by tests in this context will have their .run_fixture set to the Fixture instance you set here.

Parameters:
  • fixture – The Fixture instance to use as run fixture for this context.
  • namespace – Pass locals() from the context where set_run_fixture is called here.

New in version 3.1.

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.

MarkedTestsPlugin

class reahl.tofu.nosesupport.MarkedTestsPlugin

A Nose plugin that changes the meaning of testMatch, include and exclude patterns. With –marked-tests, thse patterns are only applied to file and directory names, and disregarded when modules and the Python objects inside them are assessed.

Python objects are regarded as tests only of they are marked marked with an @test or nose’s @istest. Python modules are regarded as test modules regardless of name except if __test__ is explicitly set to False in the __init__.py of that module.

Enable this plugin by passing --with-marked-tests to nosetests on the commandline.

New in version 3.1.

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(exception, test=None)

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, mode='w+')

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.
  • mode – The mode to open the file in, as per open() builtin.
  • contents – The contents of the file. Must text unless binary mode was specified, in which case bytes should be used.

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, mode='w+')

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

Parameters:
  • mode – The mode to open the file in, as per open() builtin.
  • contents – The contents of the file. Must text unless binary mode was specified, in which case bytes should be used.
  • 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, mode='w+')

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.

Documentation versions