Up Code sample: Hello DevForce (WPF)
DevForce Resource Center » Samples » Core concept code samples » Code sample: Hello DevForce (WPF) » Code sample: Hello, DevForce Addendum: Adding a Test Project (WPF)

Code sample: Hello, DevForce Addendum: Adding a Test Project (WPF)

Last modified on September 20, 2012 10:31

Adherents for a “Test First!” methodology make a strong case for the importance of writing unit tests as an integral part of your application development process – and one should be commenced early in the development cycle. Let’s see how to lay the foundation for integrated, ongoing, automated testing and test development.

You’ll need Team Test to reproduce the steps detailed in this chapter.

Do you have Team Test? Look for “Test” among the Visual Studio menus. If it’s there, you’ve got Team Test; if it isn’t, you don’t.

If you don’t wish to purchase an edition of Visual Studio that has Team Test, you might consider NUnit. It’s solid and it’s free. While it won’t generate the template tests (we’ll see Team Test do that shortly), you’ll otherwise find the experience of using it remarkably similar to testing with Team Test.


Problem

You know you need to write unit tests for your application, but you don't know where to start.

Solution

Here we'll walk through how to add a test project to your solution and write some simple tests.

Unit testing with Visual Studio Team Test

It’s easy to get started with the new Visual Studio Team Test.

  1. Open MainWindowViewModel.cs (or .vb) in code view, and right-click in the Code View window.
  2. Pick “Create Unit Tests …”

output_html_39400653.png

The “Create Unit Tests” Dialog appears. Uncheck all methods except the MainWindowViewModel constructor:

output_html_m3eea548e.png

  1. For “Output Project”, accept “Create a new Visual C# [or VB] Test Project”... Click [Ok].
  2. Enter “Test” as the project name, and click <Create>.

output_html_m121a219f.png

