Repetitive unit tests for a programming language
You can make your code less verbose and more expressive at the same time. Now let me explain what I mean. 

Make creating test cases easier without all those new lists and types like this

AssertProgram(new TestData
{
    Sources = { "a", "x" },
    TestCases =
    {
        { "abc", "xbc" },
        { "Hello, World!", "Hello, World!" },               
    }
});


It's at the same time less verbose because there is only one new for TestData and it's easier to understand what all the strings are.

In order for this to work you'll need three helpers with lists that are already instantiated so that you can just use the collection initializer.

class TestData
{
    public List&lt;string&gt; Sources { get; set; } = new List&lt;string&gt;();
    public TestCaseList TestCases { get; set; } = new TestCaseList();
}

class TestCase
{
    public string Input { get; set; }
    public string Output { get; set; }
}

class TestCaseList : List&lt;TestCase&gt;
{
    public void Add(string input, string output) =&gt; Add(new TestCase { Input = input, Output = output });
}


The last class is necessary so that you can add a new Add overload to the list and create your test case easily.



protected void AssertProgram(TestData testData)
{
    var interpreter = new Interpreter(testData.Sources);

    foreach (var testCase in testData.TestCases)
    {
        var actualOutput = new StringWriter();
        interpreter.Execute(testCase.Input, actualOutput);

        Assert.AreEqual(expectedOutput, actualOutput.ToString());
    }
}


If we now rewrite the AssertProgram method to work with the TestData class, it'll be much easier to use the properties than simple strings or repeat the tuple names everywhere.



BTW: you are not using the Output anywhere... yet?