如果每个测试只能有一个断言;如何测试多个输入?


15

我正在尝试建立一些测试用例,并且已阅读到您应该尝试限制每个测试用例的断言数量。

所以我的问题是,测试带有多个输入的功能的最佳方法是什么?例如,我有一个函数,可分析用户的字符串并返回分钟数。字符串可以采用形式"5w6h2d1m",其中w, h, d, m对应于星期,小时,天和分钟数。

如果我想遵循“每个测试规则1条断言”,我将不得不对每种输入变化进行多次测试?这似乎很愚蠢,所以我只有这样:

self.assertEqual(parse_date('5m'), 5)
self.assertEqual(parse_date('5h'), 300)
self.assertEqual(parse_date('5d') ,7200)
self.assertEqual(parse_date('1d4h20m'), 1700)

在一个测试用例中。有没有更好的办法?


最好的方法是使用参数(某些框架支持此功能,所有框架都应如此)。这样,您正在测试单个行为,但考虑到许多测试用例,并且如果出现错误,仍然可以看到哪些参数值导致了错误
Kemoda 2012年

Answers:


23

一种查看每个测试“规则”中的一个断言的更为实用的方法是,使您的断言在单个测试中涵盖单个概念。

这样,您仍然可以在单个测试中测试单个概念。就您而言,您的输入字符串是否在单个日期中被正确解析。

您应该根据案例进行判断,以检查是否最好测试具有多个断言的单个概念,或者在多个测试中具有单个断言。

选择使测试更清晰,重复更少的选项,同时使您的测试能够突出显示方法中的不同故障点。您希望清楚测试失败的确切时间,而不必调试测试以找出错误的原因。


17

这在很大程度上取决于您的测试库。在C#库NUnit中,您可以执行以下操作:

[TestCase('5m', 5)]
[TestCase('5h', 300)]
[TestCase('5d', 7200)]
[TestCase('1d4h20m', 1700)]
public void ParseDateTest(inputString, expectedMinutes)
{
    Assert.That(parse_date(inputString), Is.EqualTo(expectedMinutes));
}

在具有testng的Java中,您具有@DataProvider方法
Kemoda 2012年

这是最好的解决方案恕我直言。您几乎可以使用每种语言来参数化测试。对于Java:@ParameterizedJunitParamsZohhak
piotrek

3

是的,对每种输入变化进行多次测试。

每个测试准则一个断言的主要目标是(理想情况下)使一个错误导致一个测试失败,反之亦然,以便您确切地知道失败的原因。然后,您可以使用一种非常精确的测试来调试根本原因并进行验证。您可以使用一个断言来打破这一点,而使用多个断言也可以。在这种特殊情况下,我将对每个后缀和一些排序组合进行测试。

希望很清楚为什么隔离测试是有好处的:当出现问题时,您可以浪费更少的调试时间。现在,如果您真的确定测试不太可能失败,并且通过测试的开销很小,那么可能一次只测试它们以节省实现时间可能是有意义的。

但是历史表明,花一点时间写代码而不是以读取/使用代码为代价是值得的。因此,指南。


1

纯粹主义者会说,对于不同输入值的断言应放在测试类中的单独测试方法中。原因之一是,根据测试UI,区分单个测试失败通常比区分单个声明要容易得多,这可能会使您更快地确定失败的根源。

使用JUnit进行测试时,我们可以通过使用带有初始String参数的assert *方法的版本来解决此问题,以在同一测试方法中将一个断言与另一个断言区分开。

self.assertEqual("just minutes", parse_date('5m'), 5)
self.assertEqual("just hours", parse_date('5h'), 300)
self.assertEqual("just days", ('5d') ,7200)
self.assertEqual("days, hours, minutes", parse_date('1d4h20m'), 1700)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.