Walkthrough: Creating and Running Unit Tests

This walkthrough will step you through creating, running, and customizing a series of tests using Microsoft Visual Studio 2010. You start with a C# project that is under development, create tests that exercise its code, run the tests, and examine the results. Then you can change your project code and re-run the tests.

Note

For information about how to run tests from a command line, see Walkthrough: Using the Command-line Test Utility.

In this walkthrough, you will complete the following tasks:

  • Prepare a "Bank Account" project to use in a walkthrough.

  • Open an existing project.

  • Create unit tests for public and private methods.

  • Run those tests on the code.

  • Find and correct errors in tests.

  • Find and correct errors in the code.

Prerequisites

Prepare the Walkthrough

To prepare the walkthrough

  1. Open Visual Studio 2010 Premium.

  2. On the File menu, point to New and then click Project.

    The New Project dialog box appears.

  3. Under Installed Templates, click Visual C#.

  4. In the list of application types, click Class Library.

  5. In the Name box, type Bank and then click OK.

    Note

    If the name "Bank" is already used, choose another name for the project.

    The new Bank project is created and displayed in Solution Explorer with the Class1.cs file open in the Code Editor.

    Note

    If the Class1.cs file is not open in the Code Editor, double-click the file Class1.cs in Solution Explorer to open it.

  6. Copy the source code from the Sample Project for Creating Unit Tests.

  7. Replace the original contents of Class1.cs with the code from the Sample Project for Creating Unit Tests.

  8. On the Build menu, click Build Solution.

You now have a project named Bank. It contains source code to test and tools to test it with. The namespace for Bank, BankAccountNS, contains the public class BankAccount, whose methods you will test in the following procedures.

Create a Unit Test

Prerequisite: Follow the steps in the procedure, Prepare the Walkthrough.

To create a unit test

  1. If the Class1.cs file is not open in the Code Editor, in Solution Explorer, double-click the Class1.cs file in the Bank project.

  2. In the BankAccount class in the Class1.cs file, scroll to the Debit() method.

  3. Right-click the Debit() method and select Create Unit Tests.

    The Create Unit Tests dialog box is displayed.

    Under Current selection, a tree structure shows the class and member hierarchy of the assembly that houses the BankAccount class. You can use this page to generate unit tests for any selection of those members, and to choose a test project into which you want the generated unit tests to be placed.

    In the tree structure, only the Debit() method is selected. Leave it selected and also select the Credit() method.

  4. For Output project, select Create a new Visual C# test project.

  5. Click Settings.

    The Test Generation Settings dialog box appears. Under Naming settings, you can change the way test files, test classes, and test methods are named as they are generated. Under General, you can change other aspects of test generation. Leave the default values for these settings and then click OK.

  6. In the Create Unit Tests dialog box, click OK.

    The New Test Project dialog box is displayed.

  7. Accept the default name and then click Create.

    This creates a project named TestProject1, which is displayed in Solution Explorer.

    A file named BankAccountTest.cs, which contains a test class is added to TestProject1. The class is populated with a TestContext property and with methods to test the Debit() and Credit() methods.

    Note

    Every test method is automatically assigned the TestMethod() attribute. Each test corresponds to a single method in the code under test that you want to test. Test methods are housed in a test class that is assigned the TestClass() attribute.

  8. In BankAccountTest.cs, specify values for the variables to be tested. Scroll to the DebitTest method, where you see // TODO lines that indicate variables to set.

  9. To know which values to use for the DebitTest method, open the Class1.cs file and scroll to the Main method. Notice that the customer name is initialized to Mr. Bryan Walton, the account balance is initialized to 11.99, the Credit method is called with a parameter of 5.77, and the Debit method is called with a parameter of 11.22. Therefore, if this account starts with a Balance of 11.99, a call to the Debit method while passing 11.22 should give you a new Balance of 0.77.

    Note

    You will use this expected Balance value (0.77) later in this walkthrough.

  10. In the BankAccountTest.cs file, scroll to the DebitTest method.

  11. Set the following values:

    BankAccount target = new BankAccount("Mr. Bryan Walton", 11.99);
    double amount = 11.22;
    
  12. In the CreditTest method, add "Mr. Bryan Walton", 11.99) to the new BankAccount.

  13. Save the BankAccountTest.cs file.

You have created a source-code file that contains tests for the Bank project. You are now ready to run the tests in the BankAccountTest class on the code of the Bank project.

Run and Customize a Unit Test

Prerequisite: Perform the steps in the procedure Create a Unit Test.

