Added a rough cut of a document on using the new testing framework.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@3678 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f89b9c8654
commit
ff4f24958d
|
@ -292,6 +292,13 @@ this command to install the default apps.
|
|||
If you're installing the ``django.contrib.auth`` application, ``syncdb`` will
|
||||
give you the option of creating a superuser immediately.
|
||||
|
||||
test
|
||||
----
|
||||
|
||||
Discover and run tests for all installed models. See `Testing Django applications`_ for more information.
|
||||
|
||||
.. _testing django applications: ../testing/
|
||||
|
||||
validate
|
||||
--------
|
||||
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
===========================
|
||||
Testing Django applications
|
||||
===========================
|
||||
|
||||
**New in Django development version**.
|
||||
|
||||
.. XXX insert quick introduction to testing (and why you'd want to do it)
|
||||
|
||||
.. note::
|
||||
|
||||
This testing framework is currently under development, and may change
|
||||
slightly before the next official Django release.
|
||||
|
||||
(That's *no* excuse not to write tests, though!)
|
||||
|
||||
Writing tests
|
||||
=============
|
||||
|
||||
Tests in Django come in two forms: doctests and unit tests.
|
||||
|
||||
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.
|
||||
|
||||
.. admonition:: What's a **docstring**?
|
||||
|
||||
A good explanation of docstrings (and some guidlines 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.
|
||||
|
||||
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.
|
||||
|
||||
For example::
|
||||
|
||||
from django.db import model
|
||||
|
||||
class Animal(models.Model):
|
||||
"""
|
||||
An animal that knows how to make noise
|
||||
|
||||
# Create some animals
|
||||
>>> lion = Animal.objects.create(name="lion", sound="roar")
|
||||
>>> cat = Animal.objects.create(name="cat", sound="meow")
|
||||
|
||||
# Make 'em speak
|
||||
>>> lion.speak()
|
||||
'The lion says "roar"'
|
||||
>>> cat.speak()
|
||||
'The cat says "meow"'
|
||||
"""
|
||||
|
||||
name = models.CharField(maxlength=20)
|
||||
sound = models.CharField(maxlength=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
|
||||
that portions of it look like an interactive Python session, and execute those
|
||||
lines while checking that the results match.
|
||||
|
||||
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
|
||||
-----------------
|
||||
|
||||
Like doctests, Django's unit tests use a standard library module: unittest_.
|
||||
Django's test runner looks for unit test cases in a ``tests.py`` file in your
|
||||
app (i.e. in the same directory as your ``models.py`` file).
|
||||
|
||||
An equivalent unittest test case for the above example would look like::
|
||||
|
||||
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")
|
||||
|
||||
def testSpeaking(self):
|
||||
self.assertEquals(self.lion.speak(), 'The lion says "roar"')
|
||||
self.assertEquals(self.cat.speak(), 'The cat says "meow"')
|
||||
|
||||
When you `run your tests`_, the test utility will find all the test cases
|
||||
(that is, subclasses of ``unittest.TestCase``) in ``tests.py``, automatically
|
||||
build a test suite out of those test cases, and run that suite.
|
||||
|
||||
For more details about ``unittest``, see the `standard library unittest
|
||||
documentation`_.
|
||||
|
||||
.. _unittest: http://docs.python.org/lib/module-unittest.html
|
||||
.. _standard library unittest documentation: unittest_
|
||||
.. _run your tests: `Running tests`_
|
||||
|
||||
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 weather
|
||||
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 given 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.
|
||||
|
||||
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
|
||||
in different circumstances.
|
||||
|
||||
Running tests
|
||||
=============
|
||||
|
||||
Run your tests using your project's ``manage.py`` utility::
|
||||
|
||||
$ ./manage.py test
|
||||
|
||||
You'll see a bunch of text flow by as the test database is created, models are
|
||||
initialized, and your tests are run. 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
|
||||
|
||||
----------------------------------------------------------------------
|
||||
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)
|
||||
|
Loading…
Reference in New Issue