我正试图开始使用 Python 进行单元测试,我想知道是否有人能够解释 doctest 和 unittest 的优缺点。
你会在什么情况下使用它们?
我几乎完全使用 unittest。
偶尔,我会在 doctest 可用的 docstring 中放入一些内容。
95% 的测试用例是单测试的。
为什么?我喜欢把文字串保持得更短,更切中要点。有时,测试用例有助于澄清文档字符串。大多数时候,应用程序的测试用例对于 docstring 来说太长了。
如果您刚刚开始了解单元测试的概念,那么我将从 doctest开始,因为它的使用非常简单。它还自然地提供了某种级别的文档。对于使用 doctest进行更全面的测试,您可以将测试放在外部文件中,这样就不会使您的文档变得凌乱。
doctest
如果您具有使用过 JUnit 或类似的背景,希望能够像在其他地方一样编写单元测试,那么我建议使用 unittest。
unittest
我几乎从来不用文件测试。我希望我的代码是自我文档化的,而 docstring 为用户提供文档。IMO 将数百行测试添加到一个模块中,使得文档字符串的可读性大大降低。我还发现单元测试在需要时更容易修改。
我只使用 unittest; 我认为 doctest 过多地扰乱了主模块。这可能与编写彻底的测试有关。
同时使用这两种方法是一种有效且相当简单的选择。doctest模块提供了 DoctTestSuite和 DocFileSuite方法,它们分别从模块或文件创建单元测试兼容的测试套件。
DoctTestSuite
DocFileSuite
因此,我将两者都使用,并且通常将 doctest 用于简单的测试,这些测试的函数只需要很少或根本不需要设置(参数的简单类型)。实际上,我认为一些 doctest 测试 救命记录了这个函数,而不是减损它。
但是对于更复杂的用例和更全面的测试用例集,我使用 unittest 来提供更多的控制和灵活性。
我更喜欢基于发现的系统(目前使用的是前者)。
当测试也可以作为文档使用时,doctest 是很好的,否则它们会使代码过于混乱。
两者都很值钱。我使用 doctest 和 鼻子代替 unittest。我使用 doctest 来处理这样的情况: 测试提供了一个实际上作为文档很有用的用法示例。一般来说,我不会让这些测试全面,只是为了提供信息。我有效地反过来使用 doctest: 不是基于 doctest 测试我的代码是正确的,而是基于代码检查我的文档是否正确。
原因是我发现全面的文档测试会使您的文档过于混乱,因此您要么会得到不可用的文档字符串,要么会得到不完整的测试。
对于实际测试 密码,我们的目标是彻底测试每个案例,而不是通过例子来说明是什么,这是一个不同的目标,我认为其他框架更好地实现了这个目标。
Doctest 的另一个优点是,您可以确保代码完成文档所说的任务。一段时间后,软件更改可以使您的文档和代码执行不同的操作。:-)
我是一个生物信息学家,我写的大部分代码都是“一次一个任务”的脚本,这些代码只运行一到两次,并且只执行一个特定的任务。
在这种情况下,编写大的单元测试可能有些夸张,而 doctest 是一种有用的折衷方案。它们的编写速度更快,而且由于它们通常被合并到代码中,它们允许始终关注代码应该如何运行,而不必打开另一个文件。这在编写小脚本时很有用。
另外,当您必须将脚本传递给不擅长编程的研究人员时,doctest 也很有用。有些人发现很难理解单元测试是如何构造的; 另一方面,doctest 是简单的用法示例,因此人们可以直接复制粘贴它们,看看如何使用它们。
所以,回到我的答案: 当你必须编写小脚本,当你必须通过它们或者把它们展示给不是计算机科学家的研究人员时,doctest 是有用的。
我不使用 doctest 作为 unittest 的替代品。虽然它们有一点重叠,但是这两个模块没有相同的功能:
我使用 unittest作为单元测试框架,这意味着它可以帮助我快速确定任何修改对代码其余部分的影响。
我使用 doctest来保证注释(即 docstring)仍然与当前版本的代码相关。
我从 unittest中获得的测试驱动开发的广泛文档化的好处。doctest解决了过时注释误导代码维护的更微妙的危险。
Doctest有时会导致错误的结果。特别是当输出包含转义序列时。例如
Doctest
def convert(): """ >>> convert() '\xe0\xa4\x95' """ a = '\xe0\xa4\x95' return a import doctest doctest.testmod()
给予
********************************************************************** File "hindi.py", line 3, in __main__.convert Failed example: convert() Expected: 'क' Got: '\xe0\xa4\x95' ********************************************************************** 1 items had failures: 1 of 1 in __main__.convert ***Test Failed*** 1 failures.
也不检查输出的类型。它只比较输出字符串。例如,它使一些类型成为有理数,如果它是一个整数,它就像整数一样打印出来。那么假设有一个函数返回有理数。因此,doctest 不会区分输出是有理整数还是整数。