summaryrefslogtreecommitdiffstats
path: root/Doc
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-01-20 00:31:20 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2013-01-20 00:31:20 (GMT)
commit21f3283d31fdb33513d8c3bbcbbd839b68e5f161 (patch)
tree97753eabaa646727c24e35d6ee3ea8411daec89f /Doc
parentf0472f6995d71350834a097762ee2eba4b0b13f8 (diff)
parent2c5e9504d8902e8ad3e7e9323a872491c43d520a (diff)
downloadcpython-21f3283d31fdb33513d8c3bbcbbd839b68e5f161.zip
cpython-21f3283d31fdb33513d8c3bbcbbd839b68e5f161.tar.gz
cpython-21f3283d31fdb33513d8c3bbcbbd839b68e5f161.tar.bz2
Remove cruft and circumvolutions from the unittest docs.
(I would have preferred to post this for review but the bug tracker is pretty much dead at the moment)
Diffstat (limited to 'Doc')
-rw-r--r--Doc/library/unittest.rst253
1 files changed, 56 insertions, 197 deletions
diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst
index 06f3d83..3476957 100644
--- a/Doc/library/unittest.rst
+++ b/Doc/library/unittest.rst
@@ -11,17 +11,14 @@
(If you are already familiar with the basic concepts of testing, you might want
to skip to :ref:`the list of assert methods <assert-methods>`.)
-The Python unit testing framework, sometimes referred to as "PyUnit," is a
-Python language version of JUnit, by Kent Beck and Erich Gamma. JUnit is, in
-turn, a Java version of Kent's Smalltalk testing framework. Each is the de
-facto standard unit testing framework for its respective language.
+The :mod:`unittest` unit testing framework was originally inspired by JUnit
+and has a similar flavor as major unit testing frameworks in other
+languages. It supports test automation, sharing of setup and shutdown code
+for tests, aggregation of tests into collections, and independence of the
+tests from the reporting framework.
-:mod:`unittest` supports test automation, sharing of setup and shutdown code for
-tests, aggregation of tests into collections, and independence of the tests from
-the reporting framework. The :mod:`unittest` module provides classes that make
-it easy to support these qualities for a set of tests.
-
-To achieve this, :mod:`unittest` supports some important concepts:
+To achieve this, :mod:`unittest` supports some important concepts in an
+object-oriented way:
test fixture
A :dfn:`test fixture` represents the preparation needed to perform one or more
@@ -30,7 +27,7 @@ test fixture
process.
test case
- A :dfn:`test case` is the smallest unit of testing. It checks for a specific
+ A :dfn:`test case` is the individual unit of testing. It checks for a specific
response to a particular set of inputs. :mod:`unittest` provides a base class,
:class:`TestCase`, which may be used to create new test cases.
@@ -44,43 +41,12 @@ test runner
a textual interface, or return a special value to indicate the results of
executing the tests.
-The test case and test fixture concepts are supported through the
-:class:`TestCase` and :class:`FunctionTestCase` classes; the former should be
-used when creating new tests, and the latter can be used when integrating
-existing test code with a :mod:`unittest`\ -driven framework. When building test
-fixtures using :class:`TestCase`, the :meth:`~TestCase.setUp` and
-:meth:`~TestCase.tearDown` methods can be overridden to provide initialization
-and cleanup for the fixture. With :class:`FunctionTestCase`, existing functions
-can be passed to the constructor for these purposes. When the test is run, the
-fixture initialization is run first; if it succeeds, the cleanup method is run
-after the test has been executed, regardless of the outcome of the test. Each
-instance of the :class:`TestCase` will only be used to run a single test method,
-so a new fixture is created for each test.
-
-Test suites are implemented by the :class:`TestSuite` class. This class allows
-individual tests and test suites to be aggregated; when the suite is executed,
-all tests added directly to the suite and in "child" test suites are run.
-
-A test runner is an object that provides a single method,
-:meth:`~TestRunner.run`, which accepts a :class:`TestCase` or :class:`TestSuite`
-object as a parameter, and returns a result object. The class
-:class:`TestResult` is provided for use as the result object. :mod:`unittest`
-provides the :class:`TextTestRunner` as an example test runner which reports
-test results on the standard error stream by default. Alternate runners can be
-implemented for other environments (such as graphical environments) without any
-need to derive from a specific class.
-
.. seealso::
Module :mod:`doctest`
Another test-support module with a very different flavor.
- `unittest2: A backport of new unittest features for Python 2.4-2.6 <http://pypi.python.org/pypi/unittest2>`_
- Many new features were added to unittest in Python 2.7, including test
- discovery. unittest2 allows you to use these features with earlier
- versions of Python.
-
`Simple Smalltalk Testing: With Patterns <http://www.XProgramming.com/testfram.htm>`_
Kent Beck's original paper on testing frameworks using the pattern shared
by :mod:`unittest`.
@@ -89,7 +55,7 @@ need to derive from a specific class.
Third-party unittest frameworks with a lighter-weight syntax for writing
tests. For example, ``assert func(10) == 42``.
- `The Python Testing Tools Taxonomy <http://pycheesecake.org/wiki/PythonTestingToolsTaxonomy>`_
+ `The Python Testing Tools Taxonomy <http://wiki.python.org/moin/PythonTestingToolsTaxonomy>`_
An extensive list of Python testing tools including functional testing
frameworks and mock object libraries.
@@ -173,15 +139,8 @@ line, the above script produces an output that looks like this::
OK
-Instead of :func:`unittest.main`, there are other ways to run the tests with a
-finer level of control, less terse output, and no requirement to be run from the
-command line. For example, the last two lines may be replaced with::
-
- suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
- unittest.TextTestRunner(verbosity=2).run(suite)
-
-Running the revised script from the interpreter or another script produces the
-following output::
+Passing the ``-v`` option to your test script will instruct :func:`unittest.main`
+to enable a higher level of verbosity, and produce the following output::
test_choice (__main__.TestSequenceFunctions) ... ok
test_sample (__main__.TestSequenceFunctions) ... ok
@@ -359,45 +318,30 @@ test cases are represented by :class:`unittest.TestCase` instances.
To make your own test cases you must write subclasses of
:class:`TestCase` or use :class:`FunctionTestCase`.
-An instance of a :class:`TestCase`\ -derived class is an object that can
-completely run a single test method, together with optional set-up and tidy-up
-code.
-
The testing code of a :class:`TestCase` instance should be entirely self
contained, such that it can be run either in isolation or in arbitrary
combination with any number of other test cases.
-The simplest :class:`TestCase` subclass will simply override the
-:meth:`~TestCase.runTest` method in order to perform specific testing code::
+The simplest :class:`TestCase` subclass will simply implement a test method
+(i.e. a method whose name starts with ``test``) in order to perform specific
+testing code::
import unittest
class DefaultWidgetSizeTestCase(unittest.TestCase):
- def runTest(self):
+ def test_default_widget_size(self):
widget = Widget('The widget')
- self.assertEqual(widget.size(), (50, 50), 'incorrect default size')
+ self.assertEqual(widget.size(), (50, 50))
Note that in order to test something, we use one of the :meth:`assert\*`
methods provided by the :class:`TestCase` base class. If the test fails, an
exception will be raised, and :mod:`unittest` will identify the test case as a
-:dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`. This
-helps you identify where the problem is: :dfn:`failures` are caused by incorrect
-results - a 5 where you expected a 6. :dfn:`Errors` are caused by incorrect
-code - e.g., a :exc:`TypeError` caused by an incorrect function call.
+:dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`.
-The way to run a test case will be described later. For now, note that to
-construct an instance of such a test case, we call its constructor without
-arguments::
-
- testCase = DefaultWidgetSizeTestCase()
-
-Now, such test cases can be numerous, and their set-up can be repetitive. In
-the above case, constructing a :class:`Widget` in each of 100 Widget test case
-subclasses would mean unsightly duplication.
-
-Luckily, we can factor out such set-up code by implementing a method called
-:meth:`~TestCase.setUp`, which the testing framework will automatically call for
-us when we run the test::
+Tests can be numerous, and their set-up can be repetitive. Luckily, we
+can factor out set-up code by implementing a method called
+:meth:`~TestCase.setUp`, which the testing framework will automatically
+call for every single test we run::
import unittest
@@ -405,23 +349,26 @@ us when we run the test::
def setUp(self):
self.widget = Widget('The widget')
- class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
- def runTest(self):
+ def test_default_widget_size(self):
self.assertEqual(self.widget.size(), (50,50),
'incorrect default size')
- class WidgetResizeTestCase(SimpleWidgetTestCase):
- def runTest(self):
+ def test_widget_resize(self):
self.widget.resize(100,150)
self.assertEqual(self.widget.size(), (100,150),
'wrong size after resize')
+.. note::
+ The order in which the various tests will be run is determined
+ by sorting the test method names with respect to the built-in
+ ordering for strings.
+
If the :meth:`~TestCase.setUp` method raises an exception while the test is
-running, the framework will consider the test to have suffered an error, and the
-:meth:`~TestCase.runTest` method will not be executed.
+running, the framework will consider the test to have suffered an error, and
+the test method will not be executed.
Similarly, we can provide a :meth:`~TestCase.tearDown` method that tidies up
-after the :meth:`~TestCase.runTest` method has been run::
+after the test method has been run::
import unittest
@@ -431,59 +378,20 @@ after the :meth:`~TestCase.runTest` method has been run::
def tearDown(self):
self.widget.dispose()
- self.widget = None
-If :meth:`~TestCase.setUp` succeeded, the :meth:`~TestCase.tearDown` method will
-be run whether :meth:`~TestCase.runTest` succeeded or not.
+If :meth:`~TestCase.setUp` succeeded, :meth:`~TestCase.tearDown` will be
+run whether the test method succeeded or not.
Such a working environment for the testing code is called a :dfn:`fixture`.
-Often, many small test cases will use the same fixture. In this case, we would
-end up subclassing :class:`SimpleWidgetTestCase` into many small one-method
-classes such as :class:`DefaultWidgetSizeTestCase`. This is time-consuming and
-discouraging, so in the same vein as JUnit, :mod:`unittest` provides a simpler
-mechanism::
-
- import unittest
-
- class WidgetTestCase(unittest.TestCase):
- def setUp(self):
- self.widget = Widget('The widget')
-
- def tearDown(self):
- self.widget.dispose()
- self.widget = None
-
- def test_default_size(self):
- self.assertEqual(self.widget.size(), (50,50),
- 'incorrect default size')
-
- def test_resize(self):
- self.widget.resize(100,150)
- self.assertEqual(self.widget.size(), (100,150),
- 'wrong size after resize')
-
-Here we have not provided a :meth:`~TestCase.runTest` method, but have instead
-provided two different test methods. Class instances will now each run one of
-the :meth:`test_\*` methods, with ``self.widget`` created and destroyed
-separately for each instance. When creating an instance we must specify the
-test method it is to run. We do this by passing the method name in the
-constructor::
-
- defaultSizeTestCase = WidgetTestCase('test_default_size')
- resizeTestCase = WidgetTestCase('test_resize')
-
Test case instances are grouped together according to the features they test.
:mod:`unittest` provides a mechanism for this: the :dfn:`test suite`,
-represented by :mod:`unittest`'s :class:`TestSuite` class::
-
- widgetTestSuite = unittest.TestSuite()
- widgetTestSuite.addTest(WidgetTestCase('test_default_size'))
- widgetTestSuite.addTest(WidgetTestCase('test_resize'))
+represented by :mod:`unittest`'s :class:`TestSuite` class. In most cases,
+calling :func:`unittest.main` will do the right thing and collect all the
+module's test cases for you, and then execute them.
-For the ease of running tests, as we will see later, it is a good idea to
-provide in each test module a callable object that returns a pre-built test
-suite::
+However, should you want to customize the building of your test suite,
+you can do it yourself::
def suite():
suite = unittest.TestSuite()
@@ -491,37 +399,6 @@ suite::
suite.addTest(WidgetTestCase('test_resize'))
return suite
-or even::
-
- def suite():
- tests = ['test_default_size', 'test_resize']
-
- return unittest.TestSuite(map(WidgetTestCase, tests))
-
-Since it is a common pattern to create a :class:`TestCase` subclass with many
-similarly named test functions, :mod:`unittest` provides a :class:`TestLoader`
-class that can be used to automate the process of creating a test suite and
-populating it with individual tests. For example, ::
-
- suite = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)
-
-will create a test suite that will run ``WidgetTestCase.test_default_size()`` and
-``WidgetTestCase.test_resize``. :class:`TestLoader` uses the ``'test'`` method
-name prefix to identify test methods automatically.
-
-Note that the order in which the various test cases will be run is
-determined by sorting the test function names with respect to the
-built-in ordering for strings.
-
-Often it is desirable to group suites of test cases together, so as to run tests
-for the whole system at once. This is easy, since :class:`TestSuite` instances
-can be added to a :class:`TestSuite` just as :class:`TestCase` instances can be
-added to a :class:`TestSuite`::
-
- suite1 = module1.TheTestSuite()
- suite2 = module2.TheTestSuite()
- alltests = unittest.TestSuite([suite1, suite2])
-
You can place the definitions of test cases and test suites in the same modules
as the code they are to test (such as :file:`widget.py`), but there are several
advantages to placing the test code in a separate module, such as
@@ -564,23 +441,13 @@ Given the following test function::
assert something.name is not None
# ...
-one can create an equivalent test case instance as follows::
-
- testcase = unittest.FunctionTestCase(testSomething)
-
-If there are additional set-up and tear-down methods that should be called as
-part of the test case's operation, they can also be provided like so::
+one can create an equivalent test case instance as follows, with optional
+set-up and tear-down methods::
testcase = unittest.FunctionTestCase(testSomething,
setUp=makeSomethingDB,
tearDown=deleteSomethingDB)
-To make migrating existing test suites easier, :mod:`unittest` supports tests
-raising :exc:`AssertionError` to indicate test failure. However, it is
-recommended that you use the explicit :meth:`TestCase.fail\*` and
-:meth:`TestCase.assert\*` methods instead, as future versions of :mod:`unittest`
-may treat :exc:`AssertionError` differently.
-
.. note::
Even though :class:`FunctionTestCase` can be used to quickly convert an
@@ -704,32 +571,24 @@ Test cases
.. class:: TestCase(methodName='runTest')
- Instances of the :class:`TestCase` class represent the smallest testable units
+ Instances of the :class:`TestCase` class represent the logical test units
in the :mod:`unittest` universe. This class is intended to be used as a base
class, with specific tests being implemented by concrete subclasses. This class
implements the interface needed by the test runner to allow it to drive the
- test, and methods that the test code can use to check for and report various
+ tests, and methods that the test code can use to check for and report various
kinds of failure.
- Each instance of :class:`TestCase` will run a single test method: the method
- named *methodName*. If you remember, we had an earlier example that went
- something like this::
-
- def suite():
- suite = unittest.TestSuite()
- suite.addTest(WidgetTestCase('test_default_size'))
- suite.addTest(WidgetTestCase('test_resize'))
- return suite
-
- Here, we create two instances of :class:`WidgetTestCase`, each of which runs a
- single test.
+ Each instance of :class:`TestCase` will run a single base method: the method
+ named *methodName*. However, the standard implementation of the default
+ *methodName*, ``runTest()``, will run every method starting with ``test``
+ as an individual test, and count successes and failures accordingly.
+ Therefore, in most uses of :class:`TestCase`, you will neither change
+ the *methodName* nor reimplement the default ``runTest()`` method.
.. versionchanged:: 3.2
- :class:`TestCase` can be instantiated successfully without providing a method
- name. This makes it easier to experiment with :class:`TestCase` from the
- interactive interpreter.
-
- *methodName* defaults to :meth:`runTest`.
+ :class:`TestCase` can be instantiated successfully without providing a
+ *methodName*. This makes it easier to experiment with :class:`TestCase`
+ from the interactive interpreter.
:class:`TestCase` instances provide three groups of methods: one group used
to run the test, another used by the test implementation to check conditions
@@ -738,7 +597,6 @@ Test cases
Methods in the first group (running the test) are:
-
.. method:: setUp()
Method called to prepare the test fixture. This is called immediately
@@ -790,10 +648,11 @@ Test cases
.. method:: run(result=None)
- Run the test, collecting the result into the test result object passed as
- *result*. If *result* is omitted or ``None``, a temporary result
- object is created (by calling the :meth:`defaultTestResult` method) and
- used. The result object is returned to :meth:`run`'s caller.
+ Run the test, collecting the result into the :class:`TestResult` object
+ passed as *result*. If *result* is omitted or ``None``, a temporary
+ result object is created (by calling the :meth:`defaultTestResult`
+ method) and used. The result object is returned to :meth:`run`'s
+ caller.
The same effect may be had by simply calling the :class:`TestCase`
instance.