在Django中,何时应使用文档测试而非单元测试?

4 投票
2 回答
609 浏览
提问于 2025-04-16 07:28

来自Django文档的内容:

...在进行文档测试(doctests)时,数据库不会自动刷新,所以如果你的文档测试需要特定的数据库状态,你应该考虑清空数据库或者加载一个数据文件。

老实说,我现在90%的测试都是用文档测试来做的。我的一个同事觉得这很奇怪。说实话,我做的测试很少,所以我并不认为自己在这个领域是个高手。

有没有人有一些简单的经验法则,用来决定怎么进行测试呢?

非StackOverflow的回答

我的一个同事建议用文档测试来测试模型函数和约束,而用单元测试来测试视图。这样作为经验法则听起来怎么样?

2 个回答

1

文档测试(doctests)非常适合用来确保你的文档是最新的,但我不太建议用它们来测试代码。因为在你修改代码的时候,文档很容易就会变得过时。

简单来说,就是用单元测试来测试代码,用文档测试来检查文档。

15

随着你的项目不断发展,你会发现单元测试在测试代码方面要好得多。

Django项目本身正在将所有的文档测试转换为单元测试(我们计划在1.3版本发布时完成)。我们这么做的原因是,在转换之前,测试套件中的执行顺序有时会导致难以重现的错误。有时候,一段代码会意外依赖于之前运行的文档测试代码。此外,切换到单元测试后,整体测试时间也加快了,因为我们可以更合理地决定何时清空数据库。

单元测试的另一个好处是,它们更容易维护。因为整个测试案例是自包含的,你可以选择写一个新的测试案例,或者修改那个小而具体的测试函数来适应新的需求。

文档测试通常是逐步演进的——你先创建一个小部件,给它加上绿色的毛,然后确认毛是绿色的,再加上四条腿,确保有四条腿和绿色的毛,接着再加一个拇指,确保有拇指、四条腿和绿色的毛,等等……这意味着如果你想在绿色毛的阶段后添加一个测试,你就得修改后面每个测试的预期结果。

你不想做这么多的重写,所以你把新的测试放在最后。然后你又添加一个,过一段时间后,你的测试就会变得混乱不堪,根本搞不清楚某个特定功能是否被测试过!而单元测试因为每个测试都代表一个具体、有限的想法,所以更容易逻辑上重新排列测试,也能添加不依赖于之前测试的新测试。此外,如果你改变了add_green_fur()的工作方式,你就不需要修改几十个测试案例的结果。

另一个好处是,单元测试(如果写得好)能准确告诉你代码哪里出错了。Failed: MyWidget.tests.test_green_fur()比“部件测试在第384行失败”要容易调试得多,因为后者通常距离实际出错的地方有几十到几百行。

总的来说,单元测试是更好的测试方式。

编辑:

针对你同事的想法,我尊重地建议他可能没有在一个有很多文档测试的大项目上工作过。模型中的文档测试和视图中的一样糟糕。它们有完全相同的问题(如果说有什么不同,模型中的文档测试更糟,因为flush的开销非常大,而且对于彻底的文档测试是绝对必要的)。不要低估运行测试所花费的时间成本。

此外,除非你有非常好的理由,否则不要混合不同类型的测试。如果你这样做,你会很快发现自己在重复测试,或者假设某个函数在你没有查看的测试套件中已经被测试过。

文档测试常常被宣传为“提供文档”,说明你的代码应该如何工作。这听起来不错,但这并不能替代编写可读性强的代码和良好的内联注释。如果你想要更多的文档,单独写出来就好!

你无法写出既是好测试又是好文档的测试。

撰写回答