【问题标题】:Are multiple asserts wrong in this test?此测试中的多个断言是否错误?
【发布时间】:2013-11-21 11:25:39
【问题描述】:

我正在尝试测试一个名为 Login 的方法,当用户和密码参数正确时,设置两个会话变量和三个 cookie 的值并最终返回 true。

我已经阅读了几篇关于单元测试的文章,但不知何故,这并没有让我完全清楚我的情况。我知道每个单元测试应该只有一个断言,尽管你可以使用多个断言,只要你测试一个“逻辑概念”。

登录方法只有在正确设置每个会话变量和cookie并返回预期值时才是正确的,所以我不确定一次检查所有这些值是否可以(这将导致我使用六个断言在单元测试中,我觉得有点脏)或者我是否应该在不同的测试中分别检查每个会话变量和 cookie 的值。

[TestMethod()]
public void SuccessfulLoginTest()
{
    // Arrange.
    String username = "foo";
    String password = "correct password";
    Boolean remember = true;

    // Act.
    Boolean actual = Login(username, password, remember);

    // Assert.
    Assert.IsTrue(actual);
    Assert.AreEqual("foo", HttpContext.Current.Session["Username"]);
    Assert.AreEqual(1, HttpContext.Current.Session["Group"]);
    Assert.AreEqual("foo", HttpContext.Current.Response.Cookies["Username"].Value);
    Assert.AreEqual("en", HttpContext.Current.Response.Cookies["Lang1"].Value);
    Assert.AreEqual("es", HttpContext.Current.Response.Cookies["Lang2"].Value);
}

【问题讨论】:

  • 每个测试用例应该只有一个断言is foolish的想法。

标签: c# visual-studio unit-testing assert


【解决方案1】:

我也觉得不错。我不确定您从哪里得到每个单元测试应该只有一个 Assert 的概念。这听起来像是一个“象牙塔”规则,只是简单的愚蠢的国际海事组织。如果您的方法在给定特定输入的情况下设置了一堆变量,那么您应该检查给定输入的所有这些变量。编写六个不同的单元测试(以及相关的设置代码)似乎非常低效。

但是在编写软件时,我倾向于实用主义而不是学术“正确性”。

【讨论】:

  • 该规则说每个测试大约有一个 逻辑断言,OP 已经提到了这一点。这不是“学术”也不是“愚蠢”。
  • 也许“每个测试一个逻辑断言”意味着每个断言一个子句,所以不要使用Assert(theSkyIs(blue) && theSeaIs(deep));,而是使用Assert(theSkyIs(blue));Assert(theSeaIs(deep));
【解决方案2】:

您已经正确地注意到,一个断言规则涉及概念断言,而不是对Assert 方法的裸调用。当一个逻辑断言由许多断言组成时,一个很好的常用技巧可以减少混淆,并使测试更具可读性,这是将断言包装在实用程序方法中。在您的情况下,它可能看起来类似于:

void AssertSessionIsValid(string username, int group, ...)
{
    Assert.AreEqual(username, HttpContext.Current.Session["Username"]);
    Assert.AreEqual(group, HttpContext.Current.Session["Group"]);
    ...
}

有许多框架有助于提高测试的可读性,例如 Shouldly

【讨论】:

    【解决方案3】:

    我建议断言你关心的是“工作”的一切,仅此而已。断言太少,您的测试将忽略明显损坏的功能;太多了,当一些不相关的细节发生变化时,您的测试将变得脆弱和不必要地中断。

    【讨论】:

      【解决方案4】:

      在布尔变量中匹配您的条件,如果所有条件都满足,则布尔变量应返回 true。

      资产这个布尔变量

      bool AreAllConditionsFulfilled = condition1 && condtionCheckingSessionVariablesOne && conditionCheckingSessionVariablesTwo
      

      另外我建议用单独的测试用例测试每个会话变量并断言它们是否正确。

      [Test]
      public void TestUserNameSessionVariable()
      {
      //Login Code
      Assert.AreEqual("foo", HttpContext.Current.Session["Username"]);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-25
        • 1970-01-01
        • 1970-01-01
        • 2016-07-25
        • 1970-01-01
        • 2015-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多