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

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

easy_install 'fixture[decorators]'

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 subversion repository and the following command works with or without setuptools:

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

Note

The above commands may require root access

If you want to try out fixture before installing it globally, you may be interested in virtualenv.

Requirements

At the moment fixture is only tested on Python 2.4 and 2.5 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

Status

fixture is a reimplementation of testtools.fixtures which was my first attempt at the idea. As of July 2008 the fixture module is used in several test suites by my development teams at work. One project is a data migration (ETL) framework using SQLObject and another is an in-house Pylons + Ext JS application using SQLAlchemy and Elixir. It has been open source for a while but with only a few contributors so I’m not sure how much it’s used outside of that.

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 documented.

Changelog

  • 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”