readme

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· 代码 · 共 373 行 · 第 1/2 页

TXT
373
字号
                      Writing Python Regression Tests                      -------------------------------                               Skip Montanaro                              (skip@mojam.com)IntroductionIf you add a new module to Python or modify the functionality of an existingmodule, you should write one or more test cases to exercise that newfunctionality.  There are different ways to do this within the regressiontesting facility provided with Python; any particular test should use onlyone of these options.  Each option requires writing a test module using theconventions of the the selected option:    - PyUnit based tests    - doctest based tests    - "traditional" Python test modulesRegardless of the mechanics of the testing approach you choose,you will be writing unit tests (isolated tests of functions and objectsdefined by the module) using white box techniques.  Unlike black boxtesting, where you only have the external interfaces to guide your test casewriting, in white box testing you can see the code being tested and tailoryour test cases to exercise it more completely.  In particular, you will beable to refer to the C and Python code in the CVS repository when writingyour regression test cases.PyUnit based testsThe PyUnit framework is based on the ideas of unit testing as espousedby Kent Beck and the Extreme Programming (XP) movement.  The specificinterface provided by the framework is tightly based on the JUnitJava implementation of Beck's original SmallTalk test framework.  Pleasesee the documentation of the unittest module for detailed information onthe interface and general guidelines on writing PyUnit based tests.The test_support helper module provides a two functions for use byPyUnit based tests in the Python regression testing framework:run_unittest() takes a unittest.TestCase derived class as a parameterand runs the tests defined in that class, and run_suite() takes apopulated TestSuite instance and runs the tests..  All test methods inthe Python regression framework have names that start with "test_" anduse lower-case names with words separated with underscores.All PyUnit-based tests in the Python test suite use boilerplate thatlooks like this:    import unittest    import test_support    class MyTestCase(unittest.TestCase):        # define test methods here...    def test_main():        test_support.run_unittest(MyTestCase)    if __name__ == "__main__":        test_main()This has the advantage that it allows the unittest module to be usedas a script to run individual tests as well as working well with theregrtest framework.doctest based testsTests written to use doctest are actually part of the docstrings forthe module being tested.  Each test is written as a display of aninteractive session, including the Python prompts, statements that wouldbe typed by the user, and the output of those statements (includingtracebacks, although only the exception msg needs to be retained then).The module in the test package is simply a wrapper that causes doctestto run over the tests in the module.  The test for the difflib moduleprovides a convenient example:    import difflib, test_support    test_support.run_doctest(difflib)If the test is successful, nothing is written to stdout (so you should notcreate a corresponding output/test_difflib file), but running regrtestwith -v will give a detailed report, the same as if passing -v to doctest.A second argument can be passed to run_doctest to tell doctest to searchsys.argv for -v instead of using test_support's idea of verbosity.  Thisis useful for writing doctest-based tests that aren't simply running adoctest'ed Lib module, but contain the doctests themselves.  Then attimes you may want to run such a test directly as a doctest, independentof the regrtest framework.  The tail end of test_descrtut.py is a goodexample:    def test_main(verbose=None):        import test_support, test.test_descrtut        test_support.run_doctest(test.test_descrtut, verbose)    if __name__ == "__main__":        test_main(1)If run via regrtest, test_main() is called (by regrtest) without specifyingverbose, and then test_support's idea of verbosity is used.  But whenrun directly, test_main(1) is called, and then doctest's idea of verbosityis used.See the documentation for the doctest module for information onwriting tests using the doctest framework."traditional" Python test modulesThe mechanics of how the "traditional" test system operates are fairlystraightforward.  When a test case is run, the output is compared with theexpected output that is stored in .../Lib/test/output.  If the test runs tocompletion and the actual and expected outputs match, the test succeeds, ifnot, it fails.  If an ImportError or test_support.TestSkipped error israised, the test is not run.Executing Test CasesIf you are writing test cases for module spam, you need to create a filein .../Lib/test named test_spam.py.  In addition, if the tests are expectedto write to stdout during a successful run, you also need to create anexpected output file in .../Lib/test/output named test_spam ("..."represents the top-level directory in the Python source tree, the directorycontaining the configure script).  If needed, generate the initial versionof the test output file by executing:    ./python Lib/test/regrtest.py -g test_spam.pyfrom the top-level directory.Any time you modify test_spam.py you need to generate a new expectedoutput file.  Don't forget to desk check the generated output to make sureit's really what you expected to find!  All in all it's usually betternot to have an expected-out file (note that doctest- and unittest-basedtests do not).To run a single test after modifying a module, simply run regrtest.pywithout the -g flag:    ./python Lib/test/regrtest.py test_spam.pyWhile debugging a regression test, you can of course execute itindependently of the regression testing framework and see what it prints:    ./python Lib/test/test_spam.pyTo run the entire test suite:[UNIX, + other platforms where "make" works] Make the "test" target at thetop level:    make test{WINDOWS] Run rt.bat from your PCBuild directory.  Read the comments atthe top of rt.bat for the use of special -d, -O and -q options processedby rt.bat.[OTHER] You can simply execute the two runs of regrtest (optimized andnon-optimized) directly:    ./python Lib/test/regrtest.py    ./python -O Lib/test/regrtest.pyBut note that this way picks up whatever .pyc and .pyo files happen to bearound.  The makefile and rt.bat ways run the tests twice, the first timeremoving all .pyc and .pyo files from the subtree rooted at Lib/.Test cases generate output based upon values computed by the test code.When executed, regrtest.py compares the actual output generated by executingthe test case with the expected output and reports success or failure.  Itstands to reason that if the actual and expected outputs are to match, theymust not contain any machine dependencies.  This means your test casesshould not print out absolute machine addresses (e.g. the return value ofthe id() builtin function) or floating point numbers with large numbers ofsignificant digits (unless you understand what you are doing!).Test Case Writing TipsWriting good test cases is a skilled task and is too complex to discuss indetail in this short document.  Many books have been written on the subject.I'll show my age by suggesting that Glenford Myers' "The Art of SoftwareTesting", published in 1979, is still the best introduction to the subjectavailable.  It is short (177 pages), easy to read, and discusses the majorelements of software testing, though its publication predates the

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?