Referencing MSTest And MSTestv2 Unit Testing Framework Through Namespace Aliasing

Let me start-off by explaining what MSTest and MSTestV2 are.

MSTest (Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll) – This is the unit testing framework that comes pre-installed when you install Visual Studio IDE (Available through the .Net Framework – GAC)

MStestV2 (Microsoft.VisualStudio.TestPlatform.TestFramework.dll) – This is now the open source version of MSTest. With any open source libraries, there are lots of good contributions but also features do change more frequent. More often, removed (or enhanced in this case). You install this version of MSTest through Nuget.

With that brief description on MSTest and MSTestV2, now comes the question: Why would I reference both MSTest and MSTestV2 in the same test project? Well, there are two reasons; Backwards compatibility and issues exposed in MSTestV2 that is still being worked on.

In terms of backwards compatibility, I work with many developers around utilizing data driven features in MSTest. The good back then is that we can data drive tests using many data source providers (e.g. Excel, SQL, etc…). The bad part is that the open source framework (MSTestV2) only supports both XML and CSV as the data source providers (Though, it supports DataRow as a data source which is good).

Ideally, I would ask the developers to migrate directly to MSTestV2 but in this case, I’d like for them to regress any issues they find in MSTest and see what else could break in MSTestV2.

The issue: Referencing both dlls causes collisions and/or conflicts simply because most of the attributes (or All- [TestClass],[TestMethod],etc…) uses the exact same namespace:

Microsoft.VisualStudio.TestTools.UnitTesting

The Solution! Welcome back namespace aliasing. The last time I used namespace aliasing, oh, I can’t remember exactly but probably late 2006 (C# 2.0)

With namespace aliases, you can reference multiple assemblies even if those assemblies have the exact same namespace

Step 1: Provide an alias name at the assembly level.

Go to the properties of each assembly and provide an alias.

MSTest1

Step 2: In code, refer to the assembly alias using the C# reserved keywordextern

extern alias FrameworkV1;
extern alias FrameworkV2;

using System;
using TestFrameworkV1 = FrameworkV1.Microsoft.VisualStudio.TestTools.UnitTesting;
using TestFrameworkV2 = FrameworkV2.Microsoft.VisualStudio.TestTools.UnitTesting;

Step 3: Refer to the appropriate assembly classes and/or attributes through the namespace alias (variable you created through the “using” statement)

MSTest2

And the result

MSTest3

MSTEST TIP: Extension Method/s for TestContext while working on Data Driven Tests.

A very common scenario that developers/testers encounter when writing data driven tests is to print input parameters from data sources. Data driven test can encompass many data sources (sql, .csv, excel, .xml, etc…) and Yes, I was even able to extend MSTests functionality by passing my own custom collection:

MSTEST: EXTENDING DATA DRIVEN TESTS TO USE IENUMERABLE<OBJECT> AS THE DATA SOURCE

https://dondeetan.com/2016/02/18/mstest-extending-data-driven-tests-to-use-ienumerableobject-as-the-data-source/

While there are many implementations to solve this, I wanted to provide (in my opinion) the most easiest and efficient way possible for developers and testers to print out input parameters without leaving the context during test development. Thus, extension methods. What are extension methods? In a high level, extension methods allows you to “extend” or “add” methods to existing types (even types built in the .Net framework) without creating a new class from the derived type. Click here on Extension Methods (C# Programming Guide) more information.

Now that we have good understanding of extension methods, then why not extend the TestContext class which contains all information during test execution? TestContext also contains information around the datarow and datacolumn passed during data driven testing. It’s a simple as calling the datarow during runtime.

TestContext.DataRow["Description"].ToString();

TestConext.DataRow has a property “Table” which you can get all columns during the instance of test execution. At this point, all you need to do is extend TestContext to print input parameters.

public static class Helper
    {
        public static void PrintInput(this TestContext testContext)
        {
            Console.WriteLine($"Total Input Fields: {testContext.DataRow.Table.Columns.Count}");
            var columns = testContext.DataRow.Table.Columns;
            for (var i = 0; i < columns.Count; i++)
            {
                Console.WriteLine($"Field: {columns[i].ColumnName} Value: {testContext.DataRow[i]}");
            }
        }
    }

In your Test Method, all you have to do is just call one line of code:

TestContext.PrintInput();

And the results from that instance test execution:

image

Great way to show input parameters for debugging purposes!