1- Writing Python Test Cases
2- -------------------------
1+ Writing Python Regression Tests
2+ ------ -------------------------
33 Skip Montanaro
4+ 5+
6+
7+ Introduction
48
59If you add a new module to Python or modify the functionality of an existing
6- module, it is your responsibility to write one or more test cases to test
7- that new functionality. The mechanics of the test system are fairly
8- straightforward. If you are writing test cases for module zyzzyx, you need
9- to create a file in .../Lib/test named test_zyzzyx.py and an expected output
10- file in .../Lib/test/output named test_zyzzyx ("..." represents the
11- top-level directory in the Python source tree, the directory containing the
12- configure script). Generate the initial version of the test output file by
13- executing:
14-
15- cd .../Lib/test
16- python regrtest.py -g test_zyzzyx.py
17-
18- Any time you modify test_zyzzyx.py you need to generate a new expected
10+ module, you should write one or more test cases to exercise that new
11+ functionality. The mechanics of how the test system operates are fairly
12+ straightforward. When a test case is run, the output is compared with the
13+ expected output that is stored in .../Lib/test/output. If the test runs to
14+ completion and the actual and expected outputs match, the test succeeds, if
15+ not, it fails. If an ImportError is raised, the test is not run.
16+
17+ You will be writing unit tests (isolated tests of functions and objects
18+ defined by the module) using white box techniques. Unlike black box
19+ testing, where you only have the external interfaces to guide your test case
20+ writing, in white box testing you can see the code being tested and tailor
21+ your test cases to exercise it more completely. In particular, you will be
22+ able to refer to the C and Python code in the CVS repository when writing
23+ your regression test cases.
24+
25+
26+ Executing Test Cases
27+
28+ If you are writing test cases for module spam, you need to create a file
29+ in .../Lib/test named test_spam.py and an expected output file in
30+ .../Lib/test/output named test_spam ("..." represents the top-level
31+ directory in the Python source tree, the directory containing the configure
32+ script). From the top-level directory, generate the initial version of the
33+ test output file by executing:
34+
35+ ./python Lib/test/regrtest.py -g test_spam.py
36+
37+ Any time you modify test_spam.py you need to generate a new expected
1938output file. Don't forget to desk check the generated output to make sure
2039it's really what you expected to find! To run a single test after modifying
2140a module, simply run regrtest.py without the -g flag:
2241
23- cd .../Lib/test
24- python regrtest.py test_zyzzyx.py
42+ ./python Lib/test/regrtest.py test_spam.py
43+
44+ While debugging a regression test, you can of course execute it
45+ independently of the regression testing framework and see what it prints:
46+
47+ ./python Lib/test/test_spam.py
2548
2649To run the entire test suite, make the "test" target at the top level:
2750
28- cd ...
2951 make test
3052
31- Test cases generate output based upon computed values and branches taken in
32- the code. When executed, regrtest.py compares the actual output generated
33- by executing the test case with the expected output and reports success or
34- failure. It stands to reason that if the actual and expected outputs are to
35- match, they must not contain any machine dependencies. This means
36- your test cases should not print out absolute machine addresses or floating
37- point numbers with large numbers of significant digits.
53+ On non-Unix platforms where make may not be available, you can simply
54+ execute the two runs of regrtest (optimized and non-optimized) directly:
55+
56+ ./python Lib/test/regrtest.py
57+ ./python -O Lib/test/regrtest.py
58+
59+
60+ Test cases generate output based upon values computed by the test code.
61+ When executed, regrtest.py compares the actual output generated by executing
62+ the test case with the expected output and reports success or failure. It
63+ stands to reason that if the actual and expected outputs are to match, they
64+ must not contain any machine dependencies. This means your test cases
65+ should not print out absolute machine addresses (e.g. the return value of
66+ the id() builtin function) or floating point numbers with large numbers of
67+ significant digits (unless you understand what you are doing!).
68+
69+
70+ Test Case Writing Tips
3871
3972Writing good test cases is a skilled task and is too complex to discuss in
4073detail in this short document. Many books have been written on the subject.
@@ -46,32 +79,88 @@ object-oriented software revolution, so doesn't cover that subject at all.
4679Unfortunately, it is very expensive (about $100 new). If you can borrow it
4780or find it used (around $20), I strongly urge you to pick up a copy.
4881
49- As an author of at least part of a module, you will be writing unit tests
50- (isolated tests of functions and objects defined by the module) using white
51- box techniques. (Unlike black box testing, where you only have the external
52- interfaces to guide your test case writing, in white box testing you can see
53- the code being tested and tailor your test cases to exercise it more
54- completely).
55-
5682The most important goal when writing test cases is to break things. A test
57- case that doesn't uncover a bug is less valuable than one that does. In
58- designing test cases you should pay attention to the following:
59-
60- 1. Your test cases should exercise all the functions and objects defined
61- in the module, not just the ones meant to be called by users of your
62- module. This may require you to write test code that uses the module
63- in ways you don't expect (explicitly calling internal functions, for
64- example - see test_atexit.py).
65-
66- 2. You should consider any boundary values that may tickle exceptional
67- conditions (e.g. if you were testing a division module you might well
68- want to generate tests with numerators and denominators at the limits
69- of floating point and integer numbers on the machine performing the
70- tests as well as a denominator of zero).
71-
72- 3. You should exercise as many paths through the code as possible. This
73- may not always be possible, but is a goal to strive for. In
74- particular, when considering if statements (or their equivalent), you
75- want to create test cases that exercise both the true and false
76- branches. For while and for statements, you should create test cases
77- that exercise the loop zero, one and multiple times.
83+ case that doesn't uncover a bug is much less valuable than one that does.
84+ In designing test cases you should pay attention to the following:
85+
86+ * Your test cases should exercise all the functions and objects defined
87+ in the module, not just the ones meant to be called by users of your
88+ module. This may require you to write test code that uses the module
89+ in ways you don't expect (explicitly calling internal functions, for
90+ example - see test_atexit.py).
91+
92+ * You should consider any boundary values that may tickle exceptional
93+ conditions (e.g. if you were writing regression tests for division,
94+ you might well want to generate tests with numerators and denominators
95+ at the limits of floating point and integer numbers on the machine
96+ performing the tests as well as a denominator of zero).
97+
98+ * You should exercise as many paths through the code as possible. This
99+ may not always be possible, but is a goal to strive for. In
100+ particular, when considering if statements (or their equivalent), you
101+ want to create test cases that exercise both the true and false
102+ branches. For loops, you should create test cases that exercise the
103+ loop zero, one and multiple times.
104+
105+ * You should test with obviously invalid input. If you know that a
106+ function requires an integer input, try calling it with other types of
107+ objects to see how it responds.
108+
109+ * You should test with obviously out-of-range input. If the domain of a
110+ function is only defined for positive integers, try calling it with a
111+ negative integer.
112+
113+ * If you are going to fix a bug that wasn't uncovered by an existing
114+ test, try to write a test case that exposes the bug (preferably before
115+ fixing it).
116+
117+
118+ Regression Test Writing Rules
119+
120+ Each test case is different. There is no "standard" form for a Python
121+ regression test case, though there are some general rules:
122+
123+ * If your test case detects a failure, raise TestFailed (found in
124+ test_support).
125+
126+ * Import everything you'll need as early as possible.
127+
128+ * If you'll be importing objects from a module that is at least
129+ partially platform-dependent, only import those objects you need for
130+ the current test case to avoid spurious ImportError exceptions that
131+ prevent the test from running to completion.
132+
133+ * Print all your test case results using the print statement. For
134+ non-fatal errors, print an error message (or omit a successful
135+ completion print) to indicate the failure, but proceed instead of
136+ raising TestFailed.
137+
138+
139+ Miscellaneous
140+
141+ There is a test_support module you can import from your test case. It
142+ provides the following useful objects:
143+
144+ * TestFailed - raise this exception when your regression test detects a
145+ failure.
146+
147+ * findfile(file) - you can call this function to locate a file somewhere
148+ along sys.path or in the Lib/test tree - see test_linuxaudiodev.py for
149+ an example of its use.
150+
151+ * verbose - you can use this variable to control print output. Many
152+ modules use it. Search for "verbose" in the test_*.py files to see
153+ lots of examples.
154+
155+ * fcmp(x,y) - you can call this function to compare two floating point
156+ numbers when you expect them to only be approximately equal withing a
157+ fuzz factor (test_support.FUZZ, which defaults to 1e-6).
158+
159+ Python and C statement coverage results are currently available at
160+
161+ http://www.musi-cal.com/~skip/python/Python/dist/src/
162+
163+ As of this writing (July, 2000) these results are being generated nightly.
164+ You can refer to the summaries and the test coverage output files to see
165+ where coverage is adequate or lacking and write test cases to beef up the
166+ coverage.
0 commit comments