在一次测试中检查几个不同的示例输入?

时间:2009-05-06 19:45:46

标签: unit-testing tdd nunit

假设我想编写一个验证电子邮件地址的函数 用正则表达式。我写了一点测试来检查我的功能并编写 实际功能。让它通过。

但是,我可以想出一些不同的方法来测试它们 功能(test@test.com; test234@test.com; test.test.com等)。

我是否将所有需要检查的咒语放在同一个单一的咒语中 测试几个ASSERTS或我为每一个编写一个新的测试 我能想到的事情?

谢谢!

7 个答案:

答案 0 :(得分:10)

大多数测试框架现在支持某种基于数据的测试,以便您在多个数据集上运行相同的测试。

请参阅NUnit中的ValuesAttribute

xUnit.net,MBUnit和其他人有类似的方法。

答案 1 :(得分:8)

通常我会创建许多不同的测试,并为每个测试提供自己的名称。例如,假设有3种不同的正则表达式{A,B,& C}用于匹配电子邮件地址。该函数检查传入的电子邮件是否匹配,并接受找到的第一个匹配项。

我会进行以下测试。

  • ATypeEmailShouldMatchPatternA
  • BTypeEmailShouldMatchPatternB
  • CTypeEmailShouldMatchPatternC
  • BadEmailShouldNotMatchAnyPattern
  • EmailCompatibleWithPatternAAndPatternBShouldBeMatchedByA
  • EmailCompatibleWithPatternAAndCShouldBeMatchedByA
  • EmailCompatibleWithPatternBAndCShouldBeMatchedByB

通常我会在每个测试中放置一个断言。

然而,有时候,我会在测试中放置多个断言,如果断言都在检查同一个东西的不同部分。例如,假设我有一个函数可以找到与模式A匹配的所有电子邮件。我的测试在电子邮件列表中提供,但只有一个匹配模式A.该函数返回一个列表,我希望该列表只有一个元素它。所以我会断言两件事:

  1. 该列表中包含一个元素。
  2. 一个元素是与模式A匹配的电子邮件。

答案 2 :(得分:2)

正如@Paul提到的,几个测试框架支持RowTests。使用该功能,您可以像这样写出一些可怕的东西:

[TestCase ("test@test.com", true)]
[TestCase ("x!x@test.com", true)]
[TestCase ("x#x@test.com", true)]
[TestCase ("x$x@test.com", true)]
[TestCase ("x%x@test.com", true)]
[TestCase ("x&x@test.com", true)]
[TestCase ("x'x@test.com", true)]
[TestCase ("x*x@test.com", true)]
[TestCase ("x+x@test.com", true)]
[TestCase ("x-x@test.com", true)]
[TestCase ("x/x@test.com", true)]
[TestCase ("x=x@test.com", true)]
[TestCase ("x?x@test.com", true)]
[TestCase ("x^x@test.com", true)]
[TestCase ("x_x@test.com", true)]
[TestCase ("x`x@test.com", true)]
[TestCase ("x{x@test.com", true)]
[TestCase ("x{x@test.com", true)]
[TestCase ("x|x@test.com", true)]
[TestCase ("x}x@test.com", true)]
[TestCase ("x~x@test.com", true)]
[TestCase ("test", false)]
[TestCase ("", false)]
[TestCase (null, false)]
public void IsEmail_Should_Match_Valid_Email_Addresses(string target, bool result)
{
    Assert.AreEqual(result, target.IsEmail());
}

或者你可以用一堆断言做同样的事情。在执行某些操作后,在对象上声明多个属性是很常见的。我认为上述解决方案更具可读性。

答案 3 :(得分:1)

如果不同的咒语真的归结为同样的事情,那就不是问题了。

但是,如果其中一个电子邮件地址突然中断测试,您将不得不进行调试以找出哪个案例出错了。所以这似乎是打破它们的一个很好的理由。

你最终会得到数以百万计的单元测试,这是正确的,因为它们都是在测试你的应用程序的一个单元之后,但实际上多个断言会提供失败的断言打破测试的方式不会弄乱了失败的意思。

答案 4 :(得分:1)

BDD和/或上下文/规范框架like SubSpec which happens to have some salient examples通过将每批相关断言视为一个单独的观察块来管理它,该观察块为其提供名称或描述性标签。

这推动了一个良好测试的关键要素是:

  1. 你对每个阶段都有AAA / GWT分离 - 你被迫真正思考哪些是[并且通常会很快意识到什么时候需要分解更多]
  2. 您最终会在观察中获得良好的名称/描述(行测试通常会给您留下[不太可维护的]评论)
  3. 当测试中的10和17 [与行测试一样]时,您具有每个测试的状态以帮助您缩小解决方案
  4. 在某些情况下,当您真正使用简单的基于表或矩阵的套件时,行测试可能是合适的。

    此外,xUnit.net的PropertyData在某些情况下可以强大且适当,作为在其他方面做一些技巧的方法。

答案 5 :(得分:0)

我不认为您应该为每个案例编写单独的测试,因为所有案例都与测试字符串是正确的电子邮件地址的相同事物有关。如果您使用MbUnit或NUnit来运行测试,那么您可以使用RowTest和Row属性将不同的值传递给测试。另一种方法是将所有不同的电子邮件格式存储在一个数组中并循环遍历数组并执行断言。

答案 6 :(得分:0)

如果您正在测试相同的功能,我会在同一个测试中检查它们,并提供多个断言,只要您的测试足够简单。

有人提倡每个测试必须只有一个断言,因为测试必须非常,非常,非常简单。

如果测试不简单,说你有循环和ifs,你需要测试一下测试,检查它的逻辑是否正确,这是不好的。

如果您的测试有多个断言,但仍然保持简单(没有循环,没有ifs)多个断言正在测试同样的事情,那么我就不会那么激进< / em>提倡“每次测试单一断言”。选择是你的。