It's a short introduction to a project we have made recently here at
Doist Inc to improve our test codebase. The project is
named resources and it's not available on PyPI, but you
can install it right from the github anyway.

The idea is to provide a yet another way to manage your test fixtures (that is, objects and
other resources you create usually before you start verifying an assertion.)

There are two popular ways to initialize fixtures in Python I'm aware of:

xUnit-style with setup/teardown methods. It is supported by the majority of
frameworks and looks like the most universal way to initialize testing
environment. Yet it's somewhat verbose and makes you either repeat yourself,
or develop extensive set of helper functions, or hierarchy of test classes,
or invent something else to ensure you keep DRY, and your tests are readable
and manageable.

py.test-style, when you inject dependencies in a test functions by passing
parameters in it. The py.test magic instantiates objects for you and calls a
test function by passing them as arguments. It's good, because it's reusable
and granular, but it's not very flexible: there is no easy way to pass
parameters to a py.test fixture function.

Now, there is another way to make the same. The approach we propose is
to create fixtures roughly the way we did it for py.test -- a function per
fixture, and to use it the way how the Michael Foord's mock manages
the lifespan of patches it applies -- with context managers, function decorators
or start/stop methods.

So, without further ado, a short usage example which explains better than
thousands of words. The library should work with py.test, nose or unittest.

# import global instancefromresourcesimportresources# register resource named "user" by defining a function with the same# name. The function must have exactly one "yield" construction and is# used both to set up and tear down the fixtures@resources.register_funcdefuser(email='joe@example.com',password='password',username='Joe'):user=User.objects.create(email=email,password=password,username=username)try:yielduserfinally:user.delete()# use resource with an automatically created "user_ctx" context managerdeftest_user_properties():withresources.user_ctx()asuser:# the resource will be available as an assignment target# of the "with"-constructionassertuser.username=='Joe'# it's also stored in the "resources" global objectassertresources.user.username=='Joe'# instances doesn't exist and isn't accessible anymoreassertnothasattr(resources,'user')

It's a very basic example, though. If you feel like it may be useful for you,
feel free to visit the github page and to read the README we created especially
for this purpose.