unit-testing - 单元测试 - 契约(Contract)变更的单元测试的好处?

标签 unit-testing design-by-contract

最近我和一位同事就单元测试进行了一次有趣的讨论。我们正在讨论当您的契约(Contract)发生变化时,维护单元测试的效率会降低。

也许任何人都可以告诉我如何解决这个问题。让我详细说明一下:

假设有一个类可以进行一些巧妙的计算。合约规定它应该计算一个数字,否则当由于某种原因失败时返回-1。

我有契约(Contract)测试来测试这一点。在我所有的其他测试中,我都 stub 了这个漂亮的计算器。

所以现在我更改了合约,每当它无法计算时就会抛出 CannotCalculateException。

我的契约(Contract)测试将失败,我将相应地修复它们。但是,我所有的模拟/ stub 对象仍将使用旧的契约(Contract)规则。这些测试将会成功,但它们不应该成功!

出现的问题是,有了对单元测试的信心,对此类更改可以有多少信心......单元测试成功,但在测试应用程序时会出现错误。使用此计算器的测试需要修复,这会花费时间,甚至可能会被多次 stub /模拟......

您如何看待此案?我从来没有仔细思考过这个问题。在我看来,单元测试的这些改变是可以接受的。如果我不使用单元测试,我也会在测试阶段(由测试人员)看到此类错误。但我没有足够的信心指出什么会花费更多(或更少)时间。

有什么想法吗?

最佳答案

您提出的第一个问题是所谓的“脆弱测试”问题。您对应用程序进行了更改,数百个测试因该更改而中断。发生这种情况时,您就会遇到设计问题。您的测试被设计得很脆弱。它们尚未与生产代码充分解耦。解决方案是(就像在所有此类软件问题中一样)找到一种抽象,将测试与生产代码解耦,从而使生产代码的波动性对测试隐藏起来。

导致这种脆弱性的一些简单原因是:

  • 测试显示的字符串。此类字符串是不稳定的,因为它们的语法或拼写可能会因分析人员的突发奇想而改变。
  • 测试应在抽象(例如 FULL_TIME)后面编码的离散值(例如 3)。
  • 从多次测试中调用相同的 API。您应该将 API 调用包装在测试函数中,以便当 API 更改时您可以在一处进行更改。

测试设计是一个经常被 TDD 初学者忽视的重要问题。这通常会导致测试变得脆弱,从而导致新手拒绝 TDD,认为它“效率低下”。

您提出的第二个问题是误报。您使用了如此多的模拟,以至于您的测试都没有真正测试集成系统。虽然测试独立单元是一件好事,但测试系统的部分和整体集成也很重要。 TDD不仅仅是单元测试。

测试应安排如下:

  • 单元测试提供接近 100% 的代码覆盖率。他们测试独立的单元。它们是由程序员使用系统的编程语言编写的。
  • 组件测试覆盖约 50% 的系统。它们是由业务分析师和 QA 编写的。它们是用 FitNesse、Selenium、Cucumber 等语言编写的。它们测试整个组件,而不是单个单元。他们主要测试快乐路径案例和一些非常明显的不快乐路径案例。
  • 集成测试覆盖了约 20% 的系统。他们测试小型组件集而不是整个系统。也用 FitNesse/Selenium/Cucumber 等语言编写。由建筑师编写。
  • 系统测试覆盖约 10% 的系统。他们测试集成在一起的整个系统。同样,它们是用 FitNesse/Selenium/Cucumber 等语言编写的。由建筑师编写。
  • 探索性手动测试。 (参见 James Bach)这些测试是手动的,但没有脚本化。他们运用人类的聪明才智和创造力。

关于unit-testing - 单元测试 - 契约(Contract)变更的单元测试的好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2965483/

相关文章:

c# - Microsoft.VisualStudio.TestPlatform.TestFramework 和 Microsoft.VisualStudio.QualityTools.UnitTestFramework 之间的区别

android - ActivityMonitor 在 Activity 生命周期的什么时候触发?

unit-testing - 改进此代码的方法

c# - 模拟打开对话框的 openDialog 框以从驱动器中选择文件名

visual-studio-2017 - Visual Studio 2017不支持代码契约,如何使用PostSharp实现它?

node.js - Node.JS服务层设计

c# - .NET Core 单元测试未显示在 AppVeyor 测试窗口(和徽章)中

c++ - 如何将断言放在类初始化列表之前?

unit-testing - 后置条件是(类型的)单元测试吗?

actionscript-3 - 通过actionscript的合约工具进行设计