Unit Testing in VS 2013

Visual Studio 2013 now contains functionality to write tests against a Windows Store project. Now, it is a relatively simple task to write unit tests against the code you have in classes within your app’s structure.

A Basic Example

Launch Visual Studio, and from the new project dialog, select Templates -> Visual C# -> Windows Store, and create a new “Blank App (XAML)” named “AppToTest”. Make sure you change the Solution Name value to be “TestableStoreAppExample”

01-NewProjectDialog

Within the project, create a new folder named “DataAcccess”, and within that a new class named “SampleDataAccess.cs”

Open your newly created class, and mark it as public.

Now we want to add some methods to the class. These will be the methods against which our tests will run, so we will just create some dummy ones for now.

As you can see, the content of the class is very basic at this stage. We will build on this later.

Build the project to ensure that there are no errors.

Next, Let’s add a unit test project.

Right click on the solution in Solution explorer, and click on “Add -> New Project”. In the dialog, select “Unit Test Library (Windows Store Apps”, and name the test project “AppTests”.

In the unit test project you just created, right click on References and select “Add Reference”. In the dialog that appears, navigate to “Solution” on the left hand side, and select “AppToTest on the right, then press OK.

02 - AddReference

Now we can write some tests. For now, I’m just going to add these tests into the default class created when the project was initialised.

Open the file “UnitTest1.cs”

There are couple of annotations to note in this class, but these should be familiar to you if you have used MSTest before.

[TestClass] Marks the class as being a test fixture, containing unit test code.
[TestMethod] Marks a method as being a Unit Test.

For our first test, I’ll re-use the code already in the class. First of all, let’s change the name of TestMethod1 to something more descriptive. Since this test will call the GetSumOfInts method we defined earlier, lets call it TestIntegerSummation().

To break that down, first I create a new instance of the SampleDataAccess class, and call the GetSumOfInts method with 1 and 2, hopefully giving a result of 3. The final lines is where the test comparison happens. In this case, I’m calling Assert.AreEqual to test that the expected value of 3 matches the actual returned value. There are a few other Assert. methods available, e.g. Assert.AreNotEqual, Assert.IsTrue, etc.

Now build the solution in order to make the test available to the test engine.

To run the method, my preferred method is to open the Test menu in Visual Studio, and select Windows -> Test Explorer.

3-UnitTestManager

From here you can run all tests, or right click on a test name to run individual ones. (Note, theres another feature that you might want to take advantage of – automatically run tests when you build the solution. To do this, go to Test -> Test Settings and select “Run Tests After Build)

The screenshot above shows that the test we wrote passes.

OK, that’s a synchronous method. What about async ones?

Testing async Methods

This isn’t as intuitive as you might imagine, but once you know the trick, it’s very simple.

As you saw when we created the class to test, I created an async method that goes off and pulls text from a web resource. This is an async call due to the potential delays in loading a web resource.

To create a test for this, we first need to define a new method in the test class and decorate it with the [TestMethod] attribute, then write the code we want to call in the method.

If we do this with the same signature as before, however, the test won’t appear in the test explorer. There are two things we need to do to make the test runnable.

1) Add the async keyword to the method signature (to allow the use of the await keyword in the method call)

2) Change the return type of the test method from void to Task (in the System.Threading.Tasks namespace)

Our method should now look like this.

The test now shows up in Test Explorer and you can run it just like any other method.

More Complex tests

Another great way to test methods is by the use of the [DataTestMethod] attribute. This attribute allows you to specify many sets of data to run in the test, without the need to refactor a test to support different values.

Let’s take our TestIntegerSummation() test and refactor that to support different data sets.

Make a copy of the method, and call it TestIntegerSummationWithData, and add three integer parameters to the signature, calling them “input1”, “input2” and “expectedResult”.

Next we need to update the method body to use these values. The result should look like this.

Change the Attribute from [TestMethod] to [DataTestMethod].

To add sets of data against which we want the tests to run, we can add additional attributes, in this case, the [DataRow()] attribute.

Each DataRow attribute allows you to specify values to be used within the method (in the order they are defined in the method signature). The data we want to pass in should be a reasonable set of data that can be used to test various conditions, but for the purposes of this post, we’ll just pick some random values and test those.

You can see that there are likely to be some edge cases where the calculation will not return the expected result, for example, if we set input1 to be Int.MaxValue. In that case, running the test will show the following in Test Explorer – you can see it gives individual results for each DataRow defined.

4-TestRunResults

There are a couple of ways to handle this situation. We can simple extend the method signature and data rows to pass in a value of whether we expect the test to pass or not

But this isn’t an ideal situation, especially if we expect an exception.

I’ll talk about better ways to handle this in the next post.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">