Using TestContext in Unit Tests



Most people don’t know about the TestContext object, as it is not one regularly used. However, it can be very handy.



Data-Driven Unit Testing

The TestContext object’s primary purpose IMO is for linking up a unit test with data rows from a data source. If you haven’t checked out the data-driven unit test feature, take a look here. When it comes time to modify your code to pick up the data rows, you’ll use the TestContext object as documented here.



It is important to create a private instance of the TestContext object in your TestClass.  You’ll also need to create a public property on that field, so the test harness can initialize it for you. If you create unit tests by way of Code Generation, then this object will be added for you automatically. Otherwise you will need to add it manually. That will look something like this (C#):


    private TestContext m_testContext;

    public TestContext TestContext

    {

        get { return m_testContext; }

        set { m_testContext = value; }

    }




When you are ready to write your code, refer to the data through the TestContext object like (C#):


    string firstParameter = m_testContext.DataRow[0].ToString();

    string secondParameter = m_testContext.DataRow[“SecondColumn”].ToString();




Note that you can refer to the column by index (zero-based) or by name.



Finding Files

Another great use for this object is determining where your tests and files have been deployed to. The TestContext.TestDeploymentDir property contains this information. There is also TestContext.TestLogsDir, TestContext.TestDir, and even TestContext.TestName. To see what these equate to, add a new unit test and add the following lines:


    Console.WriteLine("TestDir: {0}", m_testContext.TestDir);

    Console.WriteLine("TestDeploymentDir: {0}", m_testContext.TestDeploymentDir);

    Console.WriteLine("TestLogsDir: {0}", m_testContext.TestLogsDir);

    Console.WriteLine("TestName: {0}", m_testContext.TestName);




Look at the test result details for that test to see the values.


Comments (8)

  1. This is terrible. It tells me nothing other than TestContext exists and I can do magic stuff with it.

  2. Jeremy S says:

    I agree with Brady.  This article at least goes a little further – weblogs.asp.net/…/more-on-unit-testing-testcontext.aspx

  3. phlaz says:

    Whats missing here is that you need to store a static member instance of the TestContext object that you get from a method marked with either AssemblyInitialize or CLassInitialize method like this;

    private TestContext _context;

    [AssemblyInitialize]

    public static void Initialize(TestContext context)

    {

           _context = context;

    }

    [TestMethod, DataSource(etc etc)]

    public void some_test()

    {

          var someValue = Convert.ToString(_context.DataRow["someVarcharColumn]);

    }

    Its amazing that practically every official MS example fails to explain this and hence none of them work. The other problem you run into is that in terms of Data Driven tests, only test classes with a methodmarked with AssemblyInitialize will be able to retrieve that data through the DataRow property. When you use ClassInitialize DatRow is always null. So as it stands you can only bind data to one test class in any test assembly.

  4. Darryl says:

    phlaz, the reason they don't include that is because you are WRONG.  It is not necessary.  If you define the TestContext property as demonstrated in this post, it will work.   NO additional code is necessary.

  5. Darryl says:

    Wow, the more I read your comment, the more wrong I see it is.  Since people are likely to stumble upon this blog post as they try to get a handle on data-driven tests, I think it's important to correct the misinformation you've put here.  Otherwise they'll be thrown off completely.

    "Its amazing that practically every official MS example fails to explain this and hence none of them work."

    Your code is not necessary, and the examples DO work as written.  What is necessary is a TestContext property defined as the example here shows.  That is the key to gaining access to the TestContext, not the method you propose.

    "The other problem you run into is that in terms of Data Driven tests, only test classes with a methodmarked with AssemblyInitialize will be able to retrieve that data through the DataRow property."

    Wrong again.  This is simply not true.  Data driven tests work even if you don't have a method marked with an AssemblyInitialize attribute.

    "When you use ClassInitialize DataRow is always null. So as it stands you can only bind data to one test class in any test assembly."

    Wrong yet again.  You can (and usually do) have multiple classes in a test assembly, each of which may have data-driven tests.

    Bottom line is you're doing it wrong.  The limitations you describe are only there because you aren't following the guidance given in the examples.

  6. Darryl is wrong says:

    Hi Darryl,

    You're wrong. The example didn't work as written. Without the method decorated with AssemblyInitialize, the TestContext property is never set.

    Wrong wrong wrong.

  7. CreeTar says:

    lol C# is so bullshit, check out TestContext of TestNG in Java, that's something useful, this C# TestContext is a load of crap

  8. Ed Fandangle says:

    Make sure the "TestContext" property that you create is "Public", then you'll find that it will work. The same goes for the TestInitialize and TestCleanup methods.

Skip to main content