Walkthrough: Creating and Running Unit Tests
This walkthrough will step you through creating, running, and customizing a series of tests using the Team System testing tools. 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
- The Woodgrove Bank project. See Unit Test Sample.
Prepare the Walkthrough
To prepare the walkthrough
Open Visual Studio 2005 Team Edition for Testers.
On the File menu, point to New and then click Project.
The New Project dialog box appears.
Under Project Types, click Visual C#.
Under Templates, click Class Library.
On the Name line, 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.
Double-click the file Class1.cs in Solution Explorer to open it in the Visual Studio Code Editor.
Copy the source code from the Unit Test Sample.
Replace the original contents of Class1.cs with the code from the Unit Test Sample.
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
In Solution Explorer, double-click the Class1.cs file in the Bank project.
This opens the source file for viewing and editing.
Note
The Bank project contains the code you want to test, also referred to as the code under test, or CUT.
In the BankAccount class in the Class1.cs file, scroll to the Debit() method.
Right-click the Debit() method, and select Create Unit Tests.
This displays the Create Unit Tests dialog box.
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.
For Output project, click Create a new Visual C# test project.
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.
In the Generate Unit Tests dialog box, click OK.
The New Test Project dialog box is displayed.
Accept the default name and then click Create.
This creates a project named TestProject1, which is displayed in Solution Explorer.
To that test project is added a file that is named Class1Tests.cs, which contains a test class. The class is populated with an initialize method, a cleanup method, and 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 CUT that you want to test. Test methods are housed in a test class that is assigned the TestClass() attribute.
In Class1Tests.cs, specify values for the variables to be tested. Scroll to the DebitTest method, where you see three // TODO lines that indicate variables to set, namely customerName, balance, and amount. What values should you use? To answer that, you must know the values that will be used when the application is run.
In Solution Explorer, double-click the Class1.cs file to open it, 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 result in a new Balance of 0.77.
Note
You will use this expected Balance value (0.77) in the procedure Run and Customize a Unit Test.
Open the Class1Tests.cs file and scroll to the DebitTest method.
Set the following values:
string customerName = "Mr. Bryan Walton"; double balance = 11.99; double amount = 11.22;
Save the Class1Tests.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
Using either the Test Manager window or Test View window, run the DebitTest unit test.
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.
In the Test Results window, double-click the row that represents the test.
This opens the test Results Details page, which contains information about the results of the test.
Notice that the test Results Details page displays the 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.
To find the test method that contains the Assert statement, open the Class1Tests.cs file and scroll to the DebitTest() method.
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.
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
Run the Debit test: Select the DebitTest item in Test View and click Run. Alternatively, right-click DebitTest and click Run Selection.
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.
In the Test Results window, double-click the row that represents the test.
This opens the test Results Details page, which displays the error message "Assert.AreEqual failed. Expected: <0.77>, Actual: <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.
In Solution Explorer, double-click the Class1.cs file in the Bank project and scroll to the Debit method.
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;
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 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
In Solution Explorer, double-click the Class1.cs file in the Bank project.
In the BankAccount class in the Class1.cs file, uncomment the following code:
// new enum: public enum accountType { Gold, Platinum, } // private method: private accountType GetAccountType { get { if (Balance > 15.00) return accountType.Platinum; else return accountType.Gold; } }
Right-click the GetAccountType() method, and select Create Unit Tests.
This displays the Create Unit Tests dialog box.
In the displayed tree structure, only the GetAccountType() method is selected. Leave it selected and then click OK.
This creates a new file that is named VSCodeGenAccessors.cs, which contains special accessor methods that retrieve values of private entities in the BankAccount class. You can see the new file displayed in Solution Explorer in the test project folder.
Open the Class1Tests.cs file and scroll to the GetAccountTypeTest() method.
Comment out the line that reads:
Assert.Inconclusive("Verify the correctness of this test method.");
Within the GetAccountTypeTest() method, find the three assignment statements that are marked with // TODO: comments. Change them to read as follows:
string customerName = "Mr. Bryan Walton"; double balance = 7.00; TestProject1.BankAccountNS_BankAccount_accountTypeAccessor val = TestProject1.BankAccountNS_BankAccount_accountTypeAccessor.Gold;
Run the GetAccountTypeTest test.
In the Result column in the Test Results window, the final test status displays as Passed. This is the expected result because with the account balance set to 7.00, the accountType should be Gold.
In GetAccountTypeTest(), change the
balance
assignment to read as follows:double balance = 15.01;
Re-run the GetAccountTypeTest test.
The GetAccountTypeTest() test tests the GetAccountType() method by comparing the value it returns with an expected value. In this test, returning the value of Gold for an account balance of 15.01 is incorrect. Therefore, the test expectedly produces a result of Failed, which indicates that the number tested is out of range for the Gold account type.
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.
See Also
Concepts
Unit Testing Framework
Test Results Reported