C#单元测试 - 重载方法测试的命名约定

15
我正在编写一些简单的C#扩展方法,并撰写单元测试。其中一个扩展方法是重载的,因此我很难想出一个合理的命名约定用于单元测试。
重载方法示例:
public static class StringExtensions
{
    public static List<string> ToList(this string value, char delimiter)
    {
        return ToList(value, new[] { delimiter });
    }

    public static List<string> ToList(this string value, char[] delimiterSet) { .. }
}

如果我想编写两个单元测试,一个测试每个方法,那么你会如何命名这些测试?通常我只会简单地使用:

[TestMethod, TestCategory("Single Method Tests")]
public void ToListTest

但是由于存在同名的两个方法,我很难找到一个好的约定方式。

[TestMethod, TestCategory("Single Method Tests")]
public void ToListTest

[TestMethod, TestCategory("Single Method Tests")]
public void ToListTestOverload

十分糟糕。

[TestMethod, TestCategory("Single Method Tests")]
public void ToListTestWithChar

[TestMethod, TestCategory("Single Method Tests")]
public void ToListTestWithCharArray

基于参数类型的方式更好,但仍然非常糟糕。

有些人可能建议编写一个测试方法来同时测试两个重载方法,但我理想情况下希望每个单元测试方法都与被测方法一一对应,即使这些重载方法当前是链接在一起的。 我不希望测试中做出任何假设,即这些重载方法是链接在一起并且会传递参数。

你会如何解决这个问题?

3个回答

18

Roy Osherove在他的书《单元测试的艺术》中推荐根据你要测试的行为来命名约定,而不一定需要在生产方法和测试方法之间建立一对一的映射关系。因此,举个简单的例子,假设我有一个堆栈类,如下所示:

public class Stack
{
    public void Push(int value);
    public int Pop();
    public bool IsEmpty();
}

编写测试的一种方法是拥有三个测试方法:

[TestMethod]
public void PushTest

[TestMethod]
public void PopTest

[TestMethod]
public void IsEmptyTest

然而,有一种更好的测试方法是指定Stack类的行为。这意味着类的行为和测试方法之间存在着一对一的映射关系。因此,其中一个行为是在空栈上调用IsEmpty会返回true,另一个行为是推入一个元素会使堆栈不为空。然后,我会按照这些普通英语句子在安排/操作/断言格式下编写测试。

MethodName_StateOfTheObject_ExpectedResult

因此,对于上述提到的行为:

[TestMethod]
IsEmpty_OnEmptyStack_ReturnsTrue

[TestMethod]
Push_OnEmptyStack_MakesStackNotEmpty

我建议您考虑一下要在上述方法中测试的行为,然后将这些行为映射到测试用例中。例如:

[TestMethod]
ToList_OnEmptyString_ReturnsEmptyList

[TestMethod]
ToList_OnStringWithDelimiters_ReturnsListWithTokensSeparatedByDelemiter

[TestMethod]
ToList_OnStringWithoutDelimiters_ReturnsListWithOneString

更多信息请在这里查看。


1
谢谢,回过头来看,我喜欢这种方法,而且提供了一个很好的链接。+1 和答案。 - KP.

4

我倾向于选择后者,不完全是基于传递的参数,而更多地是基于正在测试的实际功能。

因此,不是:

  • TestFunctionWithListOfNumbers
  • TestFunctionWithListOfStrings

而是可能是:

  • TestFunctionWithStudentIDs
  • TestFunctionWithStudentNames

我倾向于使用Test_Function_WithStudentIDs,这是我在方法名称中唯一使用“_”的时候。 - Ian Ringrose
我喜欢这个想法,但问题在于这些方法是通用扩展方法,可以与任何信息一起使用。基于功能的命名将是一个挑战。 - KP.
1
@KP:在这种情况下,参数之间的语义差异只是它们的类型,因此我想类型会是最好的选择。 - R. Martinho Fernandes

4

我倾向于以更多的Given, When, Then方式编写测试名称。这使得测试名称冗长,但它告诉我被测试的函数意图是什么。因此,在您的情况下,我会将测试命名为

[TestMethod]
public void GivenSingleCharDelimeter_ToList_Returnsxxx()
[TestMethod]
public void GivenCharArrayDelimeter_ToList_Returnsxxx()

1
谢谢。我对这种方法越来越感兴趣了。+1。我标记了Brian的回答,只是因为他比你早了1分钟,并且包含了更多的细节。 - KP.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接