Test


title: Python 中的单元测试 date: 2017/09/07

常常将测试代码和运行代码一起写是一种非常好的习惯。 聪明地使用这种方法将会帮助您更加精确地定义代码的含义,并且代码的耦合性更低。

测试的通用规则:

  • 测试单元应该集中于小部分的功能,并且证明它是对的。
  • 每个测试单元必须完全独立。他们都能够单独运行,也可以在测试套件中运行,而不用考虑被调用的顺序。 要想实现这个规则,测试单元应该加载最新的数据集,之后再做一些清理。 这通常用方法 setUp()tearDown() 处理。
  • 尽量使测试单元快速运行。如果一个单独的测试单元需要较长的时间去运行,开发进度将会延迟, 测试单元将不能如期常态性运行。有时候,因为测试单元需要复杂的数据结构, 并且当它运行时每次都要加载,所以其运行时间较长。把运行吃力的测试单元放在单独的测试组件中, 并且按照需要运行其它测试单元。
  • 学习使用工具,学习如何运行一个单独的测试用例。然后,当在一个模块中开发了一个功能时, 经常运行这个功能的测试用例,理想情况下,一切都将自动。
  • 在编码会话前后,要常常运行完整的测试组件。只有这样,您才会坚信剩余的代码不会中断。
  • 实现钩子(hook)是一个非常好的主意。因为一旦把代码放入分享仓库中, 这个钩子可以运行所有的测试单元。
  • 如果您在开发期间不得不打断自己的工作,写一个被打断的单元测试,它关于下一步要开发的东西。 当回到工作时,您将更快地回到原先被打断的地方,并且步入正轨。
  • 当您调试代码的时候,首先需要写一个精确定位bug的测试单元。尽管这样做很难, 但是捕捉bug的单元测试在项目中很重要。
  • 测试函数使用长且描述性的名字。这边的样式指导与运行代码有点不一样,运行代码更倾向于使用短的名字, 而测试函数不会直接被调用。在运行代码中,square()或者甚至sqr()这样的命名都是可以的, 但是在测试代码中,您应该这样取名test_square_of_number_2(),test_square_negative_number()。 当测试单元失败时,函数名应该显示,而且尽可能具有描述性。
  • 当发生了一些问题,或者不得不改变时,如果代码中有一套不错的测试单元, 维护将很大一部分依靠测试组件解决问题,或者修改确定的行为。因此测试代码应该尽可能多读, 甚至多于运行代码。目的不明确的测试单元在这种情况下没有多少用处。
  • 测试代码的另外一个用处是作为新开发人员的入门介绍。当有人需要基于现有的代码库工作时, 运行并且阅读相关的测试代码是最好的做法。他们会或者应该发现大多数困难出现的热点,以及边界的情况。 如果他们必须添加一些功能,第一步应该是添加一个测试,以确保新的功能不是一个尚未插入到界面的工作路径。

单元测试技术:

  • doctest 基于代码文档的测试工具
  • unittest 类似于其它语言中的单元测试工具
  • pytest 用更便捷的方式来编写单元测试
  • nose 比 pytest 更加易用的单元测试工具

除了单元测试外,Python 中还有许多标准库和第三方工具可以用于其它测试,详见:https://wiki.python.org/moin/PythonTestingToolsTaxonomy。

Previous
Next