我有一个“最佳实践”问题。我正在为某种方法编写测试,但有多个输入值。我应该为每个输入值编写一个测试,还是应该更改entryValues变量值,并调用.assert()方法(针对所有可能的值范围进行)?单元测试写作的最佳做法
谢谢你的帮助。 最好的问候,
佩德罗Magueija
编辑:我使用的.NET。 Visual Studio 2010与VB。
我有一个“最佳实践”问题。我正在为某种方法编写测试,但有多个输入值。我应该为每个输入值编写一个测试,还是应该更改entryValues变量值,并调用.assert()方法(针对所有可能的值范围进行)?单元测试写作的最佳做法
谢谢你的帮助。 最好的问候,
佩德罗Magueija
编辑:我使用的.NET。 Visual Studio 2010与VB。
对每个输入/输出集合进行单独的单元测试,覆盖您尝试测试的方法的全部可能值(或至少对于您希望单元测试的那些输入/输出集合)更好。
如果有人不得不编写许多仅在初始输入和最终输出方面不同的测试,则应使用数据驱动测试。这允许您一次性定义测试以及输入和输出之间的映射。单元测试框架然后将其解释为每个案例的一个测试。如何真正做到这一点取决于你正在使用的框架。
你在说这个区别吗?
- (void) testSomething
{
[foo callBarWithValue:x];
assert…
}
- (void) testSomething2
{
[foo callBarWithValue:y];
assert…
}
与
- (void) testSomething
{
[foo callBarWithValue:x];
assert…
[foo callBarWithValue:y];
assert…
}
第一个版本是在更好的测试失败时,你就会有更好的主意,什么行不通。第二个版本显然更方便。有时我甚至会将测试值填入集合以节省工作。我通常会选择第一种方法,因为我可能要单独调试这一个案例。当然,当测试值真的属于一起并形成一个连贯的单元时,我只选择后者。
你真的有两个选择,你没有提到你正在使用哪种测试框架或语言,因此可能不适用。
1)如果你的测试框架支持它,使用RowTest,MBUnit和Nunit支持这个,如果你使用.NET,这将允许你在你的方法中放置多个属性,并且每行将作为单独的测试执行
2)如果不按每个条件编写一个测试,并确保给它一个有意义的名称,以便如果(当)测试失败时,您可以轻松找到问题,这对您来说意味着什么。
编辑 其所谓的TestCase在NUnit的Nunit TestCase Explination
所以,如果你有一个像一个方法:
void testAll() {
// setup1
assert()
// setup2
assert()
// setup3
assert()
}
在我的经验,这会非常大非常快,所以变得难以阅读和理解,所以我会做:
void testDivideByZero() {
// setup
assert()
}
void testUnderflow() {
// setup
assert()
}
void testOverflow() {
// setup
assert()
}
我应该写一个测试为每个条目 值或者我应该改变 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"); }
}
为了清楚起见,我使用了elifs而不是调度表。我认为这很清楚,每个独特的价值都有不同的行为,因此您需要测试每种可能的价值。
数据驱动(参数化)测试理论上听起来不错,但恕我直言,他们使测试案例难以理解和维护。为每个案例分别使用描述性名称进行测试有助于我更好地理解用例。公平的,这意味着一些重复的代码,但重构可以最小化到可负担的水平。 – 2011-01-23 13:46:17
@Peter - 参数化测试还包含一个Description和一个Name属性以提高可读性 - 至少在NUnit中。我使用数据驱动的测试,单元测试中的所有步骤都是恒定的,只有输入 - 输出发生变化。 – Gishu 2011-02-07 09:36:27