C# 我应该在一个简单的get属性上测试多重?

C# 我应该在一个简单的get属性上测试多重?,c#,unit-testing,C#,Unit Testing,我是。。。有点像是单元测试的初学者 我刚刚读了一些单元测试最佳实践。理解单元测试是为了防止对代码所做的更改破坏应用程序。我们希望在所有对象的公共API(getter,methods)上创建测试用例来测试对象的行为,看看是否如我们所期望的那样 所以现在。。我需要测试一个简单的类: public class Foo{ private readonly string _text; public Foo(string initialText) { this._text =

我是。。。有点像是单元测试的初学者

我刚刚读了一些单元测试最佳实践。理解单元测试是为了防止对代码所做的更改破坏应用程序。我们希望在所有对象的公共API(getter,methods)上创建测试用例来测试对象的行为,看看是否如我们所期望的那样

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

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属性准确返回我在构造函数中传递的内容非常重要

这是我写的测试用例

[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);
}
我想知道这是否。。。太重了

因此,我认为确保Text属性准确返回我在构造函数中传递的内容非常重要

这是一个令人振奋的时刻。它获取在构造函数中设置的
\u文本
字段

在初始化类之后,除了检查getter返回的值之外,做任何事情都是过分的,甚至可以认为这是在测试一些不需要测试的东西


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

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

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

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

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

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

[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
更改为其他名称,会发生什么情况?现在有很多单元测试需要重新命名以满足这一需求。我的建议是,您根据正在进行的测试的上下文来命名测试(例如,给定一个带有一个字母的字符串,除了该字母)。这样,如果重命名代码中的内容,测试不会受到影响


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

鉴于属性的简单性质,我认为这有点过分了。对于几乎微不足道的字符串测试,我喜欢将其保留为3个测试:null、empty或其他

[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);
}

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

它太重了,而且还有些问题。为什么不检查一下指标,看看你已经测试了100%的路径。不管怎么说,代码路径最终可能会使用这个属性,也就是说,我通常会为setter/getter对编写一个简单的测试,但那就是我。+1-你通常不需要测试getter和setter。任何使用您的对象的测试最终都会覆盖getter和setter,您要测试的是行为/逻辑,而不是代码行。@Oded但编写单元测试并不是为了防止代码更改会破坏程序?因此,如果将来有人对文本属性getter做了一些修改,这将破坏我的程序,那么我应该对此进行测试?@KingChan-编写测试非常昂贵。你应该编写重要的测试。测试软件的逻辑比测试简单的属性更重要。@Oded我明白了,但我有另一个属性,它包含嵌入在属性getter中的算法(解析文本格式)。在这种情况下,我应该测试一下,对吗?@KingChan-是的,尽管你可能应该将它从属性更改为方法(因为人们不希望属性做太多工作)。但是说到重命名。。如果有人重新命名这个方法,这不是一回事吗?如果属性包含逻辑呢?因为我有另一个属性,所以这个人把解析算法放在Getter中…看看我的测试示例,如果你重命名了这个方法,那么测试名称中没有任何东西需要重命名,因为它们没有提到方法名称。所以你不必为此担心。至于属性——如果属性应该简单,我的偏好是,如果可能的话,几乎没有逻辑。如果您需要大量的逻辑,请使用一种方法,即
GetText()
。属性应该尽可能简单。测试名称不应该是要测试的include方法/属性名称吗?在这种情况下,更容易阅读,并且知道发生了什么。从这里开始:我构造测试的方式如下:假设我有一个类
TestClass
,带有一个方法
TestMe()
。在项目中,我将有一个名为
testclassests
的根文件夹,然后是一个子文件夹
TestMe
。在
TestMe
文件夹中,我有测试的.cs文件,例如
给定的一些上下文.cs
。但这只是一种方法,人们有自己喜欢的命名测试的方法。