TL;DR: Just here for the tool? Alright, find it here.
MSTest has come a long way. The current version, collegially called “V2”, is much more flexible then the original version that shipped back in the day with Visual Studio 2005.
MSTest consists of the execution engine/runner, typically manifested as vstest.console.exe
(and sometimes referred to as “VSTest”) and the actual test framework, containing typical
types like Assert
.
The test runner can also execute test cases using different frameworks, provided an adapter exists. For example, for NUnit, XUnit, and custom ones are also possible. In one of the projects I’ve been on, we have developed a custom adapter that can integrate a total custom test runner (for database tests using SSIS) into the Visual Studio and TFS using an adapter.
One could ask why a migration from NUnit to MSTest V2 is actually useful, when there is an adapter in place that allows to run NUnit Tests directly using VSTest? Well, the reasons basically are (and I’m aware that at least some these may be eliminated in the future):
Reduction of complexity: less NuGet packages required, less components. Less things to check when things don’t work as expected.
Direct support of features provided by MSTest but maybe not by others. And on the flip-side, obvious non-support of features supported by other frameworks but not by MSTest/VSTest. For example, NUnit, XUnit, etc. provide stuff that MSTest doesn’t.
Now as said, some of such issues may decay over time. Others, as is in the nature of “competing” concepts/products, may never be fully supported - if even technically possible.
That doesn’t say anything negative about either test framework, but can be a hindrance in productive use in a larger teams. Consider developers might create unit tests locally (using a native test runner of said frameworks) and all is well; other developers using VSTest (or TFS builds for that matter) may then choke on such features not or not properly supported by the respective adapter. (As an example see Issues #319, #438 or #47).
MSTest V2 is developed in the open, as are many newer Microsoft development products. One can see and participate on GitHub for the execution engine and the framework.
Being a liberal MIT-license, this has all the benefits one would expect from an open source software.
Now of course staying with your existing test framework (NUnit, for example) is an option one can always take. However, if you consider to move to MSTest it must be MSTest V2 and not the older “V1” version that shipped with Visual Studio 2005. MSTest V2 is actively being worked on and is also the version used when you create a new project using the UnitTest project template in Visual Studio 2017 and above.
If you want to change I would suggest the following rough plan layed out in the following chapters.
Oh, one more thing. The next chapters describe what was done in a large-ish project with about 20 test assemblies and some couple thousand test cases. If you only have one test assembly with just a couple of tests (do you?), then you can get along with a much less structured approach, just edit-build-edit-build, etc. your way through.
MSTest.TestFramework
and MSTest.TestAdapter
)TestFixture
-> TestClass
SetUp
, TearDown
-> TestInitialize
, TestCleanup
Test
-> TestMethod
Category
-> TestCategory
TestCase
-> DataRow
+ DataTestMethod
OneTimeSetUp
, OneTimeTearDown
-> ClassInitialize
, ClassCleanup
public static void
ClassInitialize
must have one parameter of type TestContext
Property
-> TestProperty
System.String
.Explicit
: has no direct counterpart in MSTest. Alternatively, use Ignore
,
Priority
or TestCategory
and filtering during execution to skip tests.Combinatorial
and Range
: again, no direct counterpart in MSTest (altough
see the note about extending MSTest below). You could expand such things to
single DataRow
attributes.Culture
: Manually set and reset Thread.Current(UI)Culture
.TestClass
has no
Description
as TestClass
had.You can also extend and customize MSTest V2 to add features that may be lost by changing from NUnit. I consider these advanced concepts and don’t discuss them here further. Please refer to the linked articles for more information. Also, arguably, if you create a standard 4-phase-test you probably don’t need much extensions.
using NUnit.Framework
with using Microsoft.VisualStudio.TestTools.UnitTesting
will make lots of stuff simply work.
Assert.AreEqual
.Assert.That(value, Is.Null)
-> Assert.IsNull(value)
Assert.That(expr, Throws.TypeOf<Ex>())
-> Assert.ThrowsException<Ex>(expr)
Assert.That(expr, Throws.TypeOf<Ex>().With.Message.Contains(str))
-> StringAssert.Contains(Assert.ThrowsException<Ex>(expr).Message, str)
Assert.True
-> Assert.IsTrue
,
Assert.NotNull
-> Assert.IsNotNull
, etc.Assert.IsInstanceOf(Type, value)
->
Assert.IsInstanceOfType(value, Type)
.So, in general MSTest has a lot less Assert API surface than NUnit. This however is not the worst thing (neglecting potential migration effort), because it forces you to write “simpler” tests. However, you could still extend MSTest, creating your own asserts.
Yes, it can. Generally, at least. Most of the tasks explained in the previous chapter could of course be handled by a tool.
The first tool of choice would be a simple search and replace using your text editor’s capabilities.
This would work nicely for the easier things like simple attribute and assert method replacement,
but fails for the even slightly more complex things like Assert.That(value, Is.Null)
-> Assert.IsNull(value)
.
No, regular expressions are not the solution - although they might get you little further. Note that
your actual code might not be written as “nicely” as in Assert.That(value, Is.Null)
, more likely it
is something like this:
Assert.That(
myObject.mamboJumbo.GetValue(499, 399),
Is.Null
)
Of course still doable with regex, but it gets nastier by the example. And remember, the result of tool supported migration should not be a half broken codebase.
The technically I thus settled on was Roslyn - i.e. the C# compiler itself. If you have never heard of that, Roslyn I mean, please check this and maybe this and go from there, to get some background information. In short, using Roslyn one can parse C# source code, create an AST from it, manipulate it, and save the results.
You can find the source code for the NUnitToMSTest tool here, along with some instructions how it works (it is a Visual Studio extension that you can invoke via right click on a project) and what it can do and what not.