3

I'm having a problem with the classinitilalize method of a unit test being executed after the evaluation of the attributes on a unit test. These tests use a [classinitialize] method to generate a test set that makes a random set of data in an xml file. The xml file is consumed by a unit test with the attribute [datasource]. A trimmed down version of this looks like this:

[ClassInitialize]
public static void Initialize(TestContext context)
{
    // Create xml output file
    var output = new XDocument(new XElement("Rows"));

    foreach (var Code in Codes)
    {
        if (output.Root != null) 
            output.Root.Add(new XElement("Row", new XElement("Code", Code)));
    }
    output.Save("TestData.xml");
}

[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
"|DataDirectory|\\TestData.xml",
"Row",
DataAccessMethod.Sequential)]
[TestMethod]
public void TestStuff()
{
    var Code = (string)TestContext.DataRow["Code"];
    TestItem(Code);
}

I'm working with Visual Studio 2012 Update 3. I have used the Sysinternals tool Process Monitor to verify the order of execution. I set a break point at the beginning of each method. I then stepped through and watched the file access. The order of operations I saw.

  1. TestData.xml read by vstestexecutionengine.
  2. ClassInitialize Method is called and writes TestData.xml
  3. TestMethod is executed, using data read in step 1. (I added a file with bogus data to test)

So my question is, what am I doing wrong that classinitialize is not executing before the xml file is read? Or is what I am trying to do impossible?

Cameron Vetter
  • 782
  • 4
  • 17
  • I'm not sure, but why not just add static xml files as resources to your test project? It makes the tests more trustworthy, imho. You have known inputs and expected outputs. – Randy James Aug 13 '13 at 20:09
  • This is a good point, the logic behind selecting a random subset is that each of these rows is fairly long running, and doing the entire set requires over an hour to complete this test. – Cameron Vetter Aug 16 '13 at 23:43
  • 1
    I do it all the time. And it's handy because when you change the schema, you can keep the old structure and add the new one, then add tests for what your expect to happen when you encounter either. e.g. Handle old versions, or throw a specific error, or migrate to new format, or whatever. – Randy James Aug 18 '13 at 14:14

1 Answers1

-1

MSTestHacks might be a possible workaround for you.

It allows an IEnumerable on your test class to be used as the DataSource for your TestMethod. You can return what you have as Codes in this property.

From the website:

Runtime data source: your test class MUST inherit from TestBase:

[TestClass]
public class UnitTest1 : TestBase
{ }

Create a property, field or method that returns an IEnumerable

[TestClass]
public class UnitTest1 : TestBase
{
    private IEnumerable<int> Stuff
    {
        get
        {
            //This could do anything, fetch a dynamic list from anywhere....
            return new List<int> { 1, 2, 3 };
        }
    }
}

Add the DataSource attribute to your test method, pointing back to the IEnumerable name created earlier. This needs to be fully qualified.

[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
    var number = this.TestContext.GetRuntimeDataSourceObject<int>();

    Assert.IsNotNull(number);
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jon
  • 2,389
  • 2
  • 20
  • 35