单元测试特定值

时间:2010-08-15 04:53:28

标签: unit-testing tdd

考虑以下代码(来自一个要求说3由于某种原因是特殊的):

bool IsSpecial(int value)
   if (value == 3)
      return true
   else
      return false

我会用一些函数对它进行单元测试 - 一个函数叫做TEST(3IsSpecial),断言当传递3时函数返回true而另一个函数传递除3之外的一些随机值并断言函数返回false。

当需求发生变化并说它现在变为3和20是特殊的时,我会编写另一个测试来验证当使用20调用时,此函数也会返回true。该测试将失败,然后我将更新函数中的if条件。

现在,如果我的团队中有人不相信单元测试并且他们进行了此更改,那该怎么办?他们将直接去更改代码,因为我的第二个单元测试可能不会测试20(它可能是随机选择一个int或者其他一些int硬编码)。现在我的测试与代码不同步。如何确保在更改代码时某些单元测试或另一个单元测试失败?

我可能会在这里做一些非常错误的事情,所以任何其他技巧来解决这个问题也是值得欢迎的。

4 个答案:

答案 0 :(得分:2)

这是一个很好的问题。当你注意到Not3IsNotSpecial测试时,选择一个随机的非3值将是传统的方法。这不会改变“特殊”的定义。

在.NET环境中,您可以使用新的代码契约功能直接在方法中编写测试谓词(后置条件)。静态分析仪会捕获您提出的缺陷。例如:

Contract.Ensures(value != 3 && Contract.Result<Boolean>() == false);

我认为任何有TDD粉丝的人现在正在试验合同以查看使用模式。你有工具来证明正确性的想法是非常强大的。您甚至可以为接口指定这些谓词。

我见过的唯一可以解决这个问题的测试方法是Model Based Testing。这个想法类似于合同方法。您抽象地设置 Not3IsNotSpecial 条件(例如,IsSpecial(x => x != 3) == false))并让模型执行环境生成具体测试。我不确定,但我认为这些环境也会进行静态分析。无论如何,您让模型执行环境连续针对您的SUT运行。我从未使用过这样的环境,但这个概念很有意思。

答案 1 :(得分:1)

不幸的是,这种具体情况很难防范。使用像IsSpecial这样的函数,测试所有40亿个负面测试用例是不现实的,所以,不,你没有做出严重错误的事情。

这就是我头脑中的问题。许多存储库都有钩子,允许您在每次签入时运行某些进程,例如运行单元测试。可以设置一个标准,新签入的代码必须达到单元测试下代码覆盖的某个阈值。如果提交不符合某些指标,则会被拒绝。

我从来没有必要设置其中一个系统,所以我不知道涉及到什么,但我知道这是可能的。

相信我,我感受到你的痛苦。我与同样对单元测试有抵抗力的人一起工作。

答案 2 :(得分:1)

你需要考虑的一件事是为什么3是一个特殊角色而另一些则不是。如果它定义了您的应用程序的某些方面,您可以将该方面排除在外,并从中进行枚举。

现在,您可以在此处查看如果枚举中不存在值,则此测试应该失败。对于枚举类,编写一个测试来检查可能的值。如果添加了新的可能值,则测试应该失败。

所以你的方法将成为:

bool IsSpecial(int value)
   if (SpecialValues.has(value))
      return true
   else
      return false

并且您的SpecialValues将是一个类似的枚举:

enum SpecialValues {

三(3),二十(20)

   public int value;
}

现在您应该编写以测试枚举的可能值。一个简单的测试可以是检查可能值的总数,另一个测试可以检查可能的值本身

答案 3 :(得分:0)

另一个要点是,在一个不那么人为的例子中:

  • 根据业务领域的知识,20可能是一些有效的测试条件。基于对业务问题的了解,以BDD方式编写测试可能有助于您明确地捕获它。

  • 由于其作为边界条件的状态,
  • 4可能是一个很好的测试值。这可能更有可能在现实世界中发生变化,因此更有可能出现在完整的测试案例中。