testtools: Import latest upstream.
[nivanova/samba-autobuild/.git] / lib / testtools / MANUAL
1 ======
2 Manual
3 ======
4
5 Introduction
6 ------------
7
8 This document provides overview of the features provided by testtools.  Refer
9 to the API docs (i.e. docstrings) for full details on a particular feature.
10
11 Extensions to TestCase
12 ----------------------
13
14 Controlling test execution
15 ~~~~~~~~~~~~~~~~~~~~~~~~~~
16
17 Testtools supports two ways to control how tests are executed. The simplest
18 is to add a new exception to self.exception_handlers::
19
20     >>> self.exception_handlers.insert(-1, (ExceptionClass, handler)).
21
22 Having done this, if any of setUp, tearDown, or the test method raise
23 ExceptionClass, handler will be called with the test case, test result and the
24 raised exception.
25
26 Secondly, by overriding __init__ to pass in runTest=RunTestFactory the whole
27 execution of the test can be altered. The default is testtools.runtest.RunTest
28 and calls  case._run_setup, case._run_test_method and finally
29 case._run_teardown. Other methods to control what RunTest is used may be
30 added in future.
31
32
33 TestCase.addCleanup
34 ~~~~~~~~~~~~~~~~~~~
35
36 addCleanup is a robust way to arrange for a cleanup function to be called
37 before tearDown.  This is a powerful and simple alternative to putting cleanup
38 logic in a try/finally block or tearDown method.  e.g.::
39
40     def test_foo(self):
41         foo.lock()
42         self.addCleanup(foo.unlock)
43         ...
44
45
46 TestCase.addOnException
47 ~~~~~~~~~~~~~~~~~~~~~~~
48
49 addOnException adds an exception handler that will be called from the test
50 framework when it detects an exception from your test code. The handler is
51 given the exc_info for the exception, and can use this opportunity to attach
52 more data (via the addDetails API) and potentially other uses.
53
54
55 TestCase.patch
56 ~~~~~~~~~~~~~~
57
58 ``patch`` is a convenient way to monkey-patch a Python object for the duration
59 of your test.  It's especially useful for testing legacy code.  e.g.::
60
61     def test_foo(self):
62         my_stream = StringIO()
63         self.patch(sys, 'stderr', my_stream)
64         run_some_code_that_prints_to_stderr()
65         self.assertEqual('', my_stream.getvalue())
66
67 The call to ``patch`` above masks sys.stderr with 'my_stream' so that anything
68 printed to stderr will be captured in a StringIO variable that can be actually
69 tested. Once the test is done, the real sys.stderr is restored to its rightful
70 place.
71
72
73 TestCase.skipTest
74 ~~~~~~~~~~~~~~~~~
75
76 ``skipTest`` is a simple way to have a test stop running and be reported as a
77 skipped test, rather than a success/error/failure. This is an alternative to
78 convoluted logic during test loading, permitting later and more localized
79 decisions about the appropriateness of running a test. Many reasons exist to
80 skip a test - for instance when a dependency is missing, or if the test is
81 expensive and should not be run while on laptop battery power, or if the test
82 is testing an incomplete feature (this is sometimes called a TODO). Using this
83 feature when running your test suite with a TestResult object that is missing
84 the ``addSkip`` method will result in the ``addError`` method being invoked
85 instead. ``skipTest`` was previously known as ``skip`` but as Python 2.7 adds
86 ``skipTest`` support, the ``skip`` name is now deprecated (but no warning
87 is emitted yet - some time in the future we may do so).
88
89
90 New assertion methods
91 ~~~~~~~~~~~~~~~~~~~~~
92
93 testtools adds several assertion methods:
94
95  * assertIn
96  * assertNotIn
97  * assertIs
98  * assertIsNot
99  * assertIsInstance
100  * assertThat
101
102
103 Improved assertRaises
104 ~~~~~~~~~~~~~~~~~~~~~
105
106 TestCase.assertRaises returns the caught exception.  This is useful for
107 asserting more things about the exception than just the type::
108
109         error = self.assertRaises(UnauthorisedError, thing.frobnicate)
110         self.assertEqual('bob', error.username)
111         self.assertEqual('User bob cannot frobnicate', str(error))
112
113
114 TestCase.assertThat
115 ~~~~~~~~~~~~~~~~~~~
116
117 assertThat is a clean way to write complex assertions without tying them to
118 the TestCase inheritance hierarchy (and thus making them easier to reuse).
119
120 assertThat takes an object to be matched, and a matcher, and fails if the
121 matcher does not match the matchee.
122
123 See pydoc testtools.Matcher for the protocol that matchers need to implement.
124
125 testtools includes some matchers in testtools.matchers.
126 python -c 'import testtools.matchers; print testtools.matchers.__all__' will
127 list those matchers.
128
129 An example using the DocTestMatches matcher which uses doctests example
130 matching logic::
131
132     def test_foo(self):
133         self.assertThat([1,2,3,4], DocTestMatches('[1, 2, 3, 4]'))
134
135
136 Creation methods
137 ~~~~~~~~~~~~~~~~
138
139 testtools.TestCase implements creation methods called ``getUniqueString`` and
140 ``getUniqueInteger``.  See pages 419-423 of *xUnit Test Patterns* by Meszaros
141 for a detailed discussion of creation methods.
142
143
144 Test renaming
145 ~~~~~~~~~~~~~
146
147 ``testtools.clone_test_with_new_id`` is a function to copy a test case
148 instance to one with a new name.  This is helpful for implementing test
149 parameterization.
150
151
152 Extensions to TestResult
153 ------------------------
154
155 TestResult.addSkip
156 ~~~~~~~~~~~~~~~~~~
157
158 This method is called on result objects when a test skips. The
159 ``testtools.TestResult`` class records skips in its ``skip_reasons`` instance
160 dict. The can be reported on in much the same way as succesful tests.
161
162
163 TestResult.time
164 ~~~~~~~~~~~~~~~
165
166 This method controls the time used by a TestResult, permitting accurate
167 timing of test results gathered on different machines or in different threads.
168 See pydoc testtools.TestResult.time for more details.
169
170
171 ThreadsafeForwardingResult
172 ~~~~~~~~~~~~~~~~~~~~~~~~~~
173
174 A TestResult which forwards activity to another test result, but synchronises
175 on a semaphore to ensure that all the activity for a single test arrives in a
176 batch. This allows simple TestResults which do not expect concurrent test
177 reporting to be fed the activity from multiple test threads, or processes.
178
179 Note that when you provide multiple errors for a single test, the target sees
180 each error as a distinct complete test.
181
182
183 TextTestResult
184 ~~~~~~~~~~~~~~
185
186 A TestResult that provides a text UI very similar to the Python standard
187 library UI. Key differences are that its supports the extended outcomes and
188 details API, and is completely encapsulated into the result object, permitting
189 it to be used without a 'TestRunner' object. Not all the Python 2.7 outcomes
190 are displayed (yet). It is also a 'quiet' result with no dots or verbose mode.
191 These limitations will be corrected soon.
192
193
194 Test Doubles
195 ~~~~~~~~~~~~
196
197 In testtools.testresult.doubles there are three test doubles that testtools
198 uses for its own testing: Python26TestResult, Python27TestResult,
199 ExtendedTestResult. These TestResult objects implement a single variation of
200 the TestResult API each, and log activity to a list self._events. These are
201 made available for the convenience of people writing their own extensions.
202
203
204 startTestRun and stopTestRun
205 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
206
207 Python 2.7 added hooks 'startTestRun' and 'stopTestRun' which are called
208 before and after the entire test run. 'stopTestRun' is particularly useful for
209 test results that wish to produce summary output.
210
211 testtools.TestResult provides empty startTestRun and stopTestRun methods, and
212 the default testtools runner will call these methods appropriately.
213
214
215 Extensions to TestSuite
216 -----------------------
217
218 ConcurrentTestSuite
219 ~~~~~~~~~~~~~~~~~~~
220
221 A TestSuite for parallel testing. This is used in conjuction with a helper that
222 runs a single suite in some parallel fashion (for instance, forking, handing
223 off to a subprocess, to a compute cloud, or simple threads).
224 ConcurrentTestSuite uses the helper to get a number of separate runnable
225 objects with a run(result), runs them all in threads using the
226 ThreadsafeForwardingResult to coalesce their activity.
227
228
229 Running tests
230 -------------
231
232 Testtools provides a convenient way to run a test suite using the testtools
233 result object: python -m testtools.run testspec [testspec...].
234
235 Test discovery
236 --------------
237
238 Testtools includes a backported version of the Python 2.7 glue for using the
239 discover test discovery module. If you either have Python 2.7/3.1 or newer, or
240 install the 'discover' module, then you can invoke discovery::
241
242     python -m testtools.run discover [path]
243
244 For more information see the Python 2.7 unittest documentation, or::
245
246     python -m testtools.run --help