Package: django-attest
=============django-attest=============.. figure:: https://travis-ci.org/bradleyayers/django-tables2.pngAn alternative testing framework for Django, based on Attest.Attempts to provide a more Pythonic testing API than ``unittest``. Usefultesting features in recent version of Django have been included for use witholder version.Installation============Requires:- Django ≥1.2.- Attest >= 0.6 (use master)Use pip::pip install django-attestOn Django ≥1.3, a custom test runner can be used::TEST_RUNNER = "django_attest.Runner"Usage=====Create some tests, then run them (replace ``tests.settings`` with your own)::DJANGO_SETTINGS_MODULE=tests.settings attest -r djangoCreate a test collection and optionally include one of ``django-attest``'s testcontexts. The result is that a ``client`` argument is passed to each testwithin the collection. ``client`` is a ``django.test.TestClient`` object andallows you to make HTTP requests to your project.::from attest import Testsfrom django_attest import TestContexttests = Tests()tests.context(TestContext())@tests.testdef can_add(client):client.get('/some-url/')  # same as self.client.get() if you were using# django.test.TestCaseSee the `TestCase.client documentation`__ for more details... __: http://docs.djangoproject.com/en/1.3/topics/testing/#django.test.TestCase.clientWhen using a ``django.test.TestCase`` subclass, you're able to specify variousoptions 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:- ``fixtures`` -- http://docs.djangoproject.com/en/1.3/topics/testing/#django.test.TestCase.fixtures- ``urls`` -- http://docs.djangoproject.com/en/1.3/topics/testing/#django.test.TestCase.urls- ``client_class`` -- http://docs.djangoproject.com/en/1.3/topics/testing/#django.test.TestCase.client_class- ``multi_db`` -- http://docs.djangoproject.com/en/1.3/topics/testing/#django.test.TestCase.multi_dbFor example if you want to specify fixtures, urls, a client_class,or multi_db, simply passin these options when creating the ``django_tables.TestContext`` object::from attest import Testsfrom django_attest import TestContexttests = 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 Testsfrom django_attest import TransactionTestContexttests = Tests()tests.context(TransactionTestContext())@tests.testdef some_test(client):# test something...Testing a reusable Django app-----------------------------A flexible approach is to create a ``tests`` Django project. This shouldn't bethe fully-fledged output of ``django-admin.py startproject``, but instead theminimum required to keep Django happy.tests/__init__.py^^^^^^^^^^^^^^^^^::from attest import Testssuite = Tests()@suite.testdef example():assert len("abc") == 3Django's built-in test runner performs various environment initialisation andcleanup tasks. It's important that tests are run using one of the loaders fromdjango-attest.tests/settings.py^^^^^^^^^^^^^^^^^::DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': ':memory:',}}INSTALLED_APPS = ['django.contrib.sessions','django.contrib.auth','django.contrib.contenttypes','my_reusable_app',]SECRET_KEY = 'abcdefghiljklmnopqrstuvwxyz'ROOT_URLCONF = 'tests.urls'tests/urls.py^^^^^^^^^^^^^::from django.conf.urls import patternsurlpatterns = 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'sdocumentation <http://docs.djangoproject.com/en/1.3/topics/testing/#writing-unit-tests>`_for details).As of Attest 0.6 you should use test cases::# myapp/tests.pyfrom attest import Teststemplate = Tests()@template.testdef filter():# ...template = template.test_case()This allows Django to find your tests, and allows you to run individual tests,e.g.::python manage.py test myapp.template.test_filter.. note::When a ``unittest.TestCase`` is created from a test collection, thefunction names are prefixed with ``test_``.Prior to Attest 0.6, you must use the test suite option, which unfortunatelydoesn't support running individual tests::from attest import Teststemplate = Tests()@template.testdef filter():# ...suite = template.test_suiteassert hook-----------Since Django uses ``manage.py`` as its entry point, django-attest enables theassert 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/assertion.py``.redirects^^^^^^^^^Assert that a response redirects to some resource::from django_attest import redirectsresponse = client.get('/')redirects(response, url="http://example.com:8000/foo/?key=value#frag")redirects(response, scheme="http")redirects(response, domain="example.com")redirects(response, port="8000")redirects(response, path="/foo/")redirects(response, query="key=value")redirects(response, fragment="frag")Each component can only be asserted if it exists explicitly in the URL, e.g.with attest.raises(AssertionError):redirects(client.get('/'), port=80)  # port is rarely explicitqueries^^^^^^^Assert an expected set of queries took place::from django_attest import querieswith queries() as qs:User.objects.count()assert len(qs) == 5# The same could be rewritten aswith queries(count=5):User.objects.count()Context managers----------------django-attest has some context managers to simplify common tasks:settings(**settings)^^^^^^^^^^^^^^^^^^^^Change global settings within a block, same functionality as Django 1.4's``TestCase.settings``::from django_attest import settingswith settings(MEDIA_ROOT="/tmp"):# ...Code that's sensitive to settings changes should use the``django_attest.signals.setting_changed`` signal to overcome any assumptions ofsettings remaining constant... note::On Django >=1.4, ``django_attest.signals.setting_changed`` is an alias of``django.test.signals.setting_changed``.translation(language_code, deactivate=False)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Activate a specific translation/language. The semantics are the same as Django1.4's ``django.utils.translation.override``::from django_attest import translationfrom django.utils.translation import ugettextwith translation('de'):assert ugettext('the apple') == 'der Apfel'urlconf(patterns)^^^^^^^^^^^^^^^^^Takes a list of URL patterns and promotes them up as the root URLconf. Thisavoids the need to have a dedicated *test project* and ``urls.py`` for simplecases::@suite.testdef 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 ``urls.py``, use``settings(ROOT_URLCONF=...)`` instead, it takes care to clear URL resolvercaches.Backports---------- ``django_attest.RequestFactory`` (from Django 1.4)- ``django_attest.settings`` (``override_settings`` inspired from Django 1.4)- ``django_attest.translation`` (``django.utils.translation.override`` port from Django 1.4)Changelog=========v0.10.0-------- Add ``translation`` context manager- Add Travis CI testingv0.9.1------- Fix requirements for Attestv0.9.0------- 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-...``)v0.8.1------- Make test runner compatible with Python 2.6- Add support for Python 3.2v0.8.0------- Add test runner to show proper Attest formatting of assertion errors