0

以前,我实现单元测试只是为了测试一个方法是否有效。但是在其他地方阅读之后,似乎我应该在方法失败时进行测试。

例如,一个方法应该抛出一个异常,它传递了一个字符串。

这些要求从何而来?

我在一个敏捷团队中工作,因此我们获得了用户故事,其中包括应用程序功能的基本要求。这些基本要求包括非常简单的 要求(即密码长度最多为 8 个字符)。

然后,我在考虑需求的情况下从这个用户故事创建任务。

因此,在测试时……我究竟应该测试什么?

我想我应该测试该方法(它是作为用户故事的一部分的任务的一部分)以它应该的方式运行,但我还应该测试它是否应该失败?

例如,当要求最多 8 个字符时,将 12 个字符传递给方法的参数(密码)。我必须为此包含一个测试用例吗?

有谁知道一个很好的资源或链接来解释更多关于这个主题的信息?

我假设没有要求,我只能测试该方法是否成功以及它是否失败,因为我不知道它何时应该失败,因为没有要求?

任何人都可以提供的任何帮助都会非常有帮助。

4

3 回答 3

1

从快乐路径测试开始。您的快乐路径应该基于需求中的用例。

当您涵盖所有快乐的路径时,请继续进行边界测试。因此,当它应该是 8 个字符的密码时,请对 7、8、9 个字符进行测试并涵盖相应的场景。

在你涵盖了所有的快乐路径和边界测试之后,问问自己我该如何编写失败的测试?如果你能弄清楚,那就写吧。如果应该提出异常,则将其覆盖。考虑到这一点,您可以轻松找出应该测试的内容以及不需要测试的内容。

于 2012-07-22T20:01:02.293 回答
1

我认为您对失败测试的阅读过多。这意味着在编写代码之前编写测试(除了总是返回无效值如 null 的存根)。这样你就知道当它失败时你有代码要写。然后,您编写代码并再次测试。测试现在应该通过了。测试驱动的开发应该总是这样工作。

于 2012-07-22T16:54:43.157 回答
1

虽然您当然不能测试所有可能性,但您至少应该测试代码中考虑的可能性。

因此,在您的示例中,传递给方法的字符串不得超过 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
}

注意测试方法的名称。它们听起来像是要求。这个想法是,陈述的需求应该被分解成实际的规范。业务需求是:

  • 密码不应超过 8 个字符

但是那里有隐含的要求吗?要求如:

  • 提供的与已知密码匹配的密码应导致身份验证。
  • 提供的与已知密码不匹配的密码不应导致身份验证。

毕竟,方法正在做所有这些事情。如果该方法正在做某事,则应该测试该方法。最终,代码所做的每一件事都应该至少有一个对应的测试来映射需求。

事实上,如果测试写得好,它们就会开始成为需求。这很好,因为这意味着相关知识(需求)可以保存在一个地方(测试)而不是多个不同的地方(测试、代码、文档、白板等)。

如果有一行代码没有被测试执行,那为什么那行代码在那里?如果没有测试,那么就没有要求。如果没有要求,请将其删除。

于 2012-07-22T17:14:20.747 回答