我有一个“最佳做法”问题。我正在为某个方法编写测试,但是有多个条目值。我应该为每个条目值编写一个测试,还是应该更改entryValues变量值,并调用.assert()方法(对所有可能的值执行此操作)?
感谢您的帮助。 最好的问候,
Pedro Magueija
编辑:我正在使用.NET。 Visual Studio 2010 with VB。
答案 0 :(得分:5)
如果必须编写许多仅在初始输入和最终输出中变化的测试,则应使用数据驱动测试。这允许您定义测试一次以及输入和输出之间的映射。然后,单元测试框架将其解释为每个案例的一个测试。如何实际执行此操作取决于您使用的是哪个框架。
答案 1 :(得分:2)
最好对每个输入/输出集进行单独的单元测试,覆盖您尝试测试的方法的全部可能值(或者至少对于您要进行单元测试的输入/输出集)。 / p>
答案 2 :(得分:1)
所以,如果您有一个方法,如:
void testAll() {
// setup1
assert()
// setup2
assert()
// setup3
assert()
}
根据我的经验,这会变得非常快,因此变得难以阅读和理解,所以我会这样做:
void testDivideByZero() {
// setup
assert()
}
void testUnderflow() {
// setup
assert()
}
void testOverflow() {
// setup
assert()
}
答案 3 :(得分:1)
我应该为每个条目写一个测试 价值还是应该改变 entryValues变量值,并调用 .assert()方法(为所有人做 范围可能的值)?
如果您通常有一个代码路径,则不会测试所有可能的输入。你通常想要测试的是“有趣”的输入,这些输入可以很好地得到你将获得的数据。
例如,如果我有一个功能
define add_one(num) {
return num+1;
}
我无法为所有可能的值编写测试,因此我可以使用MAX_NEGATIVE_INT,-1,0,1,MAX_POSITIVE_INT作为我的测试集,因为它们是我可能获得的有趣值的良好代表。
每个代码路径至少应有一个输入。如果你有一个函数,其中每个值对应一个唯一的代码路径,那么我会考虑为整个可能的值范围编写测试。例如,这将是一个命令解析器。
define execute(directive) {
if (directive == 'quit') { exit; }
elsif (directive == 'help') { print help; }
elsif (directive == 'connect') { intialize_connection(); }
else { warn("unknown directive"); }
}
为了清楚起见,我使用了elif而不是调度表。我认为这清楚地表明,每个独特的值都有不同的行为,因此您需要测试每个可能的值。
答案 4 :(得分:0)
你在谈论这种差异吗?
- (void) testSomething
{
[foo callBarWithValue:x];
assert…
}
- (void) testSomething2
{
[foo callBarWithValue:y];
assert…
}
VS
- (void) testSomething
{
[foo callBarWithValue:x];
assert…
[foo callBarWithValue:y];
assert…
}
第一个版本更好,因为当测试失败时,您将更好地了解哪些不起作用。第二个版本显然更方便。有时我甚至会将测试值填入集合中以节省工作量。我通常会选择第一种方法,因为我可能只想单独调试这个案例。当然,我只选择后者,当测试值真正属于一起并形成一个连贯的单位时。
答案 5 :(得分:0)
你真的有两种选择,你没有提到你使用的测试框架或语言,因此可能不适用。
1)如果你的测试框架支持它使用RowTest,MBUnit和Nunit支持这个,如果你使用.NET这将允许你在你的方法上放置多个属性,每一行将作为一个单独的测试执行
2)如果没有为每个条件编写一个测试,并确保给它一个有意义的名称,这样如果(当)测试失败,你可以很容易地找到问题,这对你意味着什么。
修改强> 它在Nunit中称为TestCase Nunit TestCase Explination