After some grinding in the background, you will see the Test project added to the solution, with references to the DomainModel and the necessary IdeaBlade assemblies. You will also see a new MainWindowViewModelTest.cs (or .vbtab:

output_html_m4b47377e.png

Configuring the test project

We need to make a couple of configuration changes to ready our test project for use.

  1. Make sure the following using [C#] or Imports [VB] statements at the top of the MainWindowViewModelTest.cs (or .vb) file:
C#
using WpfApplication1;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using IdeaBlade.Core;
using IdeaBlade.EntityModel;
using DomainModel;
VB
Imports WpfApplication1
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports IdeaBlade.Core
Imports IdeaBlade.EntityModel
Imports DomainModel
  1. Build or rebuild the entire solution.
  2. Set LocalTestRun.testrunconfig to deploy the app.config to the test output directory. You can do this as follows:
    1. On the Visual Studio Test menu, select Edit Test Settings and then Local(local.testsettings).
      output_html_71b12de7.png
    2. On the Test Settings dialog, select the Deployment panel.
    3. Click the Enable deployment CheckBox to set its value to true.
    4. Click <Add File...>. Change the Objects of type select to “All files(*.*)”, and find the App.config file in the folder for the solution’s executable project (WpfApplication1). Select it, and click the <Open> button. The Test Settings dialog should then appear as follows:
      output_html_m7d5a4651.png
    5. On the Test Settings dialog, click <Close> and respond Yes when prompted whether to save changes to the test settings.

Running tests

Your test environment is configured, and you’re ready to run a test.

  1. Select Test on the Visual Studio main menu, then Windows / Test View.

output_html_4a1215ba.png

This will open a tab in the group of tabbed panels at the right of the Visual Studio development environment. Find the test named “MainWindowViewModelConstructorTest”. Right-click it, select Run Selection, and note the results shown below:

output_html_41f9a2d2.png

This corresponds to the following test method which was generated automatically into the MainWindowViewModelTest class:

C#
/// <summary>
///A test for MainWindowViewModel Constructor
///</summary>
[TestMethod()]
public void MainWindowViewModelConstructorTest() {
  MainWindowViewModel target = new MainWindowViewModel();
  Assert.Inconclusive("TODO: Implement code to verify target");
}
VB
''' <summary>
'''A test for MainWindowViewModel Constructor
'''</summary>
<TestMethod()> _
Public Sub MainWindowViewModelConstructorTest()
 Dim target As New MainWindowViewModel()
  Assert.Inconclusive("TODO: Implement code to verify target")
End Sub

The test method does indeed construct an instance of MainWindowViewModel, but the Assert call that produces test results doesn’t yet do anything meaningful. Since the MainWindowViewModel’s constructor doesn’t do anything except the bare minimum, about all we can verify is the value of the target variable isn’t null. We can change our Assert statement as follows:

C#
Assert.IsTrue(target | null, "Unable to construct MainWindowViewModel");
VB
Assert.IsTrue(target Or Nothing, "Unable to construct MainWindowViewModel")
}

The second parameter to the Assert.IsTrue() true is the Error Message that would display in the Test Results panel if the test were ever to fail. Of course, there’s not much likelihood of that, so let’s write a more useful test.

  1. Copy the code for MainWindowViewModelConstructorTest() method and paste the copy just below it. Modify it so it appears as follows:
C#
///A test for the Customer query used in
///MainWindowViewModel.FirstSample()
///</summary>
[TestMethod()]
public void CustomerQueryTest() {
  NorthwindIBEntityManager mgr =
    NorthwindIBEntityManager.DefaultManager;
  var customersQuery =
    from cust in mgr.Customers
    where cust.ContactTitle == "Sales Representative"
    orderby cust.CompanyName
    select cust;
  Assert.IsTrue(customersQuery.Count() > 0,
   "Customer query returned no Customers");
}
VB
'''A test for the Customer query used in
'''MainWindowViewModel.FirstSample()
'''</summary>
<TestMethod()> _
Public Sub CustomerQueryTest()
 Dim mgr As NorthwindIBEntityManager = _
    NorthwindIBEntityManager.DefaultManager
 Dim customersQuery = From cust In mgr.Customers
                       Where cust.ContactTitle = _
                        "Sales Representative"
                       Order By cust.CompanyName
                      Select cust
  Assert.IsTrue(customersQuery.Count() > 0, _
   "Customer query returned no Customers")
End Sub

This new test method tests the query used in the FirstSample() method in the MainWindowViewModel. At this point it might be a good idea to refactor FirstSample() to separate the code that defines this query, so that our test method would be guaranteed to test exactly the same query used by FirstSample(). But we’ll leave that as an exercise for you.

  1. Save your changes to MainWindowViewModelTest.cs, refresh the Test View panel, and run the new test method, again by right-clicking it and choosing Run Selection. It should pass:

output_html_m1b501256.png

Examining test failures

Suppose your test did not pass. There are two reasons a test will fail:

  • An Assert statement fails
  • The code throws an exception.

If an Assert statement fails, then in the Error Message column of the Test Results you’ll see the message you encoded into the call -- e.g., “Customer query returned no Customers” in our Assert.IsTrue() call.

If the test failed because an exception was thrown, you see a generalized message about the test failing. To get more information, you can right-click on that message and select View Test Result Details, as shown here.

output_html_34f8d750.png

Below, as an example, is the error you get if the connection string that the Test engine found in the supplied config file was bad:

output_html_6eb6d6e3.png

Maintaining test data

When designing tests you’ll want to be careful to keep the test data always in a known state. If your test code makes changes, you’ll probably need some process to restore the original data. You should have a back up of the database just in case.

One of the cardinal testing rules is that there should be no dependencies among the tests. That means that tests can be run independently and in any order. Accordingly, if you make changes during a test, you must restore the original data immediately after the test. You must make sure we do so even if the test fails.

Do restore the test data source after every test

Do maintain a back up of the database just in case.

Running in debug mode

We launched the tests we’ve run herein using Run Selection. You can also start a test using Debug Selection:

output_html_20dd9042.png

Starting your test with Debug Selection will cause any breakpoints you place in the test code to be respected. That can be very helpful while writing a test to help you decide exactly what to compare in your Assert statements, and later to see why a particular test is failing.

Accumulating test results

Team Test keeps track of every test run. You can review them from within the “Test Results” window shown immediately above.

output_html_5143fcd4.png

When you examine your solution directory in Windows Explorer, you will find the TestResults directory where these results are stored. You don’t want this directory under source control and you definitely want to clear it out periodically. Prune or delete at your leisure.

Created by DevForce on June 18, 2010 13:34

This wiki is licensed under a Creative Commons 2.0 license. XWiki Enterprise 3.2 - Documentation. Copyright © 2015 IdeaBlade