单元测试 - 测试案例与多种方法

时间:2017-08-22 09:43:01

标签: unit-testing junit nunit xunit vs-unit-testing-framework

在为以下示例编写单元测试时,最佳做法是使用TestCases(例如在NUnit中),还是编写多个测试来验证功能?

假设您要测试下面的RetrieveContact方法 - 它只是在数组中找到相应的Contact,如果找到则返回结果,否则将返回null。

public class Contact
{
    public string Name { get; set; }
}

private static Contact[] Contacts =
{
    new Contact() { Name = "Jim" },
    new Contact() { Name = "Bob" },
    new Contact() { Name = "Tom" }
};

public static Contact RetrieveContact(string name)
{
    return Contacts.FirstOrDefault(c => c.Name == name);
}

你会用一种方法测试这个,使用TestCases,如下所示吗?

[TestCase("Bob", "Bob")]
[TestCase(null, "ZZZ")]
public void Test_RetrievesFromContacts(string expectedName, string name)
{
    var ret = RetrieveContact(name);
    Assert.AreEqual(expectedName, ret?.Name);
}

或者你会写两个单独的测试 - 一个用于有效的联系人,或者一个用于无效的联系人返回null?

[Test]
public void Test_RetrieveValidContact()
{
    var ret = RetrieveContact("Bob");
    Assert.AreEqual("Bob", ret.Name);
}

[Test]
public void Test_RetrieveInvalidContact()
{
    var ret = RetrieveContact("ZZZ");
    Assert.AreEqual(null, ret);
}

由于

2 个答案:

答案 0 :(得分:1)

JUnit中的约定是每个单元测试应测试一个特定的功能,一个不同的路径通过被测代码。此约定强烈暗示您不应将多个不相关的测试组合到单个测试方法中。

因此,在上面的示例中,您将为以下各项编写一个测试:

  • 一个有效联系人
  • 一个用于无效的联系人

理由是:

  • 如果将上述两个测试路径合并为一个测试,则第一个路径中的故障可能会阻止第二个路径运行(从而减少测试覆盖率)
  • 在所有其他条件相同的情况下,细粒度测试用例可能更简洁易读,即不太可能感染if firstPathFails then log and move on to second path等条件性
  • 如果您处理"无效的联系人,则无需更改解决幸福路径的测试用例("有效的联系人"在您的情况下)#34;变化。这是对SRP
  • 的引用

注意:

  • 如果测试用例中的多个相关方法需要共享设置代码,则可以使用@Before方法实现此方法,从而减少每个@Test方法的大小/可用性。
  • 上述约定并不意味着单个测试方法只能有一个断言。
  • 上述约定不一定适用于粗粒度测试,例如集成测试,其中可以测试整个应用程序片段。

答案 1 :(得分:1)

虽然您使用junit,xunit和nunit标记了帖子,但代码显然是NUnit。已发布的以junit为导向的答案对于junit来说无疑是正确的,但我将专注于您正在使用的框架和语言。

您提供的两个示例在NUnit中完全相同。在参数化方法中,每个测试用例作为独立于另一个测试用例的独立测试运行。每个结果都单独报告。

NUnit的build.gradle只不过是创建多个测试的语法快捷方式,只有使用的值不同。您使用哪种方法是风格和命名偏好的问题。在我看来,使用TestCaseAttribute方法对于可能决定添加新数据点的其他程序员来说更具吸引力。

如果在某些情况下您不想将要使用的数据类型作为C#中属性的构造函数参数,则还应考虑使用TestCase

我对您的特定用例有一个保留。当“失败”情况只返回null而没有其他副作用时,它工作正常。然而,在大多数现实场景中,失败案例会抛出异常,产生错误报告等。通常,对于失败案例或案例,通常最好采用完全独立的方法。