我如何测试/重构我的测试?

时间:2013-03-22 08:49:11

标签: python unit-testing testing language-agnostic

我的应用程序有测试套装。随着测试服有机地增长,测试有很多重复的代码可以重构。

但是我想确保测试套件不会随着重构而改变。如何测试我的测试对重构是不变的。

(我正在使用Python + UnitTest),但我想这个问题的答案可能与语言无关。

8 个答案:

答案 0 :(得分:5)

测试的真正测试是生产代码。

检查测试代码重构没有破坏您的测试的有效方法是执行Mutation Testing,其中测试代码的副本会发生变异以引入错误以验证您的测试抓住错误。这是一些测试覆盖工具使用的策略。

我没有使用它(我不是一个真正的python编码器),但这似乎得到Python Mutant Tester的支持,所以这可能值得一看。

答案 1 :(得分:3)

Coverage.py是你的朋友。

将要重构的所有测试移到“系统测试”(或某些此类标记)中。重构你想要的测试(你会在这里进行单元测试吗?)并监控覆盖范围:

  • 在运行新的单元测试之后但在运行系统测试之前
  • 运行新的单元测试和系统测试后。

在理想情况下,覆盖范围相同或更高,但您可以破坏旧的系统测试。

FWIW,py.test提供了轻松标记测试并仅运行特定测试的机制,并且与unittest2测试兼容。

答案 2 :(得分:2)

有趣的问题 - 我总是热衷于听到“如何测试测试?!”类型的讨论。还有来自@marksweb的好点。

检查您的测试实际上正在执行您希望他们执行的操作并测试您的意图总是一个挑战,但是要做到正确并正确执行它是很好的。我总是试图在任何项目中考虑测试应该占开发工作量的1/3 的经验法则......无论项目时间限制,压力和问题不可避免地出现。< / p>

如果您打算继续并扩展您的项目,您是否考虑过像您所说的重构,但是以某种方式创建一个适当的测试框架,允许测试驱动开发(TDD)任何未来的功能添加或项目的一般扩展?

答案 3 :(得分:1)

理论上你可以为测试编写一个测试,模拟测试中的实际对象。但我想这只是很多工作而且不值得的。

所以你剩下的是一些策略,这会有所帮助,但不会使这种失败安全。

  1. 非常小心,慢慢地工作。尽可能使用IDE的功能,以限制人为错误的可能性。

  2. 成对工作。看着你肩膀的伙伴可能只是发现你错过的小故障。

  3. 复制测试,然后重构。完成后在生产代码中引入错误以确保,两个测试都以相同(或等效)方式找到问题。然后才删除原始测试。

  4. 最后一步可以通过工具完成,虽然我不知道python的味道。要搜索的关键字是“突变测试”。

  5. 说了这么多,我个人对步骤1 + 2感到满意。

答案 4 :(得分:1)

虽然您已经提到了Python,但我想评论一下如何在Smalltalk中应用重构。大多数现代Smalltalk实现包括在系统浏览器中集成的“Refactoring Browser”来重构源代码。 RB包含一个重写框架,用于动态执行您询问的有关保留系统行为和稳定性的转换。使用它的一种方法是在通过diff工具提交之前打开范围浏览器,应用重构并查看/编辑更改。我不知道Python重构工具的成熟度,但Smalltalk社区需要很多迭代周期(数年)才能拥有如此出色的软件。

Don Roberts和John Brant编写了第一个重构浏览器工具,现在作为重构工具的标准。有一些videoshere展示了其中的一些功能。要将方法提升为超类,请在Pharo中选择方法,重构和“拉出”菜单项。该规则将检测并允许您在执行之前查看建议的重复子实现者以进行删除。重构的应用与测试代码无关。

答案 5 :(得分:0)

我看不到重构测试套件的简单方法,并且根据您的重构程度,您显然将不得不更改测试套件。你的测试套件有多大?

正确地重构需要时间和注意细节(以及很多 Ctrl + C Ctrl + V !)。每当我重构我的测试时,我都不会尝试找到任何快速的做事方式,除了找到&amp;替换,因为涉及的风险太大。

如果你想保持测试的质量,你最好做正确的手动,尽管手动慢。

答案 6 :(得分:0)

不要重构测试套件。

重构的目的是使代码更容易维护,以满足一些抽象的标准&#34;代码的好处&#34;。测试代码并不需要很好,它不需要避免重复,但它确实需要彻底。一旦你有一个有效的测试(即它确实测试了被测代码的必要条件),你就不应该删除它或改变它,所以测试代码不需要易于集中维护。 / p>

如果您愿意,可以将现有测试重写为好,并运行新测试以及旧测试。这保证了新的组合测试套件能够捕获旧的组合测试套件所带来的所有错误(可能会在未来扩展新代码时更多)。

有两种方法可以将测试视为无效 - 您意识到它是错误的(即,它有时会因为测试中的正确代码而错误地失败),或者测试中的接口已经改变(删除API测试,或允许以前测试失败的行为)。在这种情况下,您可以从套件中删除测试。如果您意识到一大堆测试是错误的(因为它们包含错误的重复代码),然后您可以将它们全部删除并用重构和更正的版本替换它们。你不会因为不喜欢他们的来源风格而删除测试。

要回答您的具体问题:要测试您的新测试代码是否与旧代码相同,您必须确保(a)所有新测试都通过您当前正确的测试 - 远至您已知的代码库,这很容易,而且(b)新测试检测到旧测试检测到的所有错误,这通常是不可能的,因为你手头上没有一套错误的代码实现测试

答案 7 :(得分:0)

测试代码可以是API的最佳低级文档,因为只要它们通过且不正确,它们就不会过时。但是凌乱的测试代码并不能很好地满足这个目的。所以重构是必不可少的。

您的测试代码也可能随时间而变化。测试也是如此。如果您希望顺利进行,则必须最小化代码重复,并且可读性是关键。

测试应该易于阅读,并且总是一次测试一件事并使下面的内容明确:

  • 有什么先决条件?
  • 正在执行什么?
  • 预期结果是什么?

如果考虑到这一点,重构测试代码应该是非常安全的。一步一步,正如@Don Ruby提到的那样,让您的生产代码成为测试的测试。

对于许多重构,您通常可以安全地依赖高级IDE工具 - 如果您在提取的代码中注意副作用。

虽然我同意应避免在没有适当测试覆盖的情况下进行重构,但我认为在通常情况下编写测试测试几乎是荒谬的。