1

在进行单元测试时,是否应该边缘案例测试相同的方法,每个都需要单独的测试方法。例如,测试传递给以下函数的空字符串:

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

我显然想捕捉边缘情况,例如:

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

ETC

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

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

4 回答 4

1

在这个简单的情况下(一个实际的功能,即没有副作用,没有异常,基本上每个测试用例一行)我会说一个单一的测试方法就可以了。

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

于 2012-10-29T22:03:23.390 回答
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);
}
于 2012-10-30T14:05:39.257 回答
0

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

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

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

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

这样你就可以在其他测试中重用它们,如果你添加一个新的边缘案例值,它们都会被添加到所有测试中

于 2012-10-30T14:16:04.020 回答
0

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

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

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

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

于 2012-10-30T14:10:06.043 回答