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 0x2b0a2fb0f438>)¶
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 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.
- 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.
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(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.