Using the fixture module

fixture is a python module for loading and referencing test data

It provides several utilities for achieving a fixed state when testing Python programs. Specifically, these utilities setup / teardown databases and work with temporary file systems. This is useful for testing and came about to fulfill stories like these:

  • I want to load data into a test database and easily reference that data when making assertions.
  • I want data linked by foreign key to load automatically and delete without integrity error.
  • I want to reference linked rows by meaningful names, not hard-coded ID numbers.
  • I don’t want to worry about auto-incrementing sequences.
  • I want to recreate an environment (say, for a bug) by querying a database for real data.
  • I want to test with files in a temporary, transparent file system.

For more info, this concept is explained in the wikipedia article, Test Fixture.

Database testing is easier than I had thought. Kumar’s fixture helps provide a stable database to drive testing.Steven F. Lott, summarizing PyCon 2007

Download / Install

Using the easy_install command:

easy_install fixture

Or pip

pip install fixture

If you want to use decorators like @fixture.with_data() you need nose installed, so run:

easy_install 'fixture[decorators]'

Note

The above commands may require root access

For more variants on the easy_install command, such as installing database libraries, see Using LoadableFixture.

The source is available from the fixture package or the fixture repository and the following command works with or without setuptools:

cd /path/to/source
python setup.py install

To run Fixture’s own test suite you need to create a buildout

python setup_test_buildout.py
./bin/buildout

Then you can run the tests with

./bin/test-fixture

Requirements

At the moment fixture is only tested on Python 2.4, 2.5, and 2.6 so it may or may not work with other versions. The module does not depend on external libraries for its core functionality but to do something interesting you will need one of several 3rd party libraries (explained later in the documentation).

Loading and referencing test data

There are a couple ways to test a database-backed application. You can create mock objects and concentrate entirely on unit testing individual components without testing the database layer itself, or you can simply load up sample data before you run a test. Thanks to sqlite in-memory connections, the latter may be more efficient than you think.

But it’s easy enough to insert data line by line in code, right? Or simply load a SQL file? Yes, but this has two major downsides: you often have to worry about and manage complex chains of foreign keys manually; and when referencing data values later on, you either have to copy / paste the values or pass around lots of variables.

The fixture module simplifies this by breaking the process down to two independent components:

DataSet
Defines sets of sample data
Fixture
Knows how to load data

Examples of Usage

Fixture can be used to load DataSet objects into the following backends:

You can read the section on loading data for general information. For a complete end-to-end example see Using Fixture To Test A Pylons + SQLAlchemy App, Using Fixture To Test A Google App Engine Site or Using Fixture To Test Django. This should help you understand how to fit fixture into a finished app.

Now, on to the knitty gritty details ...

Status

fixture was originally a reimplementation of testtools.fixtures, the first attempt at the idea. As of September 2009 the fixture module is used in several test suites by the author’s development team at work using the SQLAlchemy backend. Several contributors seem to be using it in their own projects as well for various backends like Google App Engine and Django. The project started in 2007.

Contact

Read on for info on submitting issues. For general discussion about fixture, how about the Testing In Python mailing list? Otherwise, you can try me here: kumar.mcmillan @gmail.com

Where to submit issues, patches, bugs

Please submit any issues, patches, failing tests, and/or bugs using the Issue Tracker on the fixture project site. If your code is used, your contribution will be acknowledged in the docs.

Changelog

  • 1.4
  • 1.3
    • Django support added by Ben Ford. See Using Fixture To Test Django
    • Using session.add() when in sqlalchemy 0.5.2+ to avoid deprecation warning (reported by Jeff Balogh)
    • Google Code repository migrated from Subversion to Mercurial.
  • 1.2
    • Added support for DataSet to JSON conversion
  • 1.1.2
    • Fixed bugs relating to SQLAlchemy 0.5 support (still not fully complete)
  • 1.1.1
    • Fixed bugs in Google App Engine Datastore thanks to reports and patches by Tomas Holas
    • Fixed installation bug thanks to report by bslesinsky
    • Made progress on SQLAlchemy 0.5 support (not yet complete) thanks to reports and patches from Alex Marandon
    • Improved scoped session handling for SQLAlchemy
  • 1.1
    • Added support for loading data into the Google App Engine Datastore
    • Added fixture.util.reset_log_level()
    • CHANGED the default log level to CRITICAL for all internal fixture logs so that they don’t output gobs of debug code when some other module adds a handler to the root logger.
    • A couple bugs fixed
  • 1.0
  • 0.9
    • First release where everything “kinda worked”