单元测试 - 边缘情况需要单独的测试方法吗?

时间:2012-10-29 21:54:48

标签: unit-testing language-agnostic

当单元测试时,边缘情况下测试相同的方法每个都需要单独的测试方法。例如,测试传递给以下函数的空字符串:

public function add($numbers)
{
    $numbers = preg_replace('/\s/', '', $numbers);
    if ($numbers === "") {
        return 0;
    }
}

我显然想要抓住边缘案例,例如:

""
" " 
"\t \n"
"asd"

那么需要多少测试方法才能证明这种方法有效?

public function testAddEmptyString()
{
    $stringCalculator = new StringCalculator();
    $this->assertSame(0, $stringCalculator->add(""));
}

public function testAddEmptyStringWithSpaces()
{
    $stringCalculator = new StringCalculator();
    $this->assertSame(0, $stringCalculator->add("  "));
}

public function testAddEmptyStringWithCharacters()
{
    $stringCalculator = new StringCalculator();
    $this->assertSame(0, $stringCalculator->add("asd"));
}

这似乎是测试类将包含大量的方法,用于任何非平凡的

4 个答案:

答案 0 :(得分:1)

在这个简单的情况下(一个实际的函数,即没有副作用,没有例外,每个测试用例基本上只有一行)我会说单个测试方法没问题。

如果您有更复杂的测试用例需要设置代码,那么每个测试用例都应该有自己的测试方法。

答案 1 :(得分:0)

这是一个意见问题,所以恕我直言,一种测试方法应该测试一个场景,总是

话虽如此,并且考虑到您应该像生产代码一样对待您的测试代码,您应该努力进行简洁的设计 - 在这种情况下,DRY

每种语言都有自己的方法来实现这一目标,但通常提取方法都可以解决问题。就其本身而言,如果它们是孤立的,明确的意图等,那么进行许多测试是没有害处的。

例如,xUnit(C#)解决此问题的方式如下所示:

[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData("\t \n")]
[InlineData("asd")]
public void Add_NonNumber_ZeroReturned(string numbers)
{
    var underTest = new UnderTest();
    var result = underTest.Add(numbers);
    Assert.Equal(0, result);
}

答案 2 :(得分:0)

你应该有很多单独的测试方法,不要担心它们中有多少。

尝试将多个测试塞入方法中的坏处是,当测试失败时,您不知道破坏的真实程度,因为测试的一部分失败会阻止测试的其余部分运行。 当您看到测试中断并进行修复时,结果可能会出现更多失败。

如果您组织测试以便在不同的测试中处理不同的案例,那么您将立即看到所有失败。

如果所有边缘情况都是传入不同数据的实例,并且它们都以相同的方式调用,您可能需要检查测试框架是否支持参数化测试。

答案 3 :(得分:0)

您应该将所有这些边缘案例值的数组与测试分开。

String[] edgeCaseValues = {""," ","\t \n","asd"};

然后在测试中你可以简单地遍历它们将它们传递给你的函数

foreach(var edgeCaseValue in edgeCaseValues)
{
    $stringCalculator = new StringCalculator();
    $this->assertSame(0, $stringCalculator->add(edgeCaseValue));
}

这样您就可以在其他测试中重复使用它们,如果添加新的边缘案例值,它们将全部添加到所有测试中