简体   繁体   English

对该单元进行单元测试还是不进行单元测试

[英]To Unit Test or not to Unit test this part

I have a CSV class and a CSV parser class, and their unit tests. 我有一个CSV类和CSV解析器类,以及它们的单元测试。 I want to find out if part of the unit test below must be removed: 我想确定是否必须删除以下单元测试的一部分:

public class CSV{

public string[] columns GetColumns()
        {                       
           var columns = null;

            if (!string.IsNullOrEmpty(this.textReader.ReadLine()))
            {
               var columns = this.csvParser.GetColumns(line);              
            }

            return columns;
        }



  }

   [Test]
        public void GetColumns_ReturnsCorrectLine()
        {            
            reader.Setup(r => r.ReadLine()).Returns("a\tb\tc");


            //Act
            var columns = csvReader.GetColumns();

            //Assert
            Assert.IsTrue(columns!=null);
            Assert.AreEqual(3, columns.Length);

            Assert.AreEqual("a", columns[0]);
            Assert.AreEqual("b", columns[1]);
            Assert.AreEqual("c", columns[2]);
      }

Question

1) Must the three lines of code that assert columns (a,b,c) be removed? 1)必须删除断言列(a,b,c)的三行代码吗?

2) Does the GetColumns_ReturnsCorrectLine test method perform correct unit test after removing the last three assertions 2)删除最后三个断言后, GetColumns_ReturnsCorrectLine测试方法是否执行正确的单元测试

Please note that there are already code that unit tests the CSV parser's GetColumns() method. 请注意,已经有用于单元测试CSV解析器的GetColumns()方法的代码。 The functionality of GetColumns is to parse a tab-delimietered string and turn it into columns. GetColumns的功能是解析制表符分隔的字符串并将其转换为列。

Any idea? 任何想法?

Those values should be checked but not like you are doing. 应该检查这些值,但不要像您所做的那样。

With NUnit, there is CollectionAssert : 使用NUnit,有CollectionAssert

CollectionAssert.AreEqual(new [] {"a", "b", "c"}, columns);

Must the three lines of code that assert columns (a,b,c) be removed? 必须删除断言列(a,b,c)的三行代码吗?

tl;dr: No tl; dr:

If you want to make sure that "a\\tb\\tc" results in ["a", "b", "c"] and not ["b", "a", "c"], then you should leave them in. The first two lines only check if it's not null and the length, content could be anything. 如果要确保“ a \\ tb \\ tc”的结果为[“ a”,“ b”,“ c”]而不是[“ b”,“ a”,“ c”],则应保留它们in。前两行仅检查它是否不为null,并且长度,内容可以是任何东西。

Please note that there are already code that unit tests the CSV parser's GetColumns() method. 请注意,已经有用于单元测试CSV解析器的GetColumns()方法的代码。

What are those tests? 这些测试是什么? It's hard to tell if they overlap without seeing them. 很难看到它们是否重叠而看不到它们。

It looks as if you are trying to test the CSV.GetColumns(). 似乎您正在尝试测试CSV.GetColumns()。

GetColumns() has three paths GetColumns()具有三个路径

1) textReader.ReadLine() returns null => return null 1)textReader.ReadLine()返回null =>返回null
2) textReader.ReadLine() returns "" => return null 2)textReader.ReadLine()返回“” =>返回null
3) testReader.ReadLine() returns !string.NullOrEmpty() => return the output from the CsvParser. 3)testReader.ReadLine()返回!string.NullOrEmpty()=>返回CsvParser的输出。

Three tests should be that 三个测试应该是

TextReader returns null => result is null TextReader返回null =>结果为null
TextReader returns "" => result is null TextReader返回“” =>结果为空
TestReader returns => result is return value of CsvParser. TestReader返回=>结果是CsvParser的返回值。

The values returned by the CsvParser are not important - as you mention, that the CsvParser does its job properly is tested elsewhere - we just want to say that we return the output of the parser. CsvParser返回的值并不重要-正如您提到的,CsvParser正确执行了其工作已在其他位置进行了测试-我们只想说我们返回了解析器的输出。

public interface ITextReader {
    string ReadLine();
}

public interface ICsvParser {
    string[] GetColumns(string line);
}

public class CSV {
    private readonly ITextReader textReader;
    private readonly ICsvParser csvParser;

    public CSV(ITextReader textReader, ICsvParser csvParser) {
         this.textReader = textReader;
         this.csvParser = csvParser;
    }

    public string[] GetColumns() {                       
        string[] columns = null;
        var line = this.textReader.ReadLine();          

        if (!string.IsNullOrEmpty(line)){
           columns = this.csvParser.GetColumns(line);              
        }

        return columns;
    }

}

[TestClass]
public class CSVFixture {
    private Mock<ITextReader> mockTextReader;
    private Mock<ICsvParser> mockCsvParser;
    private CSV csv;

    private readonly static string [] Columns = new string[]{};

    [TestInitialize]
    public void Setup() {
        mockTextReader = new Mock<ITextReader>();
        mockCsvParser = new Mock<ICsvParser>();
        csv = new CSV(mockTextReader.Object, mockCsvParser.Object);
    }


    [TestMethod]
    public void NullLine() {
        Execute(null);
    }

    [TestMethod]
    public void EmptyLine() {
        Execute("");
    }

    [TestMethod]
    public void PopulatedLine() {
        Execute("SomeLineValue", Columns);
    }

    private void Execute(string line, string[] expected = null) {
        mockTextReader.Setup(mk => mk.ReadLine()).Returns(line);
        mockCsvParser.Setup(mk => mk.GetColumns(line)).Returns(Columns);

        var actual = csv.GetColumns();

        Assert.AreEqual(actual, expected);

    }
}

Other Points: As long as the CsvParser is only invoked from here it is only moving code around but you might change the CsvParser so that if the input is null or empty it returns null. 其他要点:只要仅从此处调用CsvParser,它只会移动代码,但是您可以更改CsvParser,以便在输入为null或为空时返回null。 This means that you do not have to check for it every time you invoke the CsvParser. 这意味着您不必在每次调用CsvParser时都进行检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM