python函数实验报告的简单介绍( 五 )


另一种执行doctest的方法是使用unittest模块创建单独的测试程序 。在概念上,unittest模块是根据Java的JUnit单元测试库进行建模的,并用于创建包含测试用例的测试套件 。unittest模块可以基于doctests创建测试用例,而不需要知道程序或模块包含的任何事物——只要知道其包含doctest即可 。因此,为给blocks.py程序制作一个测试套件,我们可以创建如下的简单程序(将其称为test_blocks.py):
import doctest
import unittest
import blocks
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite(blocks))
runner = unittest.TextTestRunner()
print(runner.run(suite))
注意,如果釆用这种方法 , 程序的名称上会有一个隐含的约束:程序名必须是有效的模块名 。因此,名为convert-incidents.py的程序的测试不能写成这样 。因为import convert-incidents不是有效的,在Python标识符中,连接符是无效的(避开这一约束是可能的 , 但最简单的解决方案是使用总是有效模块名的程序文件名,比如,使用下划线替换连接符) 。这里展示的结构(创建一个测试套件,添加一个或多个测试用例或测试套件,运行总体的测试套件,输出结果)是典型的机遇unittest的测试 。运行时 , 这一特定实例产生如下结果:
...
.............................................................................................................
Ran 3 tests in 0.244s
OK
每次执行一个测试用例时,都会输出一个句点(因此上面的输出最前面有3个句点),之后是一行连接符,再之后是测试摘要(如果有任何一个测试失败,就会有更多的输出信息) 。
如果我们尝试将测试分离开(典型情况下是要测试的每个程序和模块都有一个测试用例),就不要再使用doctests,而是直接使用unittest模块的功能——尤其是我们习惯于使用JUnit方法进行测试时ounittest模块会将测试分离于代码——对大型项目(测试编写人员与开发人员可能不一致)而言 , 这种方法特别有用 。此外 , unittest单元测试编写为独立的Python模块,因此 , 不会像在docstring内部编写测试用例时受到兼容性和明智性的限制 。
unittest模块定义了 4个关键概念 。测试夹具是一个用于描述创建测试(以及用完之后将其清理)所必需的代码的术语,典型实例是创建测试所用的一个输入文件,最后删除输入文件与结果输出文件 。测试套件是一组测试用例的组合 。测试用例是测试的基本单元—我们很快就会看到实例 。测试运行者是执行一个或多个测试套件的对象 。
典型情况下,测试套件是通过创建unittest.TestCase的子类实现的,其中每个名称 以“test”开头的方法都是一个测试用例 。如果我们需要完成任何创建操作,就可以在一个名为setUp()的方法中实现;类似地,对任何清理操作,也可以实现一个名为 tearDown()的方法 。在测试内部 , 有大量可供我们使用的unittest.TestCase方法,包括 assertTrue()、assertEqual()、assertAlmostEqual()(对于测试浮点数很有用)、assertRaises() 以及更多,还包括很多对应的逆方法,比如assertFalse()、assertNotEqual()、failIfEqual()、 failUnlessEqual ()等 。
unittest模块进行了很好的归档,并且提供了大量功能 , 但在这里我们只是通过一 个非常简单的测试套件来感受一下该模块的使用 。这里将要使用的实例,该练习要求创建一个Atomic模块,该模块可以用作一 个上下文管理器,以确保或者所有改变都应用于某个列表、集合或字典 , 或者所有改变都不应用 。作为解决方案提供的Atomic.py模块使用30行代码来实现Atomic类,并提供了 100行左右的模块doctest 。这里,我们将创建test_Atomic.py模块,并使用 unittest测试替换doctest,以便可以删除doctest 。

推荐阅读