XUnit, like a lot of other testing frameworks, allows for creating test cases, or theories in XUnit terms, based on test data rather than static tests alone. With the CodeConverter.NET tests, I decided to generate the test cases based on input files and output files. The input files contain C# code and the output files contain PowerShell script. Each test is evaluated the same way; a C# file is passed through the conversion classes and a PowerShell script is outputted. The expected and actual scripts are compared as the assertion for each test.

Create a data driven test

Data drive tests can be developed in XUnit using the TheoryAttribute alongside the MemberDataAttribute. The MemberDataAttribute allows you to specify the data you wish to provide for each test case based on a static property of one of your classes. The static property needs to return an IEnumerable of object arrays. Each object array in the list corresponds to an argument for your Theory method.

private static readonly List<object[]> _data;
public static IEnumerable<object[]> TestData
     get { return _data; }

In my case, my theory takes a single object of type ConversionTestCase.

[MemberData("TestData", MemberType = typeof(TestCases))]
public void TestLanguages(ConversionTestCase testCase)

I add each of these test cases to the TestData collection and then XUnit creates a new test case for each item.

foreach(var testCase in Cases)
      _data.Add(new[] { new ConversionTestCase(testCase.Item1, testCase.Item2, syntaxTreeVisitor, codeWriter, testCase.Item3) });

Displaying Test Cases Correctly in Visual Studio

The above process works great for creating individual test cases from the test data but they won’t show up correctly in the Test Explorer window. You’ll see one test rather than a test for each case. To work around this, you need to implement the IXunitSerializable interface.

In my case, I serialized the ConversionTestCase.

public void Deserialize(IXunitSerializationInfo info)
   Name = info.GetValue<string>(nameof(Name));
   Description = info.GetValue<string>(nameof(Description));
   var type = Type.GetType(info.GetValue<string>(nameof(SyntaxTreeVisitor)));
   SyntaxTreeVisitor = Activator.CreateInstance(type) as ISyntaxTreeVisitor;
   type = Type.GetType(info.GetValue<string>(nameof(CodeWriter)));
   CodeWriter = Activator.CreateInstance(type) as CodeWriter;
   OutputToMarkdown = bool.Parse(info.GetValue<string>(nameof(OutputToMarkdown)));

public void Serialize(IXunitSerializationInfo info)
   info.AddValue(nameof(Name), Name);
   info.AddValue(nameof(Description), Description);
   info.AddValue(nameof(SyntaxTreeVisitor), SyntaxTreeVisitor.GetType().AssemblyQualifiedName);
   info.AddValue(nameof(CodeWriter), CodeWriter.GetType().AssemblyQualifiedName);
   info.AddValue(nameof(OutputToMarkdown), OutputToMarkdown.ToString());

This step isn’t necessary if you are only passing standard types into your test case methods. If you want to pass complex types into your test case method, you can take this approach. The result of this is a beautiful Test Explorer window with my dynamically generated set of test cases.

You can view the full implementation on the CodeConverter.NET SDK GitHub repository.