【问题标题】:How to name and organize unit tests that test a method with multiple parameters?如何命名和组织测试具有多个参数的方法的单元测试?
【发布时间】:2011-03-10 13:00:17
【问题描述】:

鉴于此方法必须经过测试:

// Search the given value using the provided search options
// Return true if the searchValue was found; false otherwise 
bool Search(string searchValue, bool useExactSearch, bool useIndexing)

我有 6 个重要的 searchValues(一个带有标点符号,一个带有重音字符,一个带有换行符等),我需要使用 useExactSearch 和 useIndexing 的每种可能组合来验证它们。这意味着 54 个测试用例。

你是怎么做的?你真的会写 54 个单元测试吗?如果是这样,你如何命名它们?您是否只为最重要的案例编写测试?您是否编写了一个循环遍历参数值和预期结果表的单元测试?如果我做一个单元测试,当持续集成报告失败时,就很难找到哪个案例被打破了。

【问题讨论】:

    标签: unit-testing language-agnostic


    【解决方案1】:

    如果您使用的是 NUnit (.Net),您可以这样做:

    [TestCase("John*",true, false, false)]
    [TestCase("*user*",false, true, true)]
    [TestCase(".",true, false, true)]
    public void SearchTest(string param1, bool param2, bool param3, bool expectedResult)
    {
        YourClass clazz = new YourClass();
        bool result = clazz.Search(param1, param2, param3);
        Assert.AreEqual(expectedResult, result);
    }
    

    NUnit Test Runner 将执行 3 次。而且,如您所见here,报告显示所有测试用例分离,这有助于您确定谁破坏了构建。 这可能在大多数 xUnit 框架上都可用。

    【讨论】:

      【解决方案2】:

      在他的《单元测试的艺术》一书中,Roy Osherove 建议使用这种命名约定:

      MethodUnderTest_ConditionUnderTest_ExpectedBehaviour()
      

      这似乎是合理的。至于如何用不同的参数对同一个函数进行多次测试,我认为单独的测试会更清楚哪里出了问题,你可以使用重构来尽量减少测试之间的重复。

      附带说明,它与语言无关,但 NUnit 允许参数化测试,因此其他单元测试框架也可以这样做。这是“一个难以理解的失败原因”测试和 54 个“几乎相同,有大量重复”测试之间的一个很好的折中点。

      【讨论】:

      • 我对这个约定没有印象。如果我们可以测试它,它必须是确定性的。这意味着预期的行为完全由被测方法和被测条件决定,因此名称的第三部分是多余的。其次,如果您的设计发生变化,预期的行为可能会发生变化,但您可能仍希望针对该条件测试该方法。
      • @Raedwald:是的,它应该是完全确定性的,但是如果你回到一年前写的测试,很高兴为你解释清楚你的期望。至于你的第二点,如果预期的行为发生变化,测试逻辑就会改变,所以你可以在那个时候重命名它。
      • “很高兴为您解释您所期望的内容”,这些都应该在断言消息中。
      • 一般我也使用“3部分命名风格”,例如我喜欢一个名为Seach_WhenSearchingPartialWordsWithIndexingTurnedOn_NoResultsAreFound的测试。但是当一个方法有 54 个用例时,测试名称会变得相当长且难以理解。
      • @Raedwald:是的,这是在断言消息中,但将其放在方法名称中的一个很好的理由是,您可以快速了解测试运行摘要中失败的原因。
      【解决方案3】:

      至少应该为重要的测试用例编写测试,并且可以根据测试用例命名测试,例如 TestSeachForPunctuation、TestSeachForAccentedChars、TestSeachForLineBreaks。

      【讨论】:

        【解决方案4】:

        如果您使用模式MethodUnderTest_ConditionUnderTest_ExpectedBehaviour(),有时将参数化测试分为正面和负面场景可以让您更好地命名测试方法名称的“ConditionUnderTest”和“ExpectedBehaviour”部分。

        参见https://freecontent.manning.com/making-better-unit-tests/上给出的示例

        作为一种折衷方案,您可以将肯定的测试用例提取到自己的测试中,并从最重要的描述性命名中受益——确定有效和无效交付日期的区别(清单 12)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-25
          • 1970-01-01
          • 2016-02-17
          • 1970-01-01
          • 1970-01-01
          • 2019-02-03
          相关资源
          最近更新 更多