skip to navigation
skip to content

django-attest 0.9.1

Provides Django specific testing helpers to Attest

Latest Version: 0.10.0

An alternative testing framework for Django, based on Attest.

Attempts to provide a more Pythonic testing API than unittest. Useful testing features in recent version of Django have been included for use with older version.



  • Django ≥1.2.
  • Attest >= 0.6 (use master)

Use pip:

pip install django-attest

On Django ≥1.3, a custom test runner can be used:

TEST_RUNNER = "django_attest.Runner"


Create some tests, then run them (replace tests.settings with your own):

DJANGO_SETTINGS_MODULE=tests.settings attest -r django

Create a test collection and optionally include one of django-attest’s test contexts. The result is that a client argument is passed to each test within the collection. client is a django.test.TestClient object and allows you to make HTTP requests to your project.

from attest import Tests
from django_attest import TestContext

tests = Tests()

def can_add(client):
    client.get('/some-url/')  # same as self.client.get() if you were using
                              # django.test.TestCase

See the TestCase.client documentation for more details.

When using a django.test.TestCase subclass, you’re able to specify various options that affect the environment in which your tests are executed. django-attest provides the same functionality via keyword arguments to the TestContext. The following keyword arguments are supported:

For example if you want to specify fixtures, urls, a client_class, or multi_db, simply pass in these options when creating the django_tables.TestContext object:

from attest import Tests
from django_attest import TestContext

tests = Tests()
tests.context(TestContext(fixtures=['testdata.json'], urls='myapp.urls'))

Transaction management in tests

If you need to test transaction management within your tests, use TransactionTestContext rather than TestContext, e.g.:

from attest import Tests
from django_attest import TransactionTestContext

tests = Tests()

def some_test(client):
    # test something

Testing a reusable Django app

A flexible approach is to create a tests Django project. This shouldn’t be the fully-fledged output of startproject, but instead the minimum required to keep Django happy.


from attest import Tests

suite = Tests()

def example():
    assert len("abc") == 3

Django’s built-in test runner performs various environment initialisation and cleanup tasks. It’s important that tests are run using one of the loaders from django-attest.


    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': ':memory:',


SECRET_KEY = 'abcdefghiljklmnopqrstuvwxyz'

ROOT_URLCONF = 'tests.urls'


from django.conf.urls import patterns
urlpatterns = patterns('')

Testing non-reusable apps in a Django project

To test non-reusable apps in a Django project, the app must contain either a tests or models module with either a suite function that returns a unittest.TestCase, or simply contains TestCase classes. (see Django’s documentation for details).

As of Attest 0.6 you should use test cases:

# myapp/
from attest import Tests

template = Tests()

def filter():
    # ...

template = template.test_case()

This allows Django to find your tests, and allows you to run individual tests, e.g.:

python test myapp.template.test_filter


When a unittest.TestCase is created from a test collection, the function names are prefixed with test_.

Prior to Attest 0.6, you must use the test suite option, which unfortunately doesn’t support running individual tests:

from attest import Tests

template = Tests()

def filter():
    # ...

suite = template.test_suite

assert hook

Since Django uses as its entry point, django-attest enables the assert hook automatically when it’s first imported.

This means that you need to do the following:

  1. Make sure django_attest is imported as soon as possible.
  2. Add from attest import assert_hook to the top of each test module.

Django assertions

For details on each of these, see django_attest/


Assert that a response redirects to some resource:

from django_attest import redirects

response = client.get('/')
redirects(response, path="/foo/")


Assert an expected set of queries took place:

from django_attest import queries

with queries() as qs:
assert len(qs) == 5

# The same could be rewritten as
with queries(count=5):

Context managers

django-attest has some context managers to simplify common tasks:


Change global settings within a block, same functionality as Django 1.4’s TestCase.settings:

from django_attest import settings

with settings(MEDIA_ROOT="/tmp"):
    # ...

Code that’s sensitive to settings changes should use the django_attest.signals.setting_changed signal to overcome any assumptions of settings remaining constant.


On Django >=1.4, django_attest.signals.setting_changed is an alias of django.test.signals.setting_changed.


Takes a list of URL patterns and promotes them up as the root URLconf. This avoids the need to have a dedicated test project and for simple cases:

def foo(client):
    def view(request):
        return HttpResponse('success')

    urls = patterns('', (r'view/', view))
    with urlconf(urls):
        assert client.get(reverse(view)).content == 'success'

If you want to provide a dotted path to a, use settings(ROOT_URLCONF=...) instead, it takes care to clear URL resolver caches.


  • django_attest.RequestFactory (from Django 1.4)
  • django_attest.settings (override_settings inspired from Django 1.4)



  • Fix requirements for Attest


  • Setting up the Django environment is no longer part of the distuils loader, rather it’s builtin to the django-attest reporters.
  • Declare reporter entry points (named django-...)


  • Make test runner compatible with Python 2.6
  • Add support for Python 3.2


  • Add test runner to show proper Attest formatting of assertion errors
File Type Py Version Uploaded on Size
django-attest-0.9.1.tar.gz (md5) Source 2012-10-18 9KB
  • Downloads (All Versions):
  • 1 downloads in the last day
  • 299 downloads in the last week
  • 1686 downloads in the last month