2011-01-21 56 views
2

我有一个“最佳实践”问题。我正在为某种方法编写测试,但有多个输入值。我应该为每个输入值编写一个测试,还是应该更改entryValues变量值,并调用.assert()方法(针对所有可能的值范围进行)?单元测试写作的最佳做​​法

谢谢你的帮助。 最好的问候,

佩德罗Magueija

编辑:我使用的.NET。 Visual Studio 2010与VB。

回答

2

对每个输入/输出集合进行单独的单元测试,覆盖您尝试测试的方法的全部可能值(或至少对于您希望单元测试的那些输入/输出集合)更好。

5

如果有人不得不编写许多仅在初始输入和最终输出方面不同的测试,则应使用数据驱动测试。这允许您一次性定义测试以及输入和输出之间的映射。单元测试框架然后将其解释为每个案例的一个测试。如何真正做到这一点取决于你正在使用的框架。

+0

数据驱动(参数化)测试理论上听起来不错,但恕我直言,他们使测试案例难以理解和维护。为每个案例分别使用描述性名称进行测试有助于我更好地理解用例。公平的,这意味着一些重复的代码,但重构可以最小化到可负担的水平。 – 2011-01-23 13:46:17

+0

@Peter - 参数化测试还包含一个Description和一个Name属性以提高可读性 - 至少在NUnit中。我使用数据驱动的测试,单元测试中的所有步骤都是恒定的,只有输入 - 输出发生变化。 – Gishu 2011-02-07 09:36:27

0

你在说这个区别吗?

- (void) testSomething 
{ 
    [foo callBarWithValue:x]; 
    assert… 
} 

- (void) testSomething2 
{ 
    [foo callBarWithValue:y]; 
    assert… 
} 

- (void) testSomething 
{ 
    [foo callBarWithValue:x]; 
    assert… 
    [foo callBarWithValue:y]; 
    assert… 
} 

第一个版本是在更好的测试失败时,你就会有更好的主意,什么行不通。第二个版本显然更方便。有时我甚至会将测试值填入集合以节省工作。我通常会选择第一种方法,因为我可能要单独调试这一个案例。当然,当测试值真的属于一起并形成一个连贯的单元时,我只选择后者。

0

你真的有两个选择,你没有提到你正在使用哪种测试框架或语言,因此可能不适用。

1)如果你的测试框架支持它,使用RowTest,MBUnit和Nunit支持这个,如果你使用.NET,这将允许你在你的方法中放置多个属性,并且每行将作为单独的测试执行

2)如果不按每个条件编写一个测试,并确保给它一个有意义的名称,以便如果(当)测试失败时,您可以轻松找到问题,这对您来说意味着什么。

编辑 其所谓的TestCase在NUnit的Nunit TestCase Explination

1
  1. 较小的测试更易于阅读。
  2. 该名称是测试文档的一部分。
  3. 单独的方法可以更准确地指出失败的原因。

所以,如果你有一个像一个方法:

void testAll() { 
    // setup1 
    assert() 
    // setup2 
    assert() 
    // setup3 
    assert() 
} 

在我的经验,这会非常大非常快,所以变得难以阅读和理解,所以我会做:

void testDivideByZero() { 
    // setup 
    assert() 
} 

void testUnderflow() { 
    // setup 
    assert() 
} 


void testOverflow() { 
    // setup 
    assert() 
} 
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"); } 
} 

为了清楚起见,我使用了elifs而不是调度表。我认为这很清楚,每个独特的价值都有不同的行为,因此您需要测试每种可能的价值。

相关问题