虽然您当然不能测试所有可能性,但您至少应该测试代码中考虑的可能性。
因此,在您的示例中,传递给方法的字符串不得超过 8 个字符(顺便说一句,这是对密码的可怕要求),该方法可能如下所示:
public bool IsPasswordCorrect(string password)
{
if (password.Length > 8)
throw new ArgumentException("Password must not be greater than 8 characters.");
return password == SomeKnownPassword;
}
目标应该是 100% 的代码覆盖率。这意味着实际执行某些操作的每一行代码都应该至少有一个相应的测试。因此,如果唯一的测试是针对“快乐路径”(不超过 8 个字符的字符串),throw
则永远不会测试该行。
那行代码是为了响应需求而存在的,因此应该测试该需求。在这种情况下,您将进行一些测试:
[TestMethod]
public void MatchingPasswordsShouldBeAllowed()
{
// set the known password
// set the passed password
// call the method
// assert that the method returned true
}
[TestMethod]
public void NonMatchingPasswordsShouldNotBeAllowed()
{
// set the known password
// set the passed password to something else
// call the method
// assert that the method returned false
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void PasswordsShouldNotBeGreaterThanEightCharacters()
{
// set the known password
// set the passed password to something too long
// call the method
// assert that an exception was thrown
}
注意测试方法的名称。它们听起来像是要求。这个想法是,陈述的需求应该被分解成实际的规范。业务需求是:
但是那里有隐含的要求吗?要求如:
- 提供的与已知密码匹配的密码应导致身份验证。
- 提供的与已知密码不匹配的密码不应导致身份验证。
毕竟,方法正在做所有这些事情。如果该方法正在做某事,则应该测试该方法。最终,代码所做的每一件事都应该至少有一个对应的测试来映射需求。
事实上,如果测试写得好,它们就会开始成为需求。这很好,因为这意味着相关知识(需求)可以保存在一个地方(测试)而不是多个不同的地方(测试、代码、文档、白板等)。
如果有一行代码没有被测试执行,那为什么那行代码在那里?如果没有测试,那么就没有要求。如果没有要求,请将其删除。