15.7 总结

    我们介绍了使用unittestdoctest来创建自动化单元测试,也介绍了可以创建测试套件,测试的集合可以被打包起来重用,被放入套件中获得更大的范围,而无需依赖自动化测试查找进程。

    我们还介绍了如何创建模仿对象,这样可以隔离软件单元对其进行测试,也介绍了几种安装和卸载的方式。这样就可以应对包含了复杂的初始化状态或存储结果的测试。

    doctestunittest都很好地符合了单元测试的FIRST(Fast Isolated Repeatable Self-Validating Timely)特性。FIRST特性如下。

    • 速度快:只要不是写得很糟糕的测试,doctest和unittest的性能都会很好。
    • 隔离:在unittest的包中提供了一个模仿模块,可以用于隔离类定义。进一步说,我们可以使用这一点对设计进行评估来确保组件之间是彼此隔离的。
    • 可重复性:使用doctest和unittest做自动化测试来确保可重复性。
    • 自我检验:基于测试用例条件来创建测试结果,确保在测试中没有包含主观的判断。
    • 及时性:一旦完成了类、函数或模块的骨架,就可以编写和运行测试用例。即使一个类的测试中只包括返回pass的逻辑,也可以作为一个测试脚本来运行。

    在软件管理方面,测试总数和通过的测试总数在软件状态报告中有时是非常有用的。

    15.7.1 设计要素和折中方案

    创建软件时,测试用例也是需要交付的。任何没有自动化测试的功能也是不应该存在的,没有测试的功能是不能被相信的。如果不能被相信,就不应该被使用。

    唯一的权衡点是,使用docttest还是unittest,或两者一起使用。对于简单的程序,doctest是不错的选择。对于复杂一些的场景,就有必要使用unittest。对于一些框架,API文档需要包括一些示例,那么两者一起使用就比较好。

    在一些情况下,创建完整的TestCase类定义的模块就足够了。可使用TestLoader类和测试查找功能来实现测试查找。

    在普遍情况下,unittest包含了使用TestLoader从每个TestCase子类中提取测试方法。将这些测试方法打包到一个类中,它们将共享类级别的setUp(),有可能也会共享setUpClass()方法。

    也可以不必使用TestLoader来创建TestCase实例。这样的话,runTest()的默认方法就被定义来包含测试用例的断言,可以基于这种类的实例创建一个套件。

    最难的部分是可测试性的设计。为了确保单元可以被独立地测试,需要移除依赖,有时会认为这样做增加了软件设计的复杂度。对于大部分情况,发现并移除依赖是一种时间上的投资,为的是创建可维护性更强和更灵活的软件。

    一般的规则是:类之间包含隐式依赖是糟糕的设计。

    可测试的设计中会包含显式的依赖,它们可以被使用模仿对象轻易地替代。

    15.7.2 展望

    在下一章中,我们会介绍如何以命令行作为起始来编写完整的应用,还会介绍几种在Python应用中处理启动选项、环境变量和配置文件的方法。

    在第17章“模块和包的设计”中,会对应用设计的扩展方面进行介绍。如何将应用组合到大的应用中以及如何将大的应用分解为小的部分。