Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 1 | Writing Python Regression Tests |
| 2 | ------------------------------- |
| 3 | Skip Montanaro |
| 4 | (skip@mojam.com) |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 5 | |
| 6 | |
| 7 | Introduction |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 8 | |
| 9 | If you add a new module to Python or modify the functionality of an existing |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 10 | module, you should write one or more test cases to exercise that new |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 11 | functionality. There are different ways to do this within the regression |
| 12 | testing facility provided with Python; any particular test should use only |
| 13 | one of these options. Each option requires writing a test module using the |
| 14 | conventions of the the selected option: |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 15 | |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 16 | - PyUnit based tests |
| 17 | - doctest based tests |
| 18 | - "traditional" Python test modules |
| 19 | |
| 20 | Regardless of the mechanics of the testing approach you choose, |
| 21 | you will be writing unit tests (isolated tests of functions and objects |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 22 | defined by the module) using white box techniques. Unlike black box |
| 23 | testing, where you only have the external interfaces to guide your test case |
| 24 | writing, in white box testing you can see the code being tested and tailor |
| 25 | your test cases to exercise it more completely. In particular, you will be |
| 26 | able to refer to the C and Python code in the CVS repository when writing |
| 27 | your regression test cases. |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 28 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 29 | |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 30 | PyUnit based tests |
| 31 | |
| 32 | The PyUnit framework is based on the ideas of unit testing as espoused |
| 33 | by Kent Beck and the Extreme Programming (XP) movement. The specific |
| 34 | interface provided by the framework is tightly based on the JUnit |
| 35 | Java implementation of Beck's original SmallTalk test framework. Please |
| 36 | see the documentation of the unittest module for detailed information on |
| 37 | the interface and general guidelines on writing PyUnit based tests. |
| 38 | |
| 39 | The test_support helper module provides a single function for use by |
| 40 | PyUnit based tests in the Python regression testing framework: |
| 41 | run_unittest() takes a unittest.TestCase derived class as a parameter |
| 42 | and runs the tests defined in that class. All test methods in the |
| 43 | Python regression framework have names that start with "test_" and use |
| 44 | lower-case names with words separated with underscores. |
| 45 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 46 | |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 47 | doctest based tests |
| 48 | |
| 49 | Tests written to use doctest are actually part of the docstrings for |
| 50 | the module being tested. Each test is written as a display of an |
| 51 | interactive session, including the Python prompts, statements that would |
| 52 | be typed by the user, and the output of those statements (including |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 53 | tracebacks, although only the exception msg needs to be retained then). |
| 54 | The module in the test package is simply a wrapper that causes doctest |
| 55 | to run over the tests in the module. The test for the difflib module |
| 56 | provides a convenient example: |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 57 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 58 | from test_support import verbose |
| 59 | import doctest, difflib |
| 60 | doctest.testmod(difflib, verbose=verbose) |
| 61 | |
| 62 | If the test is successful, nothing is written to stdout (so you should not |
| 63 | create a corresponding output/test_difflib file), but running regrtest |
| 64 | with -v will give a detailed report, the same as if passing -v to doctest |
| 65 | (that's what importing verbose from test_support accomplishes). |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 66 | |
| 67 | See the documentation for the doctest module for information on |
| 68 | writing tests using the doctest framework. |
| 69 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 70 | |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 71 | "traditional" Python test modules |
| 72 | |
| 73 | The mechanics of how the "traditional" test system operates are fairly |
| 74 | straightforward. When a test case is run, the output is compared with the |
| 75 | expected output that is stored in .../Lib/test/output. If the test runs to |
| 76 | completion and the actual and expected outputs match, the test succeeds, if |
| 77 | not, it fails. If an ImportError or test_support.TestSkipped error is |
| 78 | raised, the test is not run. |
| 79 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 80 | |
| 81 | Executing Test Cases |
| 82 | |
| 83 | If you are writing test cases for module spam, you need to create a file |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 84 | in .../Lib/test named test_spam.py. In addition, if the tests are expected |
| 85 | to write to stdout during a successful run, you also need to create an |
| 86 | expected output file in .../Lib/test/output named test_spam ("..." |
| 87 | represents the top-level directory in the Python source tree, the directory |
| 88 | containing the configure script). If needed, generate the initial version |
| 89 | of the test output file by executing: |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 90 | |
| 91 | ./python Lib/test/regrtest.py -g test_spam.py |
| 92 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 93 | from the top-level directory. |
Fred Drake | a6daad2 | 2001-05-23 04:57:49 +0000 | [diff] [blame] | 94 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 95 | Any time you modify test_spam.py you need to generate a new expected |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 96 | output file. Don't forget to desk check the generated output to make sure |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 97 | it's really what you expected to find! All in all it's usually better |
| 98 | not to have an expected-out file (note that doctest- and unittest-based |
| 99 | tests do not). |
| 100 | |
| 101 | To run a single test after modifying a module, simply run regrtest.py |
| 102 | without the -g flag: |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 103 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 104 | ./python Lib/test/regrtest.py test_spam.py |
| 105 | |
| 106 | While debugging a regression test, you can of course execute it |
| 107 | independently of the regression testing framework and see what it prints: |
| 108 | |
| 109 | ./python Lib/test/test_spam.py |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 110 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 111 | To run the entire test suite: |
| 112 | |
| 113 | [UNIX, + other platforms where "make" works] Make the "test" target at the |
| 114 | top level: |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 115 | |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 116 | make test |
| 117 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 118 | {WINDOWS] Run rt.bat from your PCBuild directory. Read the comments at |
| 119 | the top of rt.bat for the use of special -d, -O and -q options processed |
| 120 | by rt.bat. |
| 121 | |
| 122 | [OTHER] You can simply execute the two runs of regrtest (optimized and |
| 123 | non-optimized) directly: |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 124 | |
| 125 | ./python Lib/test/regrtest.py |
| 126 | ./python -O Lib/test/regrtest.py |
| 127 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 128 | But note that this way picks up whatever .pyc and .pyo files happen to be |
| 129 | around. The makefile and rt.bat ways run the tests twice, the first time |
| 130 | removing all .pyc and .pyo files from the subtree rooted at Lib/. |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 131 | |
| 132 | Test cases generate output based upon values computed by the test code. |
| 133 | When executed, regrtest.py compares the actual output generated by executing |
| 134 | the test case with the expected output and reports success or failure. It |
| 135 | stands to reason that if the actual and expected outputs are to match, they |
| 136 | must not contain any machine dependencies. This means your test cases |
| 137 | should not print out absolute machine addresses (e.g. the return value of |
| 138 | the id() builtin function) or floating point numbers with large numbers of |
| 139 | significant digits (unless you understand what you are doing!). |
| 140 | |
| 141 | |
| 142 | Test Case Writing Tips |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 143 | |
| 144 | Writing good test cases is a skilled task and is too complex to discuss in |
| 145 | detail in this short document. Many books have been written on the subject. |
| 146 | I'll show my age by suggesting that Glenford Myers' "The Art of Software |
| 147 | Testing", published in 1979, is still the best introduction to the subject |
| 148 | available. It is short (177 pages), easy to read, and discusses the major |
| 149 | elements of software testing, though its publication predates the |
| 150 | object-oriented software revolution, so doesn't cover that subject at all. |
| 151 | Unfortunately, it is very expensive (about $100 new). If you can borrow it |
| 152 | or find it used (around $20), I strongly urge you to pick up a copy. |
| 153 | |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 154 | The most important goal when writing test cases is to break things. A test |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 155 | case that doesn't uncover a bug is much less valuable than one that does. |
| 156 | In designing test cases you should pay attention to the following: |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 157 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 158 | * Your test cases should exercise all the functions and objects defined |
| 159 | in the module, not just the ones meant to be called by users of your |
| 160 | module. This may require you to write test code that uses the module |
| 161 | in ways you don't expect (explicitly calling internal functions, for |
| 162 | example - see test_atexit.py). |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 163 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 164 | * You should consider any boundary values that may tickle exceptional |
| 165 | conditions (e.g. if you were writing regression tests for division, |
| 166 | you might well want to generate tests with numerators and denominators |
| 167 | at the limits of floating point and integer numbers on the machine |
| 168 | performing the tests as well as a denominator of zero). |
Skip Montanaro | 47c60ec | 2000-06-30 06:08:35 +0000 | [diff] [blame] | 169 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 170 | * You should exercise as many paths through the code as possible. This |
| 171 | may not always be possible, but is a goal to strive for. In |
| 172 | particular, when considering if statements (or their equivalent), you |
| 173 | want to create test cases that exercise both the true and false |
| 174 | branches. For loops, you should create test cases that exercise the |
| 175 | loop zero, one and multiple times. |
| 176 | |
| 177 | * You should test with obviously invalid input. If you know that a |
| 178 | function requires an integer input, try calling it with other types of |
| 179 | objects to see how it responds. |
| 180 | |
| 181 | * You should test with obviously out-of-range input. If the domain of a |
| 182 | function is only defined for positive integers, try calling it with a |
| 183 | negative integer. |
| 184 | |
| 185 | * If you are going to fix a bug that wasn't uncovered by an existing |
| 186 | test, try to write a test case that exposes the bug (preferably before |
| 187 | fixing it). |
| 188 | |
Fred Drake | 44b6bd2 | 2000-10-23 16:37:14 +0000 | [diff] [blame] | 189 | * If you need to create a temporary file, you can use the filename in |
| 190 | test_support.TESTFN to do so. It is important to remove the file |
| 191 | when done; other tests should be able to use the name without cleaning |
| 192 | up after your test. |
| 193 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 194 | |
| 195 | Regression Test Writing Rules |
| 196 | |
| 197 | Each test case is different. There is no "standard" form for a Python |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 198 | regression test case, though there are some general rules (note that |
| 199 | these mostly apply only to the "classic" tests; unittest- and doctest- |
| 200 | based tests should follow the conventions natural to those frameworks): |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 201 | |
| 202 | * If your test case detects a failure, raise TestFailed (found in |
| 203 | test_support). |
| 204 | |
| 205 | * Import everything you'll need as early as possible. |
| 206 | |
| 207 | * If you'll be importing objects from a module that is at least |
| 208 | partially platform-dependent, only import those objects you need for |
| 209 | the current test case to avoid spurious ImportError exceptions that |
| 210 | prevent the test from running to completion. |
| 211 | |
| 212 | * Print all your test case results using the print statement. For |
| 213 | non-fatal errors, print an error message (or omit a successful |
| 214 | completion print) to indicate the failure, but proceed instead of |
| 215 | raising TestFailed. |
| 216 | |
Tim Peters | a48b526 | 2000-08-23 05:28:45 +0000 | [diff] [blame] | 217 | * Use "assert" sparingly, if at all. It's usually better to just print |
| 218 | what you got, and rely on regrtest's got-vs-expected comparison to |
| 219 | catch deviations from what you expect. assert statements aren't |
| 220 | executed at all when regrtest is run in -O mode; and, because they |
| 221 | cause the test to stop immediately, can lead to a long & tedious |
| 222 | test-fix, test-fix, test-fix, ... cycle when things are badly broken |
| 223 | (and note that "badly broken" often includes running the test suite |
| 224 | for the first time on new platforms or under new implementations of |
| 225 | the language). |
| 226 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 227 | |
| 228 | Miscellaneous |
| 229 | |
| 230 | There is a test_support module you can import from your test case. It |
| 231 | provides the following useful objects: |
| 232 | |
| 233 | * TestFailed - raise this exception when your regression test detects a |
| 234 | failure. |
| 235 | |
Fred Drake | 62c53dd | 2000-08-21 16:55:57 +0000 | [diff] [blame] | 236 | * TestSkipped - raise this if the test could not be run because the |
| 237 | platform doesn't offer all the required facilities (like large |
| 238 | file support), even if all the required modules are available. |
| 239 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 240 | * verbose - you can use this variable to control print output. Many |
| 241 | modules use it. Search for "verbose" in the test_*.py files to see |
| 242 | lots of examples. |
| 243 | |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 244 | * verify(condition, reason='test failed'). Use this instead of |
| 245 | |
| 246 | assert condition[, reason] |
| 247 | |
| 248 | verify() has two advantages over assert: it works even in -O mode, |
| 249 | and it raises TestFailed on failure instead of AssertionError. |
| 250 | |
| 251 | * TESTFN - a string that should always be used as the filename when you |
| 252 | need to create a temp file. Also use try/finally to ensure that your |
| 253 | temp files are deleted before your test completes. Note that you |
| 254 | cannot unlink an open file on all operating systems, so also be sure |
| 255 | to close temp files before trying to unlink them. |
| 256 | |
| 257 | * sortdict(dict) - acts like repr(dict.items()), but sorts the items |
| 258 | first. This is important when printing a dict value, because the |
| 259 | order of items produced by dict.items() is not defined by the |
| 260 | language. |
| 261 | |
| 262 | * findfile(file) - you can call this function to locate a file somewhere |
| 263 | along sys.path or in the Lib/test tree - see test_linuxaudiodev.py for |
| 264 | an example of its use. |
| 265 | |
Tim Peters | a48b526 | 2000-08-23 05:28:45 +0000 | [diff] [blame] | 266 | * use_large_resources - true iff tests requiring large time or space |
| 267 | should be run. |
| 268 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 269 | * fcmp(x,y) - you can call this function to compare two floating point |
| 270 | numbers when you expect them to only be approximately equal withing a |
| 271 | fuzz factor (test_support.FUZZ, which defaults to 1e-6). |
| 272 | |
Tim Peters | a48b526 | 2000-08-23 05:28:45 +0000 | [diff] [blame] | 273 | NOTE: Always import something from test_support like so: |
| 274 | |
| 275 | from test_support import verbose |
| 276 | |
| 277 | or like so: |
| 278 | |
| 279 | import test_support |
| 280 | ... use test_support.verbose in the code ... |
| 281 | |
| 282 | Never import anything from test_support like this: |
| 283 | |
| 284 | from test.test_support import verbose |
| 285 | |
| 286 | "test" is a package already, so can refer to modules it contains without |
| 287 | "test." qualification. If you do an explicit "test.xxx" qualification, that |
| 288 | can fool Python into believing test.xxx is a module distinct from the xxx |
| 289 | in the current package, and you can end up importing two distinct copies of |
| 290 | xxx. This is especially bad if xxx=test_support, as regrtest.py can (and |
| 291 | routinely does) overwrite its "verbose" and "use_large_resources" |
| 292 | attributes: if you get a second copy of test_support loaded, it may not |
| 293 | have the same values for those as regrtest intended. |
| 294 | |
| 295 | |
Skip Montanaro | e9e5dcd | 2000-07-19 17:19:49 +0000 | [diff] [blame] | 296 | Python and C statement coverage results are currently available at |
| 297 | |
| 298 | http://www.musi-cal.com/~skip/python/Python/dist/src/ |
| 299 | |
| 300 | As of this writing (July, 2000) these results are being generated nightly. |
| 301 | You can refer to the summaries and the test coverage output files to see |
| 302 | where coverage is adequate or lacking and write test cases to beef up the |
| 303 | coverage. |
Tim Peters | f5f6c43 | 2001-05-23 07:46:36 +0000 | [diff] [blame^] | 304 | |
| 305 | |
| 306 | Some Non-Obvious regrtest Features |
| 307 | |
| 308 | * Automagic test detection: When you create a new test file |
| 309 | test_spam.py, you do not need to modify regrtest (or anything else) |
| 310 | to advertise its existence. regrtest searches for and runs all |
| 311 | modules in the test directory with names of the form test_xxx.py. |
| 312 | |
| 313 | * Miranda output: If, when running test_spam.py, regrtest does not |
| 314 | find an expected-output file test/output/test_spam, regrtest |
| 315 | pretends that it did find one, containing the single line |
| 316 | |
| 317 | test_spam |
| 318 | |
| 319 | This allows new tests that don't expect to print anything to stdout |
| 320 | to not bother creating expected-output files. |
| 321 | |
| 322 | * Two-stage testing: To run test_spam.py, regrtest imports test_spam |
| 323 | as a module. Most tests run to completion as a side-effect of |
| 324 | getting imported. After importing test_spam, regrtest also executes |
| 325 | test_spam.test_main(), if test_spam has a "test_main" attribute. |
| 326 | This is rarely needed, and you shouldn't create a module global |
| 327 | with name test_main unless you're specifically exploiting this |
| 328 | gimmick. In such cases, please put a comment saying so near your |
| 329 | def test_main, because this feature is so rarely used it's not |
| 330 | obvious when reading the test code. |