【问题标题】:How to apply "One Assertion Per Test" for OR relation condition如何为 OR 关系条件应用“每个测试一个断言”
【发布时间】:2009-06-03 05:27:33
【问题描述】:

在断言中“每个测试一个断言”是公认的。写断言不好如下:

  Assert((foo != null) && (bar != null));

更好的选择是:

  Assert(foo != null);
  Assert(bar != null);

问题是如果断言是:

  Assert((foo == null) || (foo.length == 0));

关系是 OR 而不是 AND。

有没有什么方法可以在保持逻辑的同时做出“每个测试一个断言”?

【问题讨论】:

    标签: unit-testing assert


    【解决方案1】:

    该指南背后的想法是,您只在一次测试中测试一件合乎逻辑的事情(在某些情况下可能归结为 几个 断言)。因此,如果测试失败,您就会知道失败的确切原因,并且可以快速进入特定的代码块。借用this page 的示例,如果以下测试失败,我知道在地址类型中提取/确定国家/地区的方式有问题。

    public void testCountry() throws Exception {
            assertEquals("COUNTRY",  anAddress.getCountry());
        }
    

    将此与具有多个断言的测试版本进行比较,它可能因多种原因而失败(除非您使用有用的断言消息),您需要调试测试(糟糕!)。

    我需要看看你的完整测试。从它所看到的情况来看,您似乎正在检查集合中是否存在未找到的场景。在这种情况下,建议返回一个空集合,以便客户端不必检查 null。由于您的测试也是一个客户端,它的生活也变得更简单:Assert.AreEqual (0, foo.length)

    【讨论】:

    • 好答案!单元测试是指在一个的情况下测试一个单元。
    【解决方案2】:

    问题不在于断言,而在于测试用例的Arrange or Act 部分:当您进行单元测试时,您在受控环境中调用了[小] 段代码。也就是说,您应该知道被测软件的行为方式,从而知道它会返回空指针还是空字符串。 每个测试都应有一个预期结果

    ... 除非您针对多个行为不同的函数/方法或某些在不同情况下表现不同的第三方代码使用测试。 如果是这种情况,“每个规则一个断言”只是一个指导方针,您可以使用问题所示的断言。如果此测试失败,则意味着返回的 foo 是一个非空字符串。

    或者,您可以创建一个函数来测试空字符串,该函数还将测试字符串指针是否为空:

    Assert(is_empty_string(foo));
    

    你的语言字符串类可能会提供这个方法。

    【讨论】:

      【解决方案3】:

      当然:一项测试确保 foo 断言为空,一项测试确保长度为 0 的非空 foo 也失败(其他人检查 foo 不为空 具有长度的情况! = 0)。比检查 AND 有什么好处?

      编辑:按要求编写伪代码...:

        should_assert(themethod(foo=null))
        fakefoo = fakewhatever(length=0)
        should_assert(themethod(foo=fakefoo))
        ...rest of tests w/foo not null, w/length != 0
      

      例如,在带有静态伪代码 mock 的 Python 单元测试中,这可能是:

        self.assertRaises(AssertionError, theobj.themethod, null)
        fakefoo = mock.makeObj(length=0)
        self.assertRaises(AssertionError, theobj.themethod, fakefoo))
        ...rest of tests w/foo not null, w/length != 0
      

      【讨论】:

      • 我对python不熟悉。但是,我还是一头雾水。我可以把它翻译成下面吗?断言(foo == null);断言(foo.length == 0);这看起来不对。
      • 呃?如果您断言两者都是 AND,那么它当然看起来不正确......断言 OR 意味着,例如,断言(A 或 B)-> 如果不是 A,则断言 B——在 Python 或其他任何地方!- )
      • 或者更确切地说:如果 A 则断言(False)否则断言(B);-)
      • 知道了。我正在使用 C#,它可能不如 python 强大。 Assert 的签名如下:“Assert(bool condition, string msg);”有什么办法吗?
      • C# 的能力和 Python 大致相当 -- Assert(foo==null || foo.length==0, "invalid foo: non-null & non-empty") [[我想如果断言失败,则会发出 msg,并且德摩根定律说 (not(a or b)) == (not a and not b)]]。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2018-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多