4634.39.32
by Ian Clatworthy
proper Contents panel in bzr-developers.chm |
1 |
==================== |
2 |
Bazaar Testing Guide |
|
3 |
==================== |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
4 |
|
5 |
||
6 |
The Importance of Testing |
|
7 |
========================= |
|
8 |
||
9 |
Reliability is a critical success factor for any Version Control System. |
|
10 |
We want Bazaar to be highly reliable across multiple platforms while |
|
11 |
evolving over time to meet the needs of its community. |
|
12 |
||
13 |
In a nutshell, this is what we expect and encourage: |
|
14 |
||
15 |
* New functionality should have test cases. Preferably write the |
|
16 |
test before writing the code. |
|
17 |
||
18 |
In general, you can test at either the command-line level or the |
|
19 |
internal API level. See `Writing tests`_ below for more detail. |
|
20 |
||
21 |
* Try to practice Test-Driven Development: before fixing a bug, write a |
|
22 |
test case so that it does not regress. Similarly for adding a new |
|
23 |
feature: write a test case for a small version of the new feature before |
|
24 |
starting on the code itself. Check the test fails on the old code, then |
|
25 |
add the feature or fix and check it passes. |
|
26 |
||
27 |
By doing these things, the Bazaar team gets increased confidence that |
|
28 |
changes do what they claim to do, whether provided by the core team or |
|
29 |
by community members. Equally importantly, we can be surer that changes |
|
30 |
down the track do not break new features or bug fixes that you are |
|
31 |
contributing today. |
|
32 |
||
4665.2.2
by Martin Pool
Doc update that there are actually many more tests now |
33 |
As of September 2009, Bazaar ships with a test suite containing over |
34 |
23,000 tests and growing. We are proud of it and want to remain so. As |
|
35 |
community members, we all benefit from it. Would you trust version control |
|
36 |
on your project to a product *without* a test suite like Bazaar has? |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
37 |
|
38 |
||
39 |
Running the Test Suite |
|
40 |
====================== |
|
41 |
||
42 |
Currently, bzr selftest is used to invoke tests. |
|
43 |
You can provide a pattern argument to run a subset. For example, |
|
44 |
to run just the blackbox tests, run:: |
|
45 |
||
46 |
./bzr selftest -v blackbox |
|
47 |
||
48 |
To skip a particular test (or set of tests), use the --exclude option |
|
49 |
(shorthand -x) like so:: |
|
50 |
||
51 |
./bzr selftest -v -x blackbox |
|
52 |
||
53 |
To ensure that all tests are being run and succeeding, you can use the |
|
54 |
--strict option which will fail if there are any missing features or known |
|
55 |
failures, like so:: |
|
56 |
||
57 |
./bzr selftest --strict |
|
58 |
||
59 |
To list tests without running them, use the --list-only option like so:: |
|
60 |
||
61 |
./bzr selftest --list-only |
|
62 |
||
63 |
This option can be combined with other selftest options (like -x) and |
|
64 |
filter patterns to understand their effect. |
|
65 |
||
66 |
Once you understand how to create a list of tests, you can use the --load-list |
|
67 |
option to run only a restricted set of tests that you kept in a file, one test |
|
68 |
id by line. Keep in mind that this will never be sufficient to validate your |
|
69 |
modifications, you still need to run the full test suite for that, but using it |
|
70 |
can help in some cases (like running only the failed tests for some time):: |
|
71 |
||
72 |
./bzr selftest -- load-list my_failing_tests |
|
73 |
||
74 |
This option can also be combined with other selftest options, including |
|
75 |
patterns. It has some drawbacks though, the list can become out of date pretty |
|
76 |
quick when doing Test Driven Development. |
|
77 |
||
78 |
To address this concern, there is another way to run a restricted set of tests: |
|
79 |
the --starting-with option will run only the tests whose name starts with the |
|
80 |
specified string. It will also avoid loading the other tests and as a |
|
81 |
consequence starts running your tests quicker:: |
|
82 |
||
83 |
./bzr selftest --starting-with bzrlib.blackbox |
|
84 |
||
85 |
This option can be combined with all the other selftest options including |
|
86 |
--load-list. The later is rarely used but allows to run a subset of a list of |
|
87 |
failing tests for example. |
|
88 |
||
89 |
||
90 |
Test suite debug flags |
|
91 |
---------------------- |
|
92 |
||
93 |
Similar to the global ``-Dfoo`` debug options, bzr selftest accepts |
|
94 |
``-E=foo`` debug flags. These flags are: |
|
95 |
||
96 |
:allow_debug: do *not* clear the global debug flags when running a test. |
|
97 |
This can provide useful logging to help debug test failures when used |
|
98 |
with e.g. ``bzr -Dhpss selftest -E=allow_debug`` |
|
99 |
||
100 |
||
101 |
Writing Tests |
|
102 |
============= |
|
103 |
||
104 |
Where should I put a new test? |
|
105 |
------------------------------ |
|
106 |
||
107 |
Bzrlib's tests are organised by the type of test. Most of the tests in |
|
108 |
bzr's test suite belong to one of these categories: |
|
109 |
||
110 |
- Unit tests |
|
111 |
- Blackbox (UI) tests |
|
112 |
- Per-implementation tests |
|
113 |
- Doctests |
|
114 |
||
115 |
A quick description of these test types and where they belong in bzrlib's |
|
116 |
source follows. Not all tests fall neatly into one of these categories; |
|
117 |
in those cases use your judgement. |
|
118 |
||
119 |
||
120 |
Unit tests |
|
121 |
~~~~~~~~~~ |
|
122 |
||
123 |
Unit tests make up the bulk of our test suite. These are tests that are |
|
124 |
focused on exercising a single, specific unit of the code as directly |
|
125 |
as possible. Each unit test is generally fairly short and runs very |
|
126 |
quickly. |
|
127 |
||
128 |
They are found in ``bzrlib/tests/test_*.py``. So in general tests should |
|
129 |
be placed in a file named test_FOO.py where FOO is the logical thing under |
|
130 |
test. |
|
131 |
||
132 |
For example, tests for merge3 in bzrlib belong in bzrlib/tests/test_merge3.py. |
|
133 |
See bzrlib/tests/test_sampler.py for a template test script. |
|
134 |
||
135 |
||
136 |
Blackbox (UI) tests |
|
137 |
~~~~~~~~~~~~~~~~~~~ |
|
138 |
||
139 |
Tests can be written for the UI or for individual areas of the library. |
|
140 |
Choose whichever is appropriate: if adding a new command, or a new command |
|
141 |
option, then you should be writing a UI test. If you are both adding UI |
|
142 |
functionality and library functionality, you will want to write tests for |
|
143 |
both the UI and the core behaviours. We call UI tests 'blackbox' tests |
|
144 |
and they belong in ``bzrlib/tests/blackbox/*.py``. |
|
145 |
||
146 |
When writing blackbox tests please honour the following conventions: |
|
147 |
||
148 |
1. Place the tests for the command 'name' in |
|
149 |
bzrlib/tests/blackbox/test_name.py. This makes it easy for developers |
|
150 |
to locate the test script for a faulty command. |
|
151 |
||
152 |
2. Use the 'self.run_bzr("name")' utility function to invoke the command |
|
153 |
rather than running bzr in a subprocess or invoking the |
|
154 |
cmd_object.run() method directly. This is a lot faster than |
|
155 |
subprocesses and generates the same logging output as running it in a |
|
156 |
subprocess (which invoking the method directly does not). |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
157 |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
158 |
3. Only test the one command in a single test script. Use the bzrlib |
159 |
library when setting up tests and when evaluating the side-effects of |
|
160 |
the command. We do this so that the library api has continual pressure |
|
161 |
on it to be as functional as the command line in a simple manner, and |
|
162 |
to isolate knock-on effects throughout the blackbox test suite when a |
|
163 |
command changes its name or signature. Ideally only the tests for a |
|
164 |
given command are affected when a given command is changed. |
|
165 |
||
166 |
4. If you have a test which does actually require running bzr in a |
|
167 |
subprocess you can use ``run_bzr_subprocess``. By default the spawned |
|
168 |
process will not load plugins unless ``--allow-plugins`` is supplied. |
|
169 |
||
170 |
||
171 |
Per-implementation tests |
|
172 |
~~~~~~~~~~~~~~~~~~~~~~~~ |
|
173 |
||
174 |
Per-implementation tests are tests that are defined once and then run |
|
175 |
against multiple implementations of an interface. For example, |
|
4913.3.7
by John Arbash Meinel
Doc updates for permute_for_extension |
176 |
``per_transport.py`` defines tests that all Transport implementations |
177 |
(local filesystem, HTTP, and so on) must pass. They are found in |
|
178 |
``bzrlib/tests/per_*/*.py``, and ``bzrlib/tests/per_*.py``. |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
179 |
|
180 |
These are really a sub-category of unit tests, but an important one. |
|
181 |
||
4913.3.7
by John Arbash Meinel
Doc updates for permute_for_extension |
182 |
Along the same lines are tests for extension modules. We generally have |
183 |
both a pure-python and a compiled implementation for each module. As such, |
|
184 |
we want to run the same tests against both implementations. These can |
|
185 |
generally be found in ``bzrlib/tests/*__*.py`` since extension modules are |
|
186 |
usually prefixed with an underscore. Since there are only two |
|
187 |
implementations, we have a helper function |
|
188 |
``bzrlib.tests.permute_for_extension``, which can simplify the |
|
189 |
``load_tests`` implementation. |
|
190 |
||
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
191 |
|
192 |
Doctests |
|
193 |
~~~~~~~~ |
|
194 |
||
195 |
We make selective use of doctests__. In general they should provide |
|
196 |
*examples* within the API documentation which can incidentally be tested. We |
|
197 |
don't try to test every important case using doctests |--| regular Python |
|
198 |
tests are generally a better solution. That is, we just use doctests to |
|
199 |
make our documentation testable, rather than as a way to make tests. |
|
200 |
||
201 |
Most of these are in ``bzrlib/doc/api``. More additions are welcome. |
|
202 |
||
203 |
__ http://docs.python.org/lib/module-doctest.html |
|
204 |
||
205 |
||
4665.5.20
by Vincent Ladeuil
Fixed as per Martin's review. |
206 |
Shell-like tests |
4917.2.1
by Martin Pool
Add better example for ScriptRunner and tweak its place in the document hierarchy |
207 |
---------------- |
4665.5.20
by Vincent Ladeuil
Fixed as per Martin's review. |
208 |
|
209 |
``bzrlib/tests/script.py`` allows users to write tests in a syntax very close to a shell session, |
|
210 |
using a restricted and limited set of commands that should be enough to mimic |
|
211 |
most of the behaviours. |
|
212 |
||
213 |
A script is a set of commands, each command is composed of: |
|
214 |
||
215 |
* one mandatory command line, |
|
216 |
* one optional set of input lines to feed the command, |
|
217 |
* one optional set of output expected lines, |
|
218 |
* one optional set of error expected lines. |
|
219 |
||
220 |
Input, output and error lines can be specified in any order. |
|
221 |
||
222 |
Except for the expected output, all lines start with a special |
|
223 |
string (based on their origin when used under a Unix shell): |
|
224 |
||
225 |
* '$ ' for the command, |
|
226 |
* '<' for input, |
|
227 |
* nothing for output, |
|
228 |
* '2>' for errors, |
|
229 |
||
230 |
Comments can be added anywhere, they start with '#' and end with |
|
231 |
the line. |
|
232 |
||
233 |
The execution stops as soon as an expected output or an expected error is not |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
234 |
matched. |
4665.5.20
by Vincent Ladeuil
Fixed as per Martin's review. |
235 |
|
236 |
When no output is specified, any ouput from the command is accepted |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
237 |
and execution continue. |
4665.5.20
by Vincent Ladeuil
Fixed as per Martin's review. |
238 |
|
239 |
If an error occurs and no expected error is specified, the execution stops. |
|
240 |
||
241 |
An error is defined by a returned status different from zero, not by the |
|
242 |
presence of text on the error stream. |
|
243 |
||
244 |
The matching is done on a full string comparison basis unless '...' is used, in |
|
245 |
which case expected output/errors can be less precise. |
|
246 |
||
247 |
Examples: |
|
248 |
||
249 |
The following will succeeds only if 'bzr add' outputs 'adding file':: |
|
250 |
||
251 |
$ bzr add file |
|
252 |
>adding file |
|
253 |
||
254 |
If you want the command to succeed for any output, just use:: |
|
255 |
||
256 |
$ bzr add file |
|
257 |
||
258 |
The following will stop with an error:: |
|
259 |
||
260 |
$ bzr not-a-command |
|
261 |
||
262 |
If you want it to succeed, use:: |
|
263 |
||
264 |
$ bzr not-a-command |
|
265 |
2> bzr: ERROR: unknown command "not-a-command" |
|
266 |
||
267 |
You can use ellipsis (...) to replace any piece of text you don't want to be |
|
268 |
matched exactly:: |
|
269 |
||
270 |
$ bzr branch not-a-branch |
|
271 |
2>bzr: ERROR: Not a branch...not-a-branch/". |
|
272 |
||
273 |
This can be used to ignore entire lines too:: |
|
274 |
||
275 |
$ cat |
|
276 |
<first line |
|
277 |
<second line |
|
278 |
<third line |
|
279 |
# And here we explain that surprising fourth line |
|
280 |
<fourth line |
|
281 |
<last line |
|
282 |
>first line |
|
283 |
>... |
|
284 |
>last line |
|
285 |
||
286 |
You can check the content of a file with cat:: |
|
287 |
||
288 |
$ cat <file |
|
289 |
>expected content |
|
290 |
||
291 |
You can also check the existence of a file with cat, the following will fail if |
|
292 |
the file doesn't exist:: |
|
293 |
||
294 |
$ cat file |
|
295 |
||
4917.2.1
by Martin Pool
Add better example for ScriptRunner and tweak its place in the document hierarchy |
296 |
The actual use of ScriptRunner within a TestCase looks something like |
297 |
this:: |
|
298 |
||
299 |
def test_unshelve_keep(self): |
|
300 |
# some setup here |
|
301 |
sr = ScriptRunner() |
|
302 |
sr.run_script(self, ''' |
|
303 |
$ bzr add file |
|
304 |
$ bzr shelve --all -m Foo |
|
305 |
$ bzr shelve --list |
|
306 |
1: Foo |
|
307 |
$ bzr unshelve --keep |
|
308 |
$ bzr shelve --list |
|
309 |
1: Foo |
|
310 |
$ cat file |
|
311 |
contents of file |
|
312 |
''') |
|
313 |
||
4665.5.20
by Vincent Ladeuil
Fixed as per Martin's review. |
314 |
|
315 |
||
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
316 |
.. Effort tests |
317 |
.. ~~~~~~~~~~~~ |
|
318 |
||
319 |
||
320 |
||
321 |
Skipping tests |
|
322 |
-------------- |
|
323 |
||
324 |
In our enhancements to unittest we allow for some addition results beyond |
|
325 |
just success or failure. |
|
326 |
||
327 |
If a test can't be run, it can say that it's skipped by raising a special |
|
328 |
exception. This is typically used in parameterized tests |--| for example |
|
329 |
if a transport doesn't support setting permissions, we'll skip the tests |
|
330 |
that relating to that. :: |
|
331 |
||
332 |
try: |
|
333 |
return self.branch_format.initialize(repo.bzrdir) |
|
334 |
except errors.UninitializableFormat: |
|
335 |
raise tests.TestSkipped('Uninitializable branch format') |
|
336 |
||
337 |
Raising TestSkipped is a good idea when you want to make it clear that the |
|
338 |
test was not run, rather than just returning which makes it look as if it |
|
339 |
was run and passed. |
|
340 |
||
341 |
Several different cases are distinguished: |
|
342 |
||
343 |
TestSkipped |
|
344 |
Generic skip; the only type that was present up to bzr 0.18. |
|
345 |
||
346 |
TestNotApplicable |
|
347 |
The test doesn't apply to the parameters with which it was run. |
|
348 |
This is typically used when the test is being applied to all |
|
349 |
implementations of an interface, but some aspects of the interface |
|
350 |
are optional and not present in particular concrete |
|
351 |
implementations. (Some tests that should raise this currently |
|
352 |
either silently return or raise TestSkipped.) Another option is |
|
353 |
to use more precise parameterization to avoid generating the test |
|
354 |
at all. |
|
355 |
||
356 |
UnavailableFeature |
|
357 |
The test can't be run because a dependency (typically a Python |
|
358 |
library) is not available in the test environment. These |
|
359 |
are in general things that the person running the test could fix |
|
360 |
by installing the library. It's OK if some of these occur when |
|
361 |
an end user runs the tests or if we're specifically testing in a |
|
362 |
limited environment, but a full test should never see them. |
|
363 |
||
364 |
See `Test feature dependencies`_ below. |
|
365 |
||
366 |
KnownFailure |
|
367 |
The test exists but is known to fail, for example this might be |
|
368 |
appropriate to raise if you've committed a test for a bug but not |
|
369 |
the fix for it, or if something works on Unix but not on Windows. |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
370 |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
371 |
Raising this allows you to distinguish these failures from the |
372 |
ones that are not expected to fail. If the test would fail |
|
373 |
because of something we don't expect or intend to fix, |
|
374 |
KnownFailure is not appropriate, and TestNotApplicable might be |
|
375 |
better. |
|
376 |
||
377 |
KnownFailure should be used with care as we don't want a |
|
378 |
proliferation of quietly broken tests. |
|
379 |
||
4873.2.4
by John Arbash Meinel
Add a NEWS entry and an entry in the testing docs about ModuleAvailableFeature |
380 |
ModuleAvailableFeature |
381 |
A helper for handling running tests based on whether a python |
|
382 |
module is available. This can handle 3rd-party dependencies (is |
|
383 |
``paramiko`` available?) as well as stdlib (``termios``) or |
|
384 |
extension modules (``bzrlib._groupcompress_pyx``). You create a |
|
385 |
new feature instance with:: |
|
386 |
||
387 |
MyModuleFeature = ModuleAvailableFeature('bzrlib.something') |
|
388 |
||
389 |
... |
|
390 |
def test_something(self): |
|
391 |
self.requireFeature(MyModuleFeature) |
|
392 |
something = MyModuleFeature.module |
|
393 |
||
394 |
||
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
395 |
We plan to support three modes for running the test suite to control the |
396 |
interpretation of these results. Strict mode is for use in situations |
|
397 |
like merges to the mainline and releases where we want to make sure that |
|
398 |
everything that can be tested has been tested. Lax mode is for use by |
|
399 |
developers who want to temporarily tolerate some known failures. The |
|
400 |
default behaviour is obtained by ``bzr selftest`` with no options, and |
|
401 |
also (if possible) by running under another unittest harness. |
|
402 |
||
403 |
======================= ======= ======= ======== |
|
404 |
result strict default lax |
|
405 |
======================= ======= ======= ======== |
|
406 |
TestSkipped pass pass pass |
|
407 |
TestNotApplicable pass pass pass |
|
3619.3.2
by Andrew Bennetts
Remove references to unimplemented TestPlatformLimit, remove some redundant (and misplaced) text from 'Test feature dependencies'. |
408 |
UnavailableFeature fail pass pass |
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
409 |
KnownFailure fail pass pass |
410 |
======================= ======= ======= ======== |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
411 |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
412 |
|
413 |
Test feature dependencies |
|
414 |
------------------------- |
|
415 |
||
416 |
Writing tests that require a feature |
|
417 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
418 |
||
419 |
Rather than manually checking the environment in each test, a test class |
|
420 |
can declare its dependence on some test features. The feature objects are |
|
421 |
checked only once for each run of the whole test suite. |
|
422 |
||
423 |
(For historical reasons, as of May 2007 many cases that should depend on |
|
424 |
features currently raise TestSkipped.) |
|
425 |
||
426 |
For example:: |
|
427 |
||
428 |
class TestStrace(TestCaseWithTransport): |
|
429 |
||
430 |
_test_needs_features = [StraceFeature] |
|
431 |
||
3619.3.2
by Andrew Bennetts
Remove references to unimplemented TestPlatformLimit, remove some redundant (and misplaced) text from 'Test feature dependencies'. |
432 |
This means all tests in this class need the feature. If the feature is |
433 |
not available the test will be skipped using UnavailableFeature. |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
434 |
|
435 |
Individual tests can also require a feature using the ``requireFeature`` |
|
436 |
method:: |
|
437 |
||
438 |
self.requireFeature(StraceFeature) |
|
439 |
||
440 |
Features already defined in bzrlib.tests include: |
|
441 |
||
442 |
- SymlinkFeature, |
|
443 |
- HardlinkFeature, |
|
444 |
- OsFifoFeature, |
|
445 |
- UnicodeFilenameFeature, |
|
446 |
- FTPServerFeature, and |
|
447 |
- CaseInsensitiveFilesystemFeature. |
|
448 |
||
449 |
||
450 |
Defining a new feature that tests can require |
|
451 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
452 |
||
453 |
New features for use with ``_test_needs_features`` or ``requireFeature`` |
|
454 |
are defined by subclassing ``bzrlib.tests.Feature`` and overriding the |
|
455 |
``_probe`` and ``feature_name`` methods. For example:: |
|
456 |
||
457 |
class _SymlinkFeature(Feature): |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
458 |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
459 |
def _probe(self): |
460 |
return osutils.has_symlinks() |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
461 |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
462 |
def feature_name(self): |
463 |
return 'symlinks' |
|
4853.1.1
by Patrick Regan
Removed trailing whitespace from files in doc directory |
464 |
|
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
465 |
SymlinkFeature = _SymlinkFeature() |
466 |
||
467 |
||
468 |
Testing exceptions and errors |
|
469 |
----------------------------- |
|
470 |
||
471 |
It's important to test handling of errors and exceptions. Because this |
|
472 |
code is often not hit in ad-hoc testing it can often have hidden bugs -- |
|
473 |
it's particularly common to get NameError because the exception code |
|
474 |
references a variable that has since been renamed. |
|
475 |
||
476 |
.. TODO: Something about how to provoke errors in the right way? |
|
477 |
||
478 |
In general we want to test errors at two levels: |
|
479 |
||
480 |
1. A test in ``test_errors.py`` checking that when the exception object is |
|
481 |
constructed with known parameters it produces an expected string form. |
|
482 |
This guards against mistakes in writing the format string, or in the |
|
483 |
``str`` representations of its parameters. There should be one for |
|
484 |
each exception class. |
|
485 |
||
486 |
2. Tests that when an api is called in a particular situation, it raises |
|
487 |
an error of the expected class. You should typically use |
|
488 |
``assertRaises``, which in the Bazaar test suite returns the exception |
|
489 |
object to allow you to examine its parameters. |
|
490 |
||
491 |
In some cases blackbox tests will also want to check error reporting. But |
|
492 |
it can be difficult to provoke every error through the commandline |
|
493 |
interface, so those tests are only done as needed |--| eg in response to a |
|
494 |
particular bug or if the error is reported in an unusual way(?) Blackbox |
|
495 |
tests should mostly be testing how the command-line interface works, so |
|
496 |
should only test errors if there is something particular to the cli in how |
|
497 |
they're displayed or handled. |
|
498 |
||
499 |
||
500 |
Testing warnings |
|
501 |
---------------- |
|
502 |
||
503 |
The Python ``warnings`` module is used to indicate a non-fatal code |
|
504 |
problem. Code that's expected to raise a warning can be tested through |
|
505 |
callCatchWarnings. |
|
506 |
||
507 |
The test suite can be run with ``-Werror`` to check no unexpected errors |
|
508 |
occur. |
|
509 |
||
510 |
However, warnings should be used with discretion. It's not an appropriate |
|
511 |
way to give messages to the user, because the warning is normally shown |
|
512 |
only once per source line that causes the problem. You should also think |
|
513 |
about whether the warning is serious enought that it should be visible to |
|
514 |
users who may not be able to fix it. |
|
515 |
||
516 |
||
517 |
Interface implementation testing and test scenarios |
|
518 |
--------------------------------------------------- |
|
519 |
||
520 |
There are several cases in Bazaar of multiple implementations of a common |
|
521 |
conceptual interface. ("Conceptual" because it's not necessary for all |
|
522 |
the implementations to share a base class, though they often do.) |
|
523 |
Examples include transports and the working tree, branch and repository |
|
524 |
classes. |
|
525 |
||
526 |
In these cases we want to make sure that every implementation correctly |
|
527 |
fulfils the interface requirements. For example, every Transport should |
|
528 |
support the ``has()`` and ``get()`` and ``clone()`` methods. We have a |
|
529 |
sub-suite of tests in ``test_transport_implementations``. (Most |
|
530 |
per-implementation tests are in submodules of ``bzrlib.tests``, but not |
|
531 |
the transport tests at the moment.) |
|
532 |
||
533 |
These tests are repeated for each registered Transport, by generating a |
|
534 |
new TestCase instance for the cross product of test methods and transport |
|
535 |
implementations. As each test runs, it has ``transport_class`` and |
|
536 |
``transport_server`` set to the class it should test. Most tests don't |
|
537 |
access these directly, but rather use ``self.get_transport`` which returns |
|
538 |
a transport of the appropriate type. |
|
539 |
||
540 |
The goal is to run per-implementation only the tests that relate to that |
|
541 |
particular interface. Sometimes we discover a bug elsewhere that happens |
|
542 |
with only one particular transport. Once it's isolated, we can consider |
|
543 |
whether a test should be added for that particular implementation, |
|
544 |
or for all implementations of the interface. |
|
545 |
||
546 |
The multiplication of tests for different implementations is normally |
|
547 |
accomplished by overriding the ``load_tests`` function used to load tests |
|
548 |
from a module. This function typically loads all the tests, then applies |
|
549 |
a TestProviderAdapter to them, which generates a longer suite containing |
|
550 |
all the test variations. |
|
551 |
||
552 |
See also `Per-implementation tests`_ (above). |
|
553 |
||
554 |
||
555 |
Test scenarios |
|
556 |
-------------- |
|
557 |
||
558 |
Some utilities are provided for generating variations of tests. This can |
|
559 |
be used for per-implementation tests, or other cases where the same test |
|
560 |
code needs to run several times on different scenarios. |
|
561 |
||
562 |
The general approach is to define a class that provides test methods, |
|
563 |
which depend on attributes of the test object being pre-set with the |
|
564 |
values to which the test should be applied. The test suite should then |
|
565 |
also provide a list of scenarios in which to run the tests. |
|
566 |
||
567 |
Typically ``multiply_tests_from_modules`` should be called from the test |
|
568 |
module's ``load_tests`` function. |
|
569 |
||
570 |
||
571 |
Test support |
|
572 |
------------ |
|
573 |
||
574 |
We have a rich collection of tools to support writing tests. Please use |
|
575 |
them in preference to ad-hoc solutions as they provide portability and |
|
576 |
performance benefits. |
|
577 |
||
578 |
||
579 |
TestCase and its subclasses |
|
580 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
581 |
||
582 |
The ``bzrlib.tests`` module defines many TestCase classes to help you |
|
583 |
write your tests. |
|
584 |
||
585 |
TestCase |
|
586 |
A base TestCase that extends the Python standard library's |
|
587 |
TestCase in several ways. It adds more assertion methods (e.g. |
|
588 |
``assertContainsRe``), ``addCleanup``, and other features (see its API |
|
589 |
docs for details). It also has a ``setUp`` that makes sure that |
|
590 |
global state like registered hooks and loggers won't interfere with |
|
591 |
your test. All tests should use this base class (whether directly or |
|
592 |
via a subclass). |
|
593 |
||
594 |
TestCaseWithMemoryTransport |
|
595 |
Extends TestCase and adds methods like ``get_transport``, |
|
596 |
``make_branch`` and ``make_branch_builder``. The files created are |
|
597 |
stored in a MemoryTransport that is discarded at the end of the test. |
|
598 |
This class is good for tests that need to make branches or use |
|
599 |
transports, but that don't require storing things on disk. All tests |
|
600 |
that create bzrdirs should use this base class (either directly or via |
|
601 |
a subclass) as it ensures that the test won't accidentally operate on |
|
602 |
real branches in your filesystem. |
|
603 |
||
604 |
TestCaseInTempDir |
|
605 |
Extends TestCaseWithMemoryTransport. For tests that really do need |
|
606 |
files to be stored on disk, e.g. because a subprocess uses a file, or |
|
607 |
for testing functionality that accesses the filesystem directly rather |
|
608 |
than via the Transport layer (such as dirstate). |
|
609 |
||
610 |
TestCaseWithTransport |
|
611 |
Extends TestCaseInTempDir. Provides ``get_url`` and |
|
612 |
``get_readonly_url`` facilities. Subclasses can control the |
|
613 |
transports used by setting ``vfs_transport_factory``, |
|
614 |
``transport_server`` and/or ``transport_readonly_server``. |
|
615 |
||
616 |
||
617 |
See the API docs for more details. |
|
618 |
||
619 |
||
620 |
BranchBuilder |
|
621 |
~~~~~~~~~~~~~ |
|
622 |
||
623 |
When writing a test for a feature, it is often necessary to set up a |
|
624 |
branch with a certain history. The ``BranchBuilder`` interface allows the |
|
625 |
creation of test branches in a quick and easy manner. Here's a sample |
|
626 |
session:: |
|
627 |
||
628 |
builder = self.make_branch_builder('relpath') |
|
629 |
builder.build_commit() |
|
630 |
builder.build_commit() |
|
631 |
builder.build_commit() |
|
632 |
branch = builder.get_branch() |
|
633 |
||
634 |
``make_branch_builder`` is a method of ``TestCaseWithMemoryTransport``. |
|
635 |
||
636 |
Note that many current tests create test branches by inheriting from |
|
637 |
``TestCaseWithTransport`` and using the ``make_branch_and_tree`` helper to |
|
638 |
give them a ``WorkingTree`` that they can commit to. However, using the |
|
639 |
newer ``make_branch_builder`` helper is preferred, because it can build |
|
640 |
the changes in memory, rather than on disk. Tests that are explictly |
|
641 |
testing how we work with disk objects should, of course, use a real |
|
642 |
``WorkingTree``. |
|
643 |
||
644 |
Please see bzrlib.branchbuilder for more details. |
|
645 |
||
4070.5.2
by Martin Pool
Recommend setting timestamp in BranchBuilder |
646 |
If you're going to examine the commit timestamps e.g. in a test for log |
647 |
output, you should set the timestamp on the tree, rather than using fuzzy |
|
648 |
matches in the test. |
|
649 |
||
3619.3.1
by Andrew Bennetts
Move the notes on writing tests out of HACKING into a new file, and improve |
650 |
|
651 |
TreeBuilder |
|
652 |
~~~~~~~~~~~ |
|
653 |
||
654 |
The ``TreeBuilder`` interface allows the construction of arbitrary trees |
|
655 |
with a declarative interface. A sample session might look like:: |
|
656 |
||
657 |
tree = self.make_branch_and_tree('path') |
|
658 |
builder = TreeBuilder() |
|
659 |
builder.start_tree(tree) |
|
660 |
builder.build(['foo', "bar/", "bar/file"]) |
|
661 |
tree.commit('commit the tree') |
|
662 |
builder.finish_tree() |
|
663 |
||
664 |
Usually a test will create a tree using ``make_branch_and_memory_tree`` (a |
|
665 |
method of ``TestCaseWithMemoryTransport``) or ``make_branch_and_tree`` (a |
|
666 |
method of ``TestCaseWithTransport``). |
|
667 |
||
668 |
Please see bzrlib.treebuilder for more details. |
|
669 |
||
670 |
||
671 |
.. |--| unicode:: U+2014 |
|
672 |
||
673 |
.. |
|
674 |
vim: ft=rst tw=74 ai |