对方法的每个输出进行单独的单元测试

Aae*_*Aae 3 c# unit-testing mstest xunit xunit.net

我有一个方法将文件作为输入,然后根据此文件返回N个输出。

我想通过以下方式测试此方法:假设我们有M个文件要测试。对于每个文件,我想向测试程序(或单独的文件)添加一行,该行由文件路径和N个预期输出组成。此数据应产生N * M个单独的测试,每对文件和预期输出一个。

是否有实现此目标的好方法?我希望每个测试运行最多解析一次每个文件。

以下是执行我想要的示例。如您所见,我必须为每个文件添加单独的测试类。我希望找到一个解决方案,在其中我可以仅添加带有测试数据的行(例如testData.Add(("thirdfile", 4), (348, 312));)来测试新文件。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    public static class FileParser
    {
        private static int n = 0;

        public static void Init(int parameter)
        {
            n = parameter;
        }

        public static (int output1, int output2) ParseFile(string filename)
        {
            return (filename[0] * n, filename[1] * n);
        }
    }

    public class Tests
    {
        private Dictionary<(string, int), (int, int)> testData;

        public Tests()
        {
            testData = new Dictionary<(string, int), (int, int)>();
            testData.Add(("somefile", 3), (345, 333));
            testData.Add(("anotherfile", 4), (291, 330));
            testData.Add(("thirdfile", 4), (348, 312));
        }

        public void TestOutput1((int, int) result, string filename, int parameter)
        {
            Assert.AreEqual(testData[(filename, parameter)].Item1, result.Item1);
        }

        public void TestOutput2((int, int) result, string filename, int parameter)
        {
            Assert.AreEqual(testData[(filename, parameter)].Item2, result.Item2);
        }
    }

    [TestClass]
    public class Somefile
    {
        protected static (int, int) fileParseResult;

        [ClassInitialize]
        public static void ClassInit(TestContext context)
        {
            FileParser.Init(3);
            fileParseResult = FileParser.ParseFile("somefile");
        }

        [TestMethod]
        public void SomefileOutput1() { var tests = new Tests(); tests.TestOutput1(fileParseResult, "somefile", 3); }
        [TestMethod]
        public void SomefileOutput2() { var tests = new Tests(); tests.TestOutput2(fileParseResult, "somefile", 3); }
    }

    [TestClass]
    public class Anotherfile
    {
        protected static (int, int) fileParseResult;

        [ClassInitialize]
        public static void ClassInit(TestContext context)
        {
            FileParser.Init(3);
            fileParseResult = FileParser.ParseFile("anotherfile");
        }

        [TestMethod]
        public void AnotherfileOutput1() { var tests = new Tests(); tests.TestOutput1(fileParseResult, "anotherfile", 4); }
        [TestMethod]
        public void AnotherfileOutput2() { var tests = new Tests(); tests.TestOutput2(fileParseResult, "anotherfile", 4); }
    }

    [TestClass]
    public class Thirdfile
    {
        protected static (int, int) fileParseResult;

        [ClassInitialize]
        public static void ClassInit(TestContext context)
        {
            FileParser.Init(3);
            fileParseResult = FileParser.ParseFile("thirdfile");
        }

        [TestMethod]
        public void ThirdfileOutput1() { var tests = new Tests(); tests.TestOutput1(fileParseResult, "thirdfile", 4); }
        [TestMethod]
        public void ThirdfileOutput2() { var tests = new Tests(); tests.TestOutput2(fileParseResult, "thirdfile", 4); }
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 6

您实际上可以简化此操作,以便对该库进行新测试不一定需要对测试库本身进行代码更改。

可以在此处找到有关数据驱动的单元测试的MS文档。

我见过人们在csv文件中使用类似的东西,然后当需要新的测试时,他们只是在csv文件中添加一行。

另外,我个人喜欢MSTest中提供的DataRow功能。示例MS Doc可以在这里找到。我喜欢这个选项,尽管新的测试用例确实需要换行代码。

它应该减少总体代码量。有点像这样。

[TestClass]
public class FileClass
{
    [TestMethod]
    [DataRow("somefile", 3, 345, 333)]
    [DataRow("anotherfile", 4, 291, 330)]
    public void Output1IsValid(string fileName, int parameter, int resultX, int resultY) 
    { 
        var fileParseResult = FileParser.ParseFile(fileName);
        Assert.AreEqual(fileParseResult.Item1, resultX);         
    }

}
Run Code Online (Sandbox Code Playgroud)