使用参数化测试" ExpectedResult"并遵循Osherove的三部分命名惯例

时间:2016-05-26 18:41:33

标签: c# unit-testing nunit

我非常喜欢Roy Osherove关于命名单元测试的3部分命名约定:

  

[UnitOfWork_StateUnderTest_ExpectedBehavior]

对我来说意味着什么(即使使用参数化输入):

[TestCase("user1")]
[TestCase("user2")]
public void SayHello_OnExistingUser_ReturnsHelloMessage(string username) 
{
    Assert.AreEqual("Hello " + username, SayHello(username));
}

[TestCase("badusername")]
[TestCase("")]
public void SayHello_OnNonExistingUser_ReturnsNull(string username) 
{
    Assert.IsNull(SayHello(username));
}

但是,使用参数化单元测试并且每个测试用例具有指定的预期结果时,这有点棘手,例如:

[TestCase("user1", ExpectedResult = "Hello user1")]
[TestCase("user2", ExpectedResult = "Hello user2")]
[TestCase("badusername", ExpectedResult = null)]
[TestCase("", ExpectedResult = null)]
public void TESTNAMEHERE(string username)
{
    return SayHello(username);
}

对于 StateUnderTest ExpectedBehavior 的参数,测试名称应该是什么不太明显。我听说过建议不要使用"期望的结果"因为这个原因,在TestCase中,它似乎是一个可以简化测试代码的潜在功能。

我想听听有关如何执行此操作的一些建议。放弃ExpectedResult为了单元测试命名清晰度?或者为测试代码简洁交换一些清晰度?

2 个答案:

答案 0 :(得分:1)

ExpectedResult非常方便,并且总是违反了良好命名的原则。但有时会这样,在这种情况下,你的代码试图告诉你一些事情。

对于成功案例,SayHello_OnExistingUser_ReturnsExpectedGreeting等名称将起作用。

对于不成功的案例,SayHello_OnNonExistingUser_ReturnsNull也会有效。

只有尝试将逻辑上两个不同的测试组合成一个你遇到麻烦的测试。所以不要这样做。事实上,相同的代码可用于编写两个完全不同(逻辑上)不同的测试,这只是一个意外。

答案 1 :(得分:1)

据我了解,Roy Osherove的命名理念的目的是更快看到失败测试的摘要,而没有明确打开测试方法的细节。

因此NUnit的{​​{1}}有一个属性TestCaseAttribute。该属性的值将在测试资源管理器中用作测试名称。

或者使用更通用的名称进行测试,例如:
TestName