2

我是……单元测试的初学者。

我刚刚阅读了一些单元测试最佳实践。有点理解单元测试旨在防止对代码进行的更改会破坏应用程序。我们将希望在所有对象的公共 API(getter、方法)上创建测试用例来测试对象的行为,看看是否符合我们的预期。

所以现在..我有一个简单的类需要测试:

public class Foo{
   private readonly string _text;

   public Foo(string initialText)
   {
      this._text = initialText;
   }

   public string Text {get;}

   //Some other methods that will use this Text property to parsing, comparasion etc
   public string RichTextFormat {....}
}

在这里,就像在评论中一样,这个Text属性在解析、比较等方面使用了很多地方。

所以我认为确保Text属性完全返回我在构造函数中传递的内容非常重要。

这是我写的测试用例...

[TestMethod]
public void Text_WhenInitialTextIsNull()
{
    string initalizeText = null;
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

[TestMethod]
public void Text_WhenInitialTextIsEmpty()
{
    string initalizeText = string.Empty;
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

[TestMethod]
public void Text_WhenInitialTextIsOneLetter()
{
    string initalizeText = "A";
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

[TestMethod]
public void Text_WhenInitialTextIsOneSpecialCharacter()
{
    string initalizeText = "!";
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

[TestMethod]
public void Text_WhenInitialTextIsOneSentense()
{
    string initalizeText = "Hello, World!";
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

[TestMethod]
public void Text_WhenInitialTextIsOneParagraph()
{
    string initalizeText = "Who's the Smartphone Winner? " + System.Environment.NewLine +
                           " On the smartphone front, however, iSuppli put Apple at number one," +
                           " while Strategy Analytics pointed to Samsung. " + System.Environment.NewLine +
                           " According to iSuppli, Apple shipped 35 million smartphones in the first quarter" +
                           " to Samsung's 32 million. Strategy Analytics, however, said Samsung's total was" +
                           " 44.5 million to Apple's 35.1 million. Nokia landed at number three on both lists" +
                           " with 12 percent market share. ";
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

我想知道这……是不是太重了?

4

4 回答 4

4

所以我认为确保 Text 属性完全返回我在构造函数中传递的内容非常重要。

它是一个吸气剂。它获取_text您在构造函数中设置的字段。

除了在类初始化后检查从 getter 中返回的值之外,做任何事情都是多余的,即使这样也可能被认为是测试不需要测试的东西。

测试基本 C# 功能是否按预期工作是没有意义的......

于 2012-04-27T14:59:39.027 回答
2

由于您没有操纵传入的值,因此我建议您进行一项测试以确保正确设置了该值。鉴于此,以下测试就足够了。

[TestMethod]
public void TextReturnsTextPassedToConstructor()
{
    string text = "A string";
    Foo foo = new Foo(text);

    Assert.AreEqual(text, foo.Text);
}

只有在构造函数中正在进行额外的逻辑或字符串操作时,才值得添加其他测试。例如,如果您在字符串为空或空的情况下抛出异常,或者您正在执行字符替换等。

于 2012-04-27T15:01:37.170 回答
0

我认为您需要更改测试的上下文。我的意思是不要将测试集中在Text属性上,而是这样做:

[TestMethod]
public void given_null_string_expect_null()
{
    string initalizeText = null;
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

[TestMethod]
public void given_special_character_string_expect_that_character()
{
    string initalizeText = "!";
    Foo realFoo = new Foo(initalizeText);
    Assert.AreEqual(initalizeText, realFoo.Text);
}

等等。

重点是:如果将属性名称从更改为其他名称会发生Text​​什么?您现在有很多单元测试需要重命名以适应这种情况。我的建议是您根据正在发生的事情的上下文来命名测试(例如,给定一个带有一个字母的字符串,期望那个字母)。这样,如果您重命名代码中的内容,您的测试不会受到影响。

我的另一点是你不需要在这个级别进行测试。一个属性并不值得你花时间去测试。相反,您最好的测试方法或与其他类的集成,而不仅仅是一个属性。

于 2012-04-27T15:02:23.703 回答
0

鉴于您的财产的简单性质,我认为这有点矫枉过正。对于字符串上近乎琐碎的测试,我喜欢将其保持在 3 个测试中:null、empty、something。

[TestMethod]
public void Test_Text_Null()
{
    Assert.AreEqual(null, new Foo(null).Text);
}

[TestMethod]
public void Test_Text_Empty()
{
    Assert.AreEqual("", new Foo("").Text);
}

[TestMethod]
public void Test_Text_Something()
{
    Assert.AreEqual("abc", new Foo("abc").Text);
}

一般来说,我不会尝试对如此简单的输入的每一个可能的变化进行单元测试。如果您将来遇到错误,因为有人修改了 Foo 现在它会在您有逗号时中断 - 然后将其添加到您的单元测试套件中。一路上的单元测试是好的——但不要让它瘫痪你继续完成项目的能力。

于 2012-04-27T15:08:30.123 回答