To run and customize a unit test

  1. On the Test menu, click Windows and the select Test View.

    The Test View window is displayed.

  2. Right-click DebitTest and click Run Selection.

    If the Test Results window is not already open, it opens now. The DebitTest test runs.

    In the Result column in the Test Results window, test status is displayed as Running while the test is running. After the test run finishes, the outcome of the test changes to Inconclusive.

  3. In the Test Results window, right-click the row that represents the test and then click View Test Results Details.

  4. In the Test Results Details page, there is error message "Assert.Inconclusive failed. A method that does not return a value cannot be verified." To work toward creating a successful test, start by finding and evaluating this Assert statement.

  5. To find the test method that contains the Assert statement, open the BankAccountTest.cs file and scroll to the DebitTest() method.

  6. The Assert statement is the last line in the DebitTest method. It reads as follows:

    Assert.Inconclusive("A method that does not return a value cannot be verified.");
    

    Comment out this Assert statement.

  7. If you ran the test now, it would give a Passed result, but only because it tests for nothing. You must add code that tests for expected results. Add the following statement to the end of the DebitTest method:

    Assert.AreEqual((System.Convert.ToDouble(0.77)), target.Balance, 0.05);
    

    This statement compares the expected result (0.77) with the actual result from a call to the Balance method of the BankAccount class. If the two values are unequal, the Assert returns False, which makes the test fail.

    Note

    This Assert statement includes a third parameter, delta, with a value of 0.05. The delta parameter is required in this overload of the Assert.AreEqual method; it compensates for the rounding error intrinsic in floating-point types such as Doubles.

You have run the generated DebitTest method of your BankAccountTest test class, noted that it needed changes, and made those changes. It is now ready to test for the accuracy of the Debit method in your application.

Run a Unit Test and Fix Your Code

Prerequisite: Perform the steps in the procedure Run and Customize a Unit Test.

To run a unit test and fix your code

  1. Run the Debit test again: In the file BankAccountTest.cs, right-click the DebitTest() method and then click Run Tests.

    In the Result column in the Test Results window, test status is displayed as Running while the test is running. After the test run finishes, the outcome of the test changes to Failed.

  2. In the Test Results window, right-click the row that represents the test and then click View Test Results Details.

    This opens the test Results Details page, which displays the error message "Assert.AreEqual failed. Expected a difference no greater than <0.05> between expected value <0.77> and actual value <23.21>". These numbers seem to indicate a faulty mathematical operation. Because the DebitTest method of the BankAccountTest class tests the Debit method of the BankAccount class, start by checking the Debit method.

  3. Open the Class1.cs file and scroll to the Debit method.

  4. Notice the following assignment:

    m_balance += amount;
    

    This assignment adds an amount to a balance when, in a Debit method, it should be subtracting. Change this line to read as follows:

    m_balance -= amount;
    
  5. Run the Debit test again.

    The Result column of the Test Results window displays Passed for DebitTest.

    Note

    You did not have to rebuild the test project after changing the source code because running a test silently builds the project.

You have created a unit test that works and, through it, found and fixed an error in your code.

Create and Run a Unit Test for a Private Method

Prerequisite: Perform the steps in the procedure, Run a Unit Test and Fix Your Code.

To create and run a unit test for a private method

  1. Open the Class1.cs file in the Bank project.

  2. Right-click the FreezeAccount() method and select Create Unit Tests.

    This displays the Create Unit Tests dialog box.

    In the displayed tree structure, only the FreezeAccount() method is selected.

  3. (Optional) Click Filter, and then clear Display Non-public items. Notice that the FreezeAccount() method is removed from the list of child methods of the BankAccount class. Click Filter again, and then select Display Non-public items to re-display the FreezeAccount() method.

  4. Make sure that the FreezeAccount() method is selected, and then click OK.

    This creates a new private accessor file that is named Bank.accessor. It contains special accessor methods that the test uses to indirectly call private methods in the BankAccount class. You can see the new file displayed in Solution Explorer in the Test References folder.

  5. Open the BankAccountTest.cs file and scroll to the FreezeAccountTest() method.

  6. Change the code of the FreezeAccountTest() method so that it reads as follows. Changed or new areas are indicated:

    public void FreezeAccountTest()
    {
        BankAccount_Accessor target = new BankAccount_Accessor("Mr. Bryan Walton", 11.99); // TODO: Initialize to an appropriate value
    target.FreezeAccount(); 
        // Assert.Inconclusive("A method that does not return a value cannot be verified.");
        
        bool creditAccount = false; // False means account could be credited: Fail test. 
        // Try to credit account
        try
        {
            target.Credit(1.00); 
        }
        catch (System.Exception)
        {
            // Threw exception. FreezeAccount worked correctly: Pass test. 
            creditAccount = true;
        }
        
        // Assert fails if 'creditAccount' condition is false. Fail test.
        Assert.IsTrue(creditAccount, "Was able to credit account.");
    }
    
  7. Run the FreezeAccountTest test.

    In the Result column in the Test Results window, the final test status appears as Passed. This is the expected result because the test called the Credit() method after freezing the account by calling the FreezeAccount() method.

You have added a private method, created a new unit test for it, and run the test. You can run it additional times, using other borderline values, such as 15.00, for the balance variable.

Next Steps

When you run tests on code in an assembly, you can see the proportion of your project's code that is being tested by collecting code coverage data. For more information, see Walkthrough: Run Tests and View Code Coverage.

You can run tests on a command line instead of in Visual Studio. For more information, see Walkthrough: Using the Command-line Test Utility.

If you are using Visual Studio 2010 Ultimate,you can create load tests to isolate stress and performance issues using your unit tests.

Walkthrough: Creating and Running a Load Test Containing Unit Tests

See Also

Tasks

Sample Project for Creating Unit Tests