Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

*Finally* edited docs/testing.txt

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5889 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 1ba9012d873ad2372ee39cf1afe64f366ecefb65 1 parent 543ab12
@adrianholovaty adrianholovaty authored
Showing with 659 additions and 409 deletions.
  1. +659 −409 docs/testing.txt
View
1,068 docs/testing.txt
@@ -22,6 +22,9 @@ it should be doing.
The best part is, it's really easy.
+This document is split into two primary sections. First, we explain how to
+write tests with Django. Then, we explain how to run them.
+
.. admonition:: Note
This testing framework is currently under development. It may change
@@ -32,35 +35,81 @@ The best part is, it's really easy.
Writing tests
=============
-Tests in Django come in two forms: doctests and unit tests.
+There are two primary ways to write tests with Django, corresponding to the
+two test frameworks that ship in the Python standard library. The two
+frameworks are:
+
+ * **Doctests** -- tests that are embedded in your functions' docstrings and
+ are written in a way that emulates a session of the Python interactive
+ interpreter. For example::
+
+ def my_func(a_list, idx):
+ """
+ >>> a = ['larry', 'curly', 'moe']
+ >>> my_func(a, 0)
+ 'larry'
+ >>> my_func(a, 1)
+ 'curly'
+ """
+ return a_list[idx]
+
+ * **Unit tests** -- tests that are expressed as methods on a Python class
+ that subclasses ``unittest.TestCase``. For example::
+
+ import unittest
+
+ class MyFuncTestCase(unittest.TestCase)
+ def testBasic(self):
+ a = ['larry', 'curly', 'moe']
+ self.assertEquals(my_func(a, 0), 'larry')
+ self.assertEquals(my_func(a, 1), 'curly')
+
+You can choose the test framework you like, depending on which syntax you
+prefer, or you can mix and match, using one framework for some of your code and
+the other framework for other code. You can also use any *other* Python test
+frameworks, as we'll explain in a bit.
Writing doctests
----------------
-Doctests use Python's standard doctest_ module, which searches for tests in
-your docstrings. Django's test runner looks for doctests in your ``models.py``
-file, and executes any that it finds. Django will also search for a file
-called ``tests.py`` in the application directory (i.e., the directory that
-holds ``models.py``). If a ``tests.py`` is found, it will also be searched
-for doctests.
+Doctests use Python's standard doctest_ module, which searches your docstrings
+for statements that resemble a session of the Python interactive interpreter.
+A full explanation of how doctest works is out of the scope of this document;
+read Python's official documentation for the details.
.. admonition:: What's a **docstring**?
- A good explanation of docstrings (and some guidlines for using them
+ A good explanation of docstrings (and some guidelines for using them
effectively) can be found in :PEP:`257`:
A docstring is a string literal that occurs as the first statement in
a module, function, class, or method definition. Such a docstring
becomes the ``__doc__`` special attribute of that object.
- Since tests often make great documentation, doctest lets you put your
- tests directly in your docstrings.
+ For example, this function has a docstring that describes what it does::
+
+ def add_two(num):
+ "Adds 2 to the given number and returns the result."
+ return num + 2
-You can put doctest strings on any object in your ``models.py``, but it's
-common practice to put application-level doctests in the module docstring, and
-model-level doctests in the docstring for each model.
+ Because tests often make great documentation, putting tests directly in
+ your docstrings is an effective way to document *and* test your code.
-For example::
+For a given Django application, the test runner looks for doctests in two
+places:
+
+ * The ``models.py`` file. You can define module-level doctests and/or a
+ doctest for individual models. It's common practice to put
+ application-level doctests in the module docstring and model-level
+ doctests in the model docstrings.
+
+ * A file called ``tests.py`` in the application directory -- i.e., the
+ directory that holds ``models.py``. This file is a hook for any and all
+ doctests you want to write that aren't necessarily related to models.
+
+Here is an example model doctest::
+
+ # models.py
from django.db import models
@@ -78,38 +127,53 @@ For example::
>>> cat.speak()
'The cat says "meow"'
"""
-
name = models.CharField(max_length=20)
sound = models.CharField(max_length=20)
def speak(self):
return 'The %s says "%s"' % (self.name, self.sound)
-When you `run your tests`_, the test utility will find this docstring, notice
+When you `run your tests`_, the test runner will find this docstring, notice
that portions of it look like an interactive Python session, and execute those
lines while checking that the results match.
+In the case of model tests, note that the test runner takes care of creating
+its own test database. That is, any test that accesses a database -- by
+creating and saving model instances, for example -- will not affect your
+production database. Each doctest begins with a "blank slate" -- a fresh
+database containing an empty table for each model. (See the section on
+fixtures, below, for more on this.)
+
For more details about how doctest works, see the `standard library
documentation for doctest`_
.. _doctest: http://docs.python.org/lib/module-doctest.html
.. _standard library documentation for doctest: doctest_
-Writing unittests
------------------
+Writing unit tests
+------------------
Like doctests, Django's unit tests use a standard library module: unittest_.
-As with doctests, Django's test runner looks for any unit test cases defined
-in ``models.py``, or in a ``tests.py`` file stored in the application
-directory.
+This module uses a different way of defining tests, taking a class-based
+approach.
-An equivalent unittest test case for the above example would look like::
+As with doctests, for a given Django application, the test runner looks for
+unit tests in two places:
+
+ * The ``models.py`` file. The test runner looks for any subclass of
+ ``unittest.TestCase`` in this module.
+
+ * A file called ``tests.py`` in the application directory -- i.e., the
+ directory that holds ``models.py``. Again, the test runner looks for any
+ subclass of ``unittest.TestCase`` in this module.
+
+This example ``unittest.TestCase`` subclass is equivalent to the example given
+in the doctest section above::
import unittest
from myapp.models import Animal
class AnimalTestCase(unittest.TestCase):
-
def setUp(self):
self.lion = Animal.objects.create(name="lion", sound="roar")
self.cat = Animal.objects.create(name="cat", sound="meow")
@@ -123,13 +187,12 @@ to find all the test cases (that is, subclasses of ``unittest.TestCase``)
in ``models.py`` and ``tests.py``, automatically build a test suite out of
those test cases, and run that suite.
-**New in Django development version**
-
-However, if you define a method called ``suite()`` in either ``models.py`` or
-``tests.py``, that method will be used to construct the test suite for that
-module. This follows the `suggested organization`_ for unit tests. See the
-Python documentation for more details on how to construct a complex test
-suite.
+In the Django development version, there is a second way to define the test
+suite for a module: if you define a function called ``suite()`` in either
+``models.py`` or ``tests.py``, the Django test runner will use that function
+to construct the test suite for that module. This follows the
+`suggested organization`_ for unit tests. See the Python documentation for
+more details on how to construct a complex test suite.
For more details about ``unittest``, see the `standard library unittest
documentation`_.
@@ -142,304 +205,541 @@ documentation`_.
Which should I use?
-------------------
-Choosing a test framework is often contentious, so Django simply supports
-both of the standard Python test frameworks. Choosing one is up to each
-developer's personal tastes; each is supported equally. Since each test
-system has different benefits, the best approach is probably to use both
-together, picking the test system to match the type of tests you need to
-write.
-
-For developers new to testing, however, this choice can seem
-confusing, so here are a few key differences to help you decide whether
-doctests or unit tests are right for you.
-
-If you've been using Python for a while, ``doctest`` will probably feel more
-"pythonic". It's designed to make writing tests as easy as possible, so
-there's no overhead of writing classes or methods; you simply put tests in
-docstrings. This gives the added advantage of giving your modules automatic
-documentation -- well-written doctests can kill both the documentation and the
-testing bird with a single stone.
-
-For developers just getting started with testing, using doctests will probably
-get you started faster.
-
-The ``unittest`` framework will probably feel very familiar to developers
-coming from Java. Since ``unittest`` is inspired by Java's JUnit, if
-you've used testing frameworks in other languages that similarly were
-inspired by JUnit, ``unittest`` should also feel pretty familiar.
-
-Since ``unittest`` is organized around classes and methods, if you need
-to write a bunch of tests that all share similar code, you can easily use
-subclass to abstract common tasks; this makes test code shorter and cleaner.
-There's also support for explicit setup and/or cleanup routines, which give
-you a high level of control over the environment your test cases run in.
+Because Django supports both of the standard Python test frameworks, it's up to
+you and your tastes to decide which one to use. You can even decide to use
+*both*.
+
+For developers new to testing, however, this choice can seem confusing. Here,
+then, are a few key differences to help you decide which approach is right for
+you:
+
+ * If you've been using Python for a while, ``doctest`` will probably feel
+ more "pythonic". It's designed to make writing tests as easy as possible,
+ so it requires no overhead of writing classes or methods. You simply put
+ tests in docstrings. This has the added advantage of serving as
+ documentation (and correct documentation, at that!).
+
+ If you're just getting started with testing, using doctests will probably
+ get you started faster.
+
+ * The ``unittest`` framework will probably feel very familiar to developers
+ coming from Java. ``unittest`` is inspired by Java's JUnit, so you'll
+ feel at home with this method if you've used JUnit or any test framework
+ inspired by JUnit.
+
+ * If you need to write a bunch of tests that share similar code, then
+ you'll appreciate the ``unittest`` framework's organization around
+ classes and methods. This makes it easy to abstract common tasks into
+ common methods. The framework also supports explicit setup and/or cleanup
+ routines, which give you a high level of control over the environment
+ in which your test cases are run.
Again, remember that you can use both systems side-by-side (even in the same
-app). In the end, most projects will eventually end up using both; each shines
+app). In the end, most projects will eventually end up using both. Each shines
in different circumstances.
-Testing Tools
+Running tests
+=============
+
+Once you've written tests, run them using your project's ``manage.py`` utility::
+
+ $ ./manage.py test
+
+By default, this will run every test in every application in ``INSTALLED_APPS``.
+If you only want to run tests for a particular application, add the
+application name to the command line. For example, if your ``INSTALLED_APPS``
+contains ``'myproject.polls'`` and ``'myproject.animals'``, you can run the
+``myproject.animals`` unit tests alone with this command::
+
+ # ./manage.py test animals
+
+Note that we used ``animals``, not ``myproject.animals``.
+
+**New in Django development version:** If you use unit tests, as opposed to
+doctests, you can be even *more* specific in choosing which tests to execute.
+To run a single test case in an application (for example, the
+``AnimalTestCase`` described in the "Writing unit tests" section), add the
+name of the test case to the label on the command line::
+
+ $ ./manage.py test animals.AnimalTestCase
+
+And it gets even more granular than that! To run a *single* test method inside
+a test case, add the name of the test method to the label::
+
+ $ ./manage.py test animals.AnimalTestCase.testFluffyAnimals
+
+Understanding the test output
+-----------------------------
+
+When you run your tests, you'll see a number of messages as the test runner
+prepares itself::
+
+ Creating test database...
+ Creating table myapp_animal
+ Creating table myapp_mineral
+ Loading 'initial_data' fixtures...
+ No fixtures found.
+
+This tells you that the test runner is creating a test database -- a blank,
+from-scratch database that it will use for any tests that happen to require a
+database (namely, model tests).
+
+Don't worry -- the test runner will not touch your "real" (production)
+database. It creates a separate database purely for the tests. This test
+database gets its name by prepending ``test_`` to the value of the
+``DATABASE_NAME`` setting. If you want to use a different name, specify the
+``TEST_DATABASE_NAME`` setting.
+
+Aside from using a separate database, the test runner will otherwise use all of
+the same database settings you have in your settings file: ``DATABASE_ENGINE``,
+``DATABASE_USER``, ``DATABASE_HOST``, etc. The test database is created by the
+user specified by ``DATABASE_USER``, so you'll need to make sure that the given
+user account has sufficient privileges to create a new database on the system.
+
+**New in Django development version:** For fine-grained control over the
+character encoding of your test database, use the ``TEST_DATABASE_CHARSET``
+setting. If you're using MySQL, you can also use the ``TEST_DATABASE_COLLATION``
+setting to control the particular collation used by the test database. See the
+settings_ documentation for details of these advanced settings.
+
+.. _settings: ../settings/
+
+Once the test database has been created, Django will run your tests.
+If everything goes well, you'll see something like this::
+
+ ----------------------------------------------------------------------
+ Ran 22 tests in 0.221s
+
+ OK
+
+If there are test failures, however, you'll see full details about which tests
+failed::
+
+ ======================================================================
+ FAIL: Doctest: ellington.core.throttle.models
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ File "/dev/django/test/doctest.py", line 2153, in runTest
+ raise self.failureException(self.format_failure(new.getvalue()))
+ AssertionError: Failed doctest test for myapp.models
+ File "/dev/myapp/models.py", line 0, in models
+
+ ----------------------------------------------------------------------
+ File "/dev/myapp/models.py", line 14, in myapp.models
+ Failed example:
+ throttle.check("actor A", "action one", limit=2, hours=1)
+ Expected:
+ True
+ Got:
+ False
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in 0.048s
+
+ FAILED (failures=1)
+
+A full explanation of this error output is beyond the scope of this document,
+but it's pretty intuitive. You can consult the documentation of Python's
+``unittest`` library for details.
+
+Note that the return code for the test-runner script is the total number of
+failed and erroneous tests. If all the tests pass, the return code is 0. This
+feature is useful if you're using the test-runner script in a shell script and
+need to test for success or failure at that level.
+
+Regardless of whether the tests pass or fail, the test database is destroyed when
+all the tests have been executed.
+
+Testing tools
=============
-To assist in testing various features of your application, Django provides
-tools that can be used to establish tests and test conditions.
+Django provides a small set of tools that come in handy when writing tests.
+
+The test client
+---------------
+
+The test client is a Python class that acts as a dummy Web browser, allowing
+you to test your views and interact with your Django-powered application
+programatically.
-* `Test Client`_
-* `TestCase`_
-* `E-mail services`_
+Some of the things you can do with the test client are:
-Test Client
------------
+ * Simulate GET and POST requests on a URL and observe the response --
+ everything from low-level HTTP (result headers and status codes) to
+ page content.
-The Test Client is a simple dummy browser. It allows you to simulate
-GET and POST requests on a URL, and observe the response that is received.
-This allows you to test that the correct view is executed for a given URL,
-and that the view constructs the correct response.
+ * Test that the correct view is executed for a given URL.
-As the response is generated, the Test Client gathers details on the
-Template and Context objects that were used to generate the response. These
-Templates and Contexts are then provided as part of the response, and can be
-used as test conditions.
+ * Test that a given request is rendered by a given Django template, with
+ a template context that contains certain values.
-.. admonition:: Test Client vs Browser Automation?
+Note that the test client is not intended to be a replacement for Twill_,
+Selenium_, or other "in-browser" frameworks. Django's test client has
+a different focus. In short:
- The Test Client is not intended as a replacement for Twill_, Selenium_,
- or other browser automation frameworks - it is intended to allow
- testing of the contexts and templates produced by a view,
- rather than the HTML rendered to the end-user.
+ * Use Django's test client to establish that the correct view is being
+ called and that the view is collecting the correct context data.
- A comprehensive test suite should use a combination of both: Test Client
- tests to establish that the correct view is being called and that
- the view is collecting the correct context data, and Browser Automation
- tests to check that user interface behaves as expected.
+ * Use in-browser frameworks such as Twill and Selenium to test *rendered*
+ HTML and the *behavior* of Web pages, namely JavaScript functionality.
+
+A comprehensive test suite should use a combination of both test types.
.. _Twill: http://twill.idyll.org/
.. _Selenium: http://www.openqa.org/selenium/
+Overview and a quick example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To use the test client, instantiate ``django.test.client.Client`` and retrieve
+Web pages::
+
+ >>> from django.test.client import Client
+ >>> c = Client()
+ >>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
+ >>> response.status_code
+ 200
+ >>> response = c.get('/customer/details/')
+ >>> response.content
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...'
+
+As this example suggests, you can instantiate ``Client`` from within a session
+of the Python interactive interpreter.
+
+Note a few important things about how the test client works:
+
+ * The test client does *not* require the Web server to be running. In fact,
+ it will run just fine with no Web server running at all! That's because
+ it avoids the overhead of HTTP and deals directly with the Django
+ framework. This helps make the unit tests run quickly.
+
+ * When retrieving pages, remember to specify the *path* of the URL, not the
+ whole domain. For example, this is correct::
+
+ >>> c.get('/login/')
+
+ This is incorrect::
+
+ >>> c.get('http://www.example.com/login/')
+
+ The test client is not capable of retrieving Web pages that are not
+ powered by your Django project. If you need to retrieve other Web pages,
+ use a Python standard library module such as urllib_ or urllib2_.
+
+ * To resolve URLs, the test client uses whatever URLconf is pointed-to by
+ your ``ROOT_URLCONF`` setting.
+
+ * Although the above example would work in the Python interactive
+ interpreter, some of the test client's functionality, notably the
+ template-related functionality, is only available *while tests are running*.
+
+ The reason for this is that Django's test runner performs a bit of black
+ magic in order to determine which template was loaded by a given view.
+ This black magic (essentially a patching of Django's template system in
+ memory) only happens during test running.
+
+.. _urllib: http://docs.python.org/lib/module-urllib.html
+.. _urllib2: http://docs.python.org/lib/module-urllib2.html
+
Making requests
~~~~~~~~~~~~~~~
-Creating an instance of ``Client`` (``django.test.client.Client``) requires
-no arguments at time of construction. Once constructed, the following methods
-can be invoked on the ``Client`` instance.
+Use the ``django.test.client.Client`` class to make requests. It requires no
+arguments at time of construction::
+
+ >>> c = Client()
+
+Once you have a ``Client`` instance, you can call any of the following methods:
``get(path, data={})``
- Make a GET request on the provided ``path``. The key-value pairs in the
- data dictionary will be used to create a GET data payload. For example::
+ Makes a GET request on the provided ``path`` and returns a ``Response``
+ object, which is documented below.
- c = Client()
- c.get('/customers/details/', {'name':'fred', 'age':7})
+ The key-value pairs in the ``data`` dictionary are used to create a GET
+ data payload. For example::
- will result in the evaluation of a GET request equivalent to::
+ >>> c = Client()
+ >>> c.get('/customers/details/', {'name': 'fred', 'age': 7})
- http://yoursite.com/customers/details/?name=fred&age=7
+ ...will result in the evaluation of a GET request equivalent to::
+
+ /customers/details/?name=fred&age=7
``post(path, data={}, content_type=MULTIPART_CONTENT)``
- Make a POST request on the provided ``path``. If you provide a content type
- (e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be
- sent as-is in the POST request, using the content type in the HTTP
- ``Content-Type`` header.
+ Makes a POST request on the provided ``path`` and returns a ``Response``
+ object, which is documented below.
+
+ The key-value pairs in the ``data`` dictionary are used to submit POST
+ data. For example::
+
+ >>> c = Client()
+ >>> c.get('/login/', {'name': 'fred', 'passwd': 'secret'})
+
+ ...will result in the evaluation of a POST request to this URL::
+
+ /login/
- If you do not provide a value for ``content_type``, the values in
+ ...with this POST data::
+
+ name=fred&passwd&secret
+
+ If you provide ``content_type`` (e.g., ``text/xml`` for an XML payload),
+ the contents of ``data`` will be sent as-is in the POST request, using
+ ``content_type`` in the HTTP ``Content-Type`` header.
+
+ If you don't provide a value for ``content_type``, the values in
``data`` will be transmitted with a content type of ``multipart/form-data``.
- The key-value pairs in the data dictionary will be encoded as a multipart
- message and used to create the POST data payload.
-
- To submit multiple values for a given key (for example, to specify
- the selections for a multiple selection list), provide the values as a
- list or tuple for the required key. For example, a data dictionary of
- ``{'choices': ('a','b','d')}`` would submit three selected rows for the
- field named ``choices``.
-
- Submitting files is a special case. To POST a file, you need only
- provide the file field name as a key, and a file handle to the file you wish to
- upload as a value. The Test Client will populate the two POST fields (i.e.,
- ``field`` and ``field_file``) required by Django's FileField. For example::
-
- c = Client()
- f = open('wishlist.doc')
- c.post('/customers/wishes/', {'name':'fred', 'attachment':f})
- f.close()
-
- will result in the evaluation of a POST request on ``/customers/wishes/``,
- with a POST dictionary that contains ``name``, ``attachment`` (containing the
- file name), and ``attachment_file`` (containing the file data). Note that you
- need to manually close the file after it has been provided to the POST.
+ In this case, the key-value pairs in ``data`` will be encoded as a
+ multipart message and used to create the POST data payload.
+
+ To submit multiple values for a given key -- for example, to specify
+ the selections for a ``<select multiple>`` -- provide the values as a
+ list or tuple for the required key. For example, this value of ``data``
+ would submit three selected values for the field named ``choices``::
+
+ {'choices': ('a', 'b', 'd')}
+
+ Submitting files is a special case. To POST a file, you need only provide
+ the file field name as a key, and a file handle to the file you wish to
+ upload as a value. For example::
+
+ >>> c = Client()
+ >>> f = open('wishlist.doc')
+ >>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f})
+ >>> f.close()
+
+ (The name ``attachment`` here is not relevant; use whatever name your
+ file-processing code expects.)
+
+ Note that you should manually close the file after it has been provided to
+ ``post()``.
``login(**credentials)``
**New in Django development version**
- On a production site, it is likely that some views will be protected from
- anonymous access through the use of the @login_required decorator, or some
- other login checking mechanism. The ``login()`` method can be used to
- simulate the effect of a user logging into the site. As a result of calling
- this method, the Client will have all the cookies and session data required
- to pass any login-based tests that may form part of a view.
+ If your site uses Django's `authentication system`_ and you deal with
+ logging in users, you can use the test client's ``login()`` method to
+ simulate the effect of a user logging into the site.
+
+ After you call this method, the test client will have all the cookies and
+ session data required to pass any login-based tests that may form part of
+ a view.
- In most cases, the ``credentials`` required by this method are the username
- and password of the user that wants to log in, provided as keyword
- arguments::
+ The format of the ``credentials`` argument depends on which
+ `authentication backend`_ you're using (which is configured by your
+ ``AUTHENTICATION_BACKENDS`` setting). If you're using the standard
+ authentication backend provided by Django (``ModelBackend``),
+ ``credentials`` should be the user's username and password, provided as
+ keyword arguments::
- c = Client()
- c.login(username='fred', password='secret')
- # Now you can access a login protected view
+ >>> c = Client()
+ >>> c.login(username='fred', password='secret')
+ >>> # Now you can access a view that's only available to logged-in users.
- If you are using a different authentication backend, this method may
- require different credentials.
+ If you're using a different authentication backend, this method may require
+ different credentials. It requires whichever credentials are required by
+ your backend's ``authenticate()`` method.
``login()`` returns ``True`` if it the credentials were accepted and login
was successful.
- Note that since the test suite will be executed using the test database,
- which contains no users by default. As a result, logins that are valid
- on your production site will not work under test conditions. You will
- need to create users as part of the test suite (either manually, or
- using a test fixture).
+ Finally, you'll need to remember to create user accounts before you can use
+ this method. As we explained above, the test runner is executed using a
+ test database, which contains no users by default. As a result, user
+ accounts that are valid on your production site will not work under test
+ conditions. You'll need to create users as part of the test suite -- either
+ manually (using the Django model API) or with a test fixture.
-Testing Responses
+.. _authentication system: ../authentication/
+.. _authentication backend: ../authentication/#other-authentication-sources
+
+Testing responses
~~~~~~~~~~~~~~~~~
-The ``get()`` and ``post()`` methods both return a Response object. This
-Response object has the following properties that can be used for testing
-purposes:
+The ``get()`` and ``post()`` methods both return a ``Response`` object. This
+``Response`` object is *not* the same as the ``HttpResponse`` object returned
+Django views; this object is simpler and has some additional data useful for
+tests.
+
+Specifically, a ``Response`` object has the following attributes::
=============== ==========================================================
- Property Description
+ Attribute Description
=============== ==========================================================
- ``status_code`` The HTTP status of the response. See RFC2616_ for a
- full list of HTTP status codes.
-
- ``content`` The body of the response. This is the final page
- content as rendered by the view, or any error message
- (such as the URL for a 302 redirect).
-
- ``template`` The Template instance that was used to render the final
- content. Testing ``template.name`` can be particularly
- useful; if the template was loaded from a file,
- ``template.name`` will be the file name that was loaded.
-
- If multiple templates were rendered, (e.g., if one
- template includes another template),``template`` will
- be a list of Template objects, in the order in which
- they were rendered.
-
- ``context`` The Context that was used to render the template that
- produced the response content.
-
- As with ``template``, if multiple templates were rendered
- ``context`` will be a list of Context objects, stored in
- the order in which they were rendered.
+ ``status_code`` The HTTP status of the response, as an integer. See
+ RFC2616_ for a full list of HTTP status codes.
+
+ ``content`` The body of the response, as a string. This is the final
+ page content as rendered by the view, or any error
+ message (such as the URL for a 302 redirect).
+
+ ``template`` The ``Template`` instance that was used to render the
+ final content. Use ``template.name`` to get the
+ template's file name, if the template was loaded from a
+ file. (The name is a string such as
+ ``'admin/index.html'``.)
+
+ If the rendered page used multiple templates -- e.g.,
+ using `template inheritance`_ -- then ``template`` will
+ be a list of ``Template`` instances, in the order in
+ which they were rendered.
+
+ ``context`` The template ``Context`` instance that was used to render
+ the template that produced the response content.
+
+ As with ``template``, if the rendered page used multiple
+ templates, then ``context`` will be a list of ``Context``
+ objects, in the order in which they were rendered.
=============== ==========================================================
.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+.. _template inheritance: ../templates/#template-inheritance
Exceptions
~~~~~~~~~~
-If you point the Test Client at a view that raises an exception, that exception
+If you point the test client at a view that raises an exception, that exception
will be visible in the test case. You can then use a standard ``try...catch``
-block, or ``unittest.TestCase.assertRaises()`` to test for exceptions.
+block or ``unittest.TestCase.assertRaises()`` to test for exceptions.
-The only exceptions that are not visible in a Test Case are ``Http404``,
+The only exceptions that are not visible to the test client are ``Http404``,
``PermissionDenied`` and ``SystemExit``. Django catches these exceptions
-internally and converts them into the appropriate HTTP responses codes.
+internally and converts them into the appropriate HTTP response codes. In these
+cases, you can check ``response.status_code`` in your test.
Persistent state
~~~~~~~~~~~~~~~~
-The Test Client is stateful; if a cookie is returned as part of a response,
-that cookie is provided as part of the next request issued by that Client
-instance. Expiry policies for these cookies are not followed; if you want
-a cookie to expire, either delete it manually or create a new Client
-instance (which will effectively delete all cookies).
+The test client is stateful. If a response returns a cookie, then that cookie
+will be stored in the test client and sent with all subsequent ``get()`` and
+``post()`` requests.
-There are two properties of the Test Client which are used to store persistent
-state information. If necessary, these properties can be interrogated as
-part of a test condition.
+Expiration policies for these cookies are not followed. If you want a cookie
+to expire, either delete it manually or create a new ``Client`` instance (which
+will effectively delete all cookies).
+
+A test client has two attributes that store persistent state information. You
+can access these properties as part of a test condition.
=============== ==========================================================
- Property Description
+ Attribute Description
=============== ==========================================================
``cookies`` A Python ``SimpleCookie`` object, containing the current
- values of all the client cookies.
+ values of all the client cookies. See the
+ `Cookie module documentation`_ for more.
``session`` A dictionary-like object containing session information.
See the `session documentation`_ for full details.
=============== ==========================================================
-.. _`session documentation`: ../sessions/
+.. _Cookie module documentation: http://docs.python.org/lib/module-Cookie.html
+.. _session documentation: ../sessions/
Example
~~~~~~~
-The following is a simple unit test using the Test Client::
+The following is a simple unit test using the test client::
import unittest
from django.test.client import Client
class SimpleTest(unittest.TestCase):
def setUp(self):
- # Every test needs a client
+ # Every test needs a client.
self.client = Client()
+
def test_details(self):
- # Issue a GET request
+ # Issue a GET request.
response = self.client.get('/customer/details/')
- # Check that the respose is 200 OK
+ # Check that the respose is 200 OK.
self.failUnlessEqual(response.status_code, 200)
- # Check that the rendered context contains 5 customers
+
+ # Check that the rendered context contains 5 customers.
self.failUnlessEqual(len(response.context['customers']), 5)
TestCase
--------
-Normal python unit tests extend a base class of ``unittest.testCase``.
-Django provides an extension of this base class - ``django.test.TestCase``
-- that provides some additional capabilities that can be useful for
-testing web sites.
+Normal Python unit test classes extend a base class of ``unittest.TestCase``.
+Django provides an extension of this base class -- ``django.test.TestCase``
+-- that provides some additional capabilities that can be useful for
+testing Web sites.
-Moving from a normal unittest TestCase to a Django TestCase is easy - just
-change the base class of your test from ``unittest.TestCase`` to
-``django.test.TestCase``. All of the standard Python unit test facilities
-will continue to be available, but they will be augmented with some useful
-extra facilities.
+Converting a normal ``unittest.TestCase`` to a Django ``TestCase`` is easy:
+just change the base class of your test from ``unittest.TestCase`` to
+``django.test.TestCase``. All of the standard Python unit test functionality
+will continue to be available, but it will be augmented with some useful
+additions.
-Default Test Client
+Default test client
~~~~~~~~~~~~~~~~~~~
+
**New in Django development version**
Every test case in a ``django.test.TestCase`` instance has access to an
-instance of a Django `Test Client`_. This Client can be accessed as
-``self.client``. This client is recreated for each test.
+instance of a Django test client. This client can be accessed as
+``self.client``. This client is recreated for each test, so you don't have to
+worry about state (such as cookies) carrying over from one test to another.
+
+This means, instead of instantiating a ``Client`` in each test::
+
+ import unittest
+ from django.test.client import Client
+
+ class SimpleTest(unittest.TestCase):
+ def test_details(self):
+ client = Client()
+ response = client.get('/customer/details/')
+ self.failUnlessEqual(response.status_code, 200)
+
+ def test_index(self):
+ client = Client()
+ response = client.get('/customer/index/')
+ self.failUnlessEqual(response.status_code, 200)
+
+...you can just refer to ``self.client``, like so::
+
+ from django.test import TestCase
+ from django.test.client import Client
+
+ class SimpleTest(TestCase):
+ def test_details(self):
+ response = self.client.get('/customer/details/')
+ self.failUnlessEqual(response.status_code, 200)
+
+ def test_index(self):
+ response = self.client.get('/customer/index/')
+ self.failUnlessEqual(response.status_code, 200)
Fixture loading
~~~~~~~~~~~~~~~
-A test case for a database-backed website isn't much use if there isn't any
+A test case for a database-backed Web site isn't much use if there isn't any
data in the database. To make it easy to put test data into the database,
-Django provides a fixtures framework.
+Django's custom ``TestCase`` class provides a way of loading **fixtures**.
-A *Fixture* is a collection of files that contain the serialized contents of
-the database. Each fixture has a unique name; however, the files that
-comprise the fixture can be distributed over multiple directories, in
-multiple applications.
+A fixture is a collection of data that Django knows how to import into a
+database. For example, if your site has user accounts, you might set up a
+fixture of fake user accounts in order to populate your database during tests.
+
+The most straightforward way of creating a fixture is to use the
+``manage.py dumpdata`` command. This assumes you already have some data in
+your database. See the `dumpdata documentation`_ for more details.
.. note::
- If you have synchronized a Django project, you have already experienced
- the use of one fixture -- the ``initial_data`` fixture. Every time you
- synchronize the database, Django installs the ``initial_data`` fixture.
- This provides a mechanism to populate a new database with any initial
- data (such as a default set of categories). Fixtures with other names
- can be installed manually using ``django-admin.py loaddata``.
-
-However, for the purposes of unit testing, each test must be able to
-guarantee the contents of the database at the start of each and every
-test.
-
-To define a fixture for a test, all you need to do is add a class
-attribute to your test describing the fixtures you want the test to use.
-For example, the test case from `Writing unittests`_ would
-look like::
+ If you've ever run ``manage.py syncdb``, you've already used a fixture
+ without even knowing it! When you call ``syncdb`` in the database for
+ the first time, Django installs a fixture called ``initial_data``.
+ This gives you a way of populating a new database with any initial data,
+ such as a default set of categories.
+
+ Fixtures with other names can always be installed manually using the
+ ``manage.py loaddata`` command.
+
+Once you've created a fixture and placed it somewhere in your Django project,
+you can use it in your unit tests by specifying a ``fixtures`` class attribute
+on your ``django.test.TestCase`` subclass::
from django.test import TestCase
from myapp.models import Animal
@@ -448,260 +748,205 @@ look like::
fixtures = ['mammals.json', 'birds']
def setUp(self):
- # test definitions as before
+ # Test definitions as before.
def testFluffyAnimals(self):
- # A test that uses the fixtures
+ # A test that uses the fixtures.
-At the start of each test case, before ``setUp()`` is run, Django will
-flush the database, returning the database the state it was in directly
-after ``syncdb`` was called. Then, all the named fixtures are installed.
-In this example, any JSON fixture called ``mammals``, and any fixture
-named ``birds`` will be installed. See the documentation on
-`loading fixtures`_ for more details on defining and installing fixtures.
+Here's specifically what will happen:
-.. _`loading fixtures`: ../django-admin/#loaddata-fixture-fixture
+ * At the start of each test case, before ``setUp()`` is run, Django will
+ flush the database, returning the database to the state it was in
+ directly after ``syncdb`` was called.
+
+ * Then, all the named fixtures are installed. In this example, Django will
+ install any JSON fixture named ``mammals``, followed by any fixture named
+ ``birds``. See the `loaddata documentation`_ for more details on defining
+ and installing fixtures.
This flush/load procedure is repeated for each test in the test case, so you
can be certain that the outcome of a test will not be affected by
-another test, or the order of test execution.
+another test, or by the order of test execution.
+
+.. _dumpdata documentation: ../django-admin/#dumpdata-appname-appname
+.. _loaddata documentation: ../django-admin/#loaddata-fixture-fixture
Emptying the test outbox
~~~~~~~~~~~~~~~~~~~~~~~~
+
**New in Django development version**
-At the start of each test case, in addition to installing fixtures,
-Django clears the contents of the test e-mail outbox.
+If you use Django's custom ``TestCase`` class, the test runner will clear the
+contents of the test e-mail outbox at the start of each test case.
For more detail on e-mail services during tests, see `E-mail services`_.
Assertions
~~~~~~~~~~
+
**New in Django development version**
-Normal Python unit tests have a wide range of assertions, such as
-``assertTrue`` and ``assertEquals`` that can be used to validate behavior.
-``django.TestCase`` adds to these, providing some assertions
-that can be useful in testing the behavior of web sites.
+As Python's normal ``unittest.TestCase`` class implements assertion
+methods such as ``assertTrue`` and ``assertEquals``, Django's custom
+``TestCase`` class provides a number of custom assertion methods that are
+useful for testing Web applications:
``assertContains(response, text, count=None, status_code=200)``
- Assert that a response indicates that a page could be retrieved and
- produced the nominated status code, and that ``text`` in the content
- of the response. If ``count`` is provided, ``text`` must occur exactly
- ``count`` times in the response.
+ Asserts that a ``Response`` instance produced the given ``status_code`` and
+ that ``text`` appears in the content of the response. If ``count`` is
+ provided, ``text`` must occur exactly ``count`` times in the response.
``assertFormError(response, form, field, errors)``
- Assert that a field on a form raised the provided list of errors when
+ Asserts that a field on a form raises the provided list of errors when
rendered on the form.
- ``form`` is the name the form object was given in the template context.
+ ``form`` is the name the ``Form`` instance was given in the template
+ context. Note that this works only for ``newforms.Form`` instances, not
+ ``oldforms.Form`` instances.
``field`` is the name of the field on the form to check. If ``field``
- has a value of ``None``, non-field errors will be checked.
+ has a value of ``None``, non-field errors (errors you can access via
+ ``form.non_field_errors()``) will be checked.
``errors`` is an error string, or a list of error strings, that are
expected as a result of form validation.
``assertTemplateNotUsed(response, template_name)``
- Assert that the template with the given name was *not* used in rendering
+ Asserts that the template with the given name was *not* used in rendering
the response.
``assertRedirects(response, expected_path, status_code=302, target_status_code=200)``
- Assert that the response received produced the nominated status code,
- redirects the browser to the provided path, and that retrieving the provided
- path yields a response with the target status code.
+ Asserts that the response return a ``status_code`` redirect status,
+ it redirected to ``expected_path`` and the subsequent page was received with
+ ``target_status_code``.
``assertTemplateUsed(response, template_name)``
- Assert that the template with the given name was used in rendering the
+ Asserts that the template with the given name was used in rendering the
response.
+ The name is a string such as ``'admin/index.html'``.
+
E-mail services
---------------
**New in Django development version**
-If your view makes use of the `Django e-mail services`_, you don't really
-want e-mail to be sent every time you run a test using that view.
-
-When the Django test framework is initialized, it transparently replaces the
-normal `SMTPConnection`_ class with a dummy implementation that redirects all
-e-mail to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``,
-is a simple list of all `EmailMessage`_ instances that have been sent.
-For example, during test conditions, it would be possible to run the following
-code::
+If any of your Django views send e-mail using `Django's e-mail functionality`_,
+you probably don't want to send e-mail each time you run a test using that
+view. For this reason, Django's test runner automatically redirects all
+Django-sent e-mail to a dummy outbox. This lets you test every aspect of
+sending e-mail -- from the number of messages sent to the contents of each
+message -- without actually sending the messages.
+
+The test runner accomplishes this by transparently replacing the normal
+`SMTPConnection`_ class with a different version. (Don't worry -- this has no
+effect on any other e-mail senders outside of Django, such as your machine's
+mail server, if you're running one.)
+
+During test running, each outgoing e-mail is saved in
+``django.core.mail.outbox``. This is a simple list of all `EmailMessage`_
+instances that have been sent. It does not exist under normal execution
+conditions, i.e., when you're not running unit tests. The outbox is created
+during test setup, along with the dummy `SMTPConnection`_. When the test
+framework is torn down, the standard `SMTPConnection`_ class is restored, and
+the test outbox is destroyed.
+
+Here's an example test that examines ``django.core.mail.outbox`` for length
+and contents::
from django.core import mail
+ from django.test import TestCase
- # Send message
- mail.send_mail('Subject here', 'Here is the message.', 'from@example.com',
- ['to@example.com'], fail_silently=False)
+ class EmailTest(TestCase):
+ def test_send_email(self):
+ # Send message.
+ mail.send_mail('Subject here', 'Here is the message.',
+ 'from@example.com', ['to@example.com'],
+ fail_silently=False)
- # One message has been sent
- self.assertEqual(len(mail.outbox), 1)
- # Subject of first message is correct
- self.assertEqual(mail.outbox[0].subject, 'Subject here')
+ # Test that one message has been sent.
+ self.assertEqual(len(mail.outbox), 1)
-The ``mail.outbox`` object does not exist under normal execution conditions.
-The outbox is created during test setup, along with the dummy `SMTPConnection`_.
-When the test framework is torn down, the standard `SMTPConnection`_ class
-is restored, and the test outbox is destroyed.
+ # Verify that the subject of the first message is correct.
+ self.assertEqual(mail.outbox[0].subject, 'Subject here')
As noted `previously`_, the test outbox is emptied at the start of every
-test in a Django TestCase. To empty the outbox manually, assign the empty list
-to mail.outbox::
+test in a Django ``TestCase``. To empty the outbox manually, assign the
+empty list to ``mail.outbox``::
from django.core import mail
# Empty the test outbox
mail.outbox = []
-.. _`Django e-mail services`: ../email/
+.. _`Django's e-mail functionality`: ../email/
.. _`SMTPConnection`: ../email/#the-emailmessage-and-smtpconnection-classes
.. _`EmailMessage`: ../email/#the-emailmessage-and-smtpconnection-classes
.. _`previously`: #emptying-the-test-outbox
-Running tests
-=============
-
-Run your tests using your project's ``manage.py`` utility::
-
- $ ./manage.py test
-
-If you only want to run tests for a particular application, add the
-application name to the command line. For example, if your
-``INSTALLED_APPS`` contains ``myproject.polls`` and ``myproject.animals``,
-but you only want to run the animals unit tests, run::
-
- $ ./manage.py test animals
+Using different testing frameworks
+==================================
-**New in Django development version:** If you use unit tests, you can be more
-specific in the tests that are executed. To run a single test case in an
-application (for example, the AnimalTestCase described previously), add the
-name of the test case to the label on the command line::
-
- $ ./manage.py test animals.AnimalTestCase
-
-**New in Django development version:** To run a single test method inside a
-test case, add the name of the test method to the label::
-
- $ ./manage.py test animals.AnimalTestCase.testFluffyAnimals
-
-When you run your tests, you'll see a bunch of text flow by as the test
-database is created and models are initialized. This test database is
-created from scratch every time you run your tests.
-
-By default, the test database gets its name by prepending ``test_`` to
-the database name specified by the ``DATABASE_NAME`` setting; all other
-database settings will the same as they would be for the project normally.
-If you wish to use a name other than the default for the test database,
-you can use the ``TEST_DATABASE_NAME`` setting to provide a name.
-
-**New in Django development version:** For fine-grained control over the
-character encoding of your database, use the ``TEST_DATABASE_CHARSET`` setting.
-If you're using MySQL, you can also use the ``TEST_DATABASE_COLLATION`` setting
-to control the particular collation used by the test database. See the
-settings_ documentation for details of these advanced settings.
-
-.. _settings: ../settings/
-
-The test database is created by the user in the ``DATABASE_USER`` setting.
-This user needs to have sufficient privileges to create a new database on the
-system.
-
-Once the test database has been established, Django will run your tests.
-If everything goes well, at the end you'll see::
-
- ----------------------------------------------------------------------
- Ran 22 tests in 0.221s
-
- OK
-
-If there are test failures, however, you'll see full details about what tests
-failed::
-
- ======================================================================
- FAIL: Doctest: ellington.core.throttle.models
- ----------------------------------------------------------------------
- Traceback (most recent call last):
- File "/dev/django/test/doctest.py", line 2153, in runTest
- raise self.failureException(self.format_failure(new.getvalue()))
- AssertionError: Failed doctest test for myapp.models
- File "/dev/myapp/models.py", line 0, in models
+Clearly, ``doctest`` and ``unittest`` are not the only Python testing
+frameworks. While Django doesn't provide explicit support for alternative
+frameworks, it does provide a way to invoke tests constructed for an
+alternative framework as if they were normal Django tests.
- ----------------------------------------------------------------------
- File "/dev/myapp/models.py", line 14, in myapp.models
- Failed example:
- throttle.check("actor A", "action one", limit=2, hours=1)
- Expected:
- True
- Got:
- False
-
- ----------------------------------------------------------------------
- Ran 2 tests in 0.048s
+When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
+setting to determine what to do. By default, ``TEST_RUNNER`` points to
+``'django.test.simple.run_tests'``. This method defines the default Django
+testing behavior. This behavior involves:
- FAILED (failures=1)
+ #. Performing global pre-test setup.
-The return code for the script is the total number of failed and erroneous
-tests. If all the tests pass, the return code is 0.
+ #. Creating the test database.
-Regardless of whether the tests pass or fail, the test database is destroyed when
-all the tests have been executed.
+ #. Running ``syncdb`` to install models and initial data into the test
+ database.
-Using a different testing framework
-===================================
+ #. Looking for unit tests and doctests in the ``models.py`` and
+ ``tests.py`` files in each installed application.
-Doctest and Unittest are not the only Python testing frameworks. While
-Django doesn't provide explicit support these alternative frameworks,
-it does provide a mechanism to allow you to invoke tests constructed for
-an alternative framework as if they were normal Django tests.
+ #. Running the unit tests and doctests that are found.
-When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
-setting to determine what to do. By default, ``TEST_RUNNER`` points to
-``django.test.simple.run_tests``. This method defines the default Django
-testing behavior. This behavior involves:
+ #. Destroying the test database.
-#. Performing global pre-test setup
-#. Creating the test database
-#. Running ``syncdb`` to install models and initial data into the test database
-#. Looking for Unit Tests and Doctests in ``models.py`` and ``tests.py`` file for each installed application
-#. Running the Unit Tests and Doctests that are found
-#. Destroying the test database
-#. Performing global post-test teardown
+ #. Performing global post-test teardown.
-If you define your own test runner method and point ``TEST_RUNNER``
-at that method, Django will execute your test runner whenever you run
-``./manage.py test``. In this way, it is possible to use any test
-framework that can be executed from Python code.
+If you define your own test runner method and point ``TEST_RUNNER`` at that
+method, Django will execute your test runner whenever you run
+``./manage.py test``. In this way, it is possible to use any test framework
+that can be executed from Python code.
Defining a test runner
----------------------
-By convention, a test runner should be called ``run_tests``; however, you
-can call it anything you want. The only requirement is that it has the
-same arguments as the Django test runner:
+
+**New in Django development version**
+
+By convention, a test runner should be called ``run_tests``. The only strict
+requirement is that it has the same arguments as the Django test runner:
``run_tests(test_labels, verbosity=1, interactive=True, extra_tests=[])``
-
- **New in Django development version:** ``test_labels`` is a list of
- strings describing the tests to be run. A test label can take one of
- three forms:
- * ``app.TestCase.test_method`` - Run a single test method in a test case
- * ``app.TestCase`` - Run all the test methods in a test case
- * ``app`` - Search for and run all tests in the named application.
+ ``test_labels`` is a list of strings describing the tests to be run. A test
+ label can take one of three forms:
+
+ * ``app.TestCase.test_method`` -- Run a single test method in a test case.
+ * ``app.TestCase`` -- Run all the test methods in a test case.
+ * ``app`` -- Search for and run all tests in the named application.
If ``test_labels`` has a value of ``None``, the test runner should run
search for tests in all the applications in ``INSTALLED_APPS``.
- Verbosity determines the amount of notification and debug information that
- will be printed to the console; ``0`` is no output, ``1`` is normal output,
- and ``2`` is verbose output.
+ ``verbosity`` determines the amount of notification and debug information
+ that will be printed to the console; ``0`` is no output, ``1`` is normal
+ output, and ``2`` is verbose output.
- **New in Django development version:** If ``interactive`` is ``True``, the
- test suite may ask the user for instructions when the test suite is
- executed. An example of this behavior would be asking for permission to
- delete an existing test database. If ``interactive`` is ``False``, the
- test suite must be able to run without any manual intervention.
+ If ``interactive`` is ``True``, the test suite has permission to ask the
+ user for instructions when the test suite is executed. An example of this
+ behavior would be asking for permission to delete an existing test
+ database. If ``interactive`` is ``False``, the test suite must be able to
+ run without any manual intervention.
``extra_tests`` is a list of extra ``TestCase`` instances to add to the
suite that is executed by the test runner. These extra tests are run
@@ -718,28 +963,33 @@ a number of utility methods in the ``django.test.utils`` module.
``setup_test_environment()``
Performs any global pre-test setup, such as the installing the
instrumentation of the template rendering system and setting up
- the dummy SMTPConnection.
+ the dummy ``SMTPConnection``.
``teardown_test_environment()``
- Performs any global post-test teardown, such as removing the instrumentation
- of the template rendering system and restoring normal e-mail services.
+ Performs any global post-test teardown, such as removing the
+ black magic hooks into the template system and restoring normal e-mail
+ services.
``create_test_db(verbosity=1, autoclobber=False)``
- Creates a new test database, and run ``syncdb`` against it.
+ Creates a new test database and runs ``syncdb`` against it.
+
+ ``verbosity`` has the same behavior as in ``run_tests()``.
- ``verbosity`` has the same behavior as in the test runner.
+ ``autoclobber`` describes the behavior that will occur if a database with
+ the same name as the test database is discovered:
+
+ * If ``autoclobber`` is ``False``, the user will be asked to approve
+ destroying the existing database. ``sys.exit`` is called if the user
+ does not approve.
- ``Autoclobber`` describes the behavior that will occur if a database with
- the same name as the test database is discovered. If ``autoclobber`` is False,
- the user will be asked to approve destroying the existing database. ``sys.exit``
- is called if the user does not approve. If autoclobber is ``True``, the database
- will be destroyed without consulting the user.
+ * If autoclobber is ``True``, the database will be destroyed without
+ consulting the user.
``create_test_db()`` has the side effect of modifying
``settings.DATABASE_NAME`` to match the name of the test database.
``destroy_test_db(old_database_name, verbosity=1)``
- Destroys the database with the name ``settings.DATABASE_NAME`` matching,
- and restores the value of ``settings.DATABASE_NAME`` to the provided name.
+ Destroys the database whose name is in the ``DATABASE_NAME`` setting
+ and restores the value of ``DATABASE_NAME`` to the provided name.
- ``verbosity`` has the same behavior as in the test runner.
+ ``verbosity`` has the same behavior as in ``run_tests()``.
Please sign in to comment.
Something went wrong with that request. Please try again.