1. Introduction

This document will cover practical approach to White box Testing Techniques using Microsoft Visual Studio 2005 Test Team Suite. It covers concepts with a simple, easy to follow example.

As Microsoft Visual Studio 2005 Test Team Suite is new to the market, there is not enough and useful documentation for testing. So we are sharing our experience in this paper.

2. Topics Covered

3. What is White box testing?

White box testing is a technique for Unit Testing used to validate that a particular module of source code is working properly. The idea is to write test cases for all functions and methods so that whenever a change causes a regression, it can be quickly identified and fixed. Ideally, each test case is separate from the others. This type of testing is mostly done by the developers and not by end-users.

4. Benefits

The goal of unit testing is to isolate each part of the program and show that the individual parts are correct. Unit testing provides a strict, written contract that the piece of code must satisfy. As a result, it affords several benefits.

4.1. Cheaper cost
There is not additional cost for Team Test Suite. It is a component that comes along with the MS Visual Studio IDE.

4.2. Disciplined Development
Well defined deliverable for the developer and more quantifiable progress. Often, just considering a test case will identify issues with an approach/design.

4.3. Facilitates change and Reduces code fragility
Unit testing allows the programmer to refractor code at a later date, and make sure the module still works correctly (i.e. regression testing).

4.4. Simplifies integration
Unit testing helps eliminate uncertainty in the pieces themselves and can be used in a bottom-up testing style approach. By testing the parts of a program first and then testing the sum of its parts, integration testing becomes much easier.

4.5. Documentation
Unit testing provides a sort of "living document". Clients and other developers looking to learn how to use the class can look at the unit tests to determine how to use the class to fit their needs and gain a basic understanding of the API.

4.6. Relative cost to fix defects graph

A high percentage of errors are caught in the review process:
According to Fagan (1976) 67%,
Jones (1977) 85%
The earlier an error is caught the cheaper it is to fix.

5. White Box Testing Techniques Types

BS7925-2 lists all the white box test techniques

5.1. Why do we need White Box techniques?

5.2. Systematic techniques exist white box testing:

5.3. Designing test cases:

To plan and design effective cases requires a knowledge of the

6. Types

6.1. Statement Testing

Any test case with b TRUE will achieve full statement coverage

NOTE: Full statement coverage can be achieved without exercising with b FALSE

6.2. Branch / Decision testing

Branch / Decision testing example

a;
if (b)
{
c;
}
d;

Note: 100% statement coverage requires 1 test case (b = True)
100% branch / decision coverage requires 2 test cases: (b = True & b = False)

6.3. Cyclometric Complexity Technique:

A quantitative measure of the logical complexity of a program.

There are three algorithms for its calculation.

V(G) = E - N + 2
V(G) = Np + 1
V(G) = R
V(G) = the cyclometric complexity
N = Number of flow graph nodes
Np = Number of flow graph predicate nodes
E = Number of flow graph edges
R = Number of flow graph regions

Example:
void Sort(int items[],int toPos)
{ int pos = 0, minPos = 1;

/* iterate over the vector */
1 while( pos < toPos ) {
2 minPos = pos + 1;

/* find the smallest item */
3 while( minPos <= toPos ) {
4 if(items[pos] < items[minPos]){ /* swap items */
5 int temp = items[pos];
6 items[pos] = items[minPos];
7 items[minPos] = temp;
8 } /*end if*/
9 minPos++;
10 } /*end while inner loop */
11 pos++;
12 } /*end while outer loop */
}

V(G)= Cyclometric complexity
N = Number of flow graph nodes =7
Np = Number of flow graph predicate nodes =3
A predicate node represents a point where flow may continue on two or more paths.
E = Number of flow graph edges =9
R = Number of flow graph regions =4

V(G) = E - N + 2 = 9 - 7 + 2 = 4
V(G) = Np + 1 = 3 + 1 = 4
V(G) = R = 4
I.E. V(G) = 4

Flow Graph

7. Microsoft Visual Studio 2005 Overview

MSVS 2005 is an expansion of Visual Studio Professional including support for various roles in the development process.

Product goals:

7.1. Architecture

7.2. What is Team Test Suite?

With the latest release of Visual Studio Test System (VSTS) comes a full suite of functionality for Visual Studio Team Test (TT).

Team Test is a Visual Studio integrated unit-testing framework that enables:

In addition, Team Test includes a suite of testing capabilities not only for the developer, but the test engineer as well. E.g.: Manual testing

8. Hands-on Approach

In this section, we are going to walk through how to create Team Test unit tests. We begin by creating a sample VB project, and then generating the unit tests for methods within that project. This will provide readers new to Team Test and unit testing with the basic syntax and code. It also provides a good introduction on how to quickly set up the test project structure.
One of the key features of Team Test is the ability to load test data from a database and then use that data within the test methods. After demonstrating basic unit testing, we describe how to create test data and incorporate it into a test.

8.1. Pre Requisites

8.2. Steps involved

1. Open Visual Studio IDE
Click Start-->Programs-->Microsoft Visual Studio 2005-->Microsoft Visual Studio 2005

2. Creating a Sample VB Project
File-->New Project-->Chose from Templates as below

3. Add a simple "add" method to the code. This method accepts 2 arguments, adds them and returns the total.

4. Create Unit Test for "add" method by right clicking on the method


5. This will display a dialog box for generating unit tests into a different project (see Figure below). By default, the Output project setting is for a new Visual Basic project, but C# and C++ test projects are also available. For this article, we will select as Visual Basic project click the OK button.

6.


7. Now enter a Test project name of VSTSVBDemo.Test for the project name.

8. The generated test project contains following files related to testing.

File Name Purpose
AuthoringTest.txt Provides notes about authoring tests including instructions on adding additional tests to the project.
sampleTest.vb Includes generated test for testing the add(x,y) method along with methods for test initialization and cleanup.

9. In addition to some default files; the generated test project contains references to both the Microsoft.VisualStudio.QualityTools.UnitTestFramework and the SampleVB project, which the unit tests are executing against. The former is the testing framework assembly the test engine depends on when executing the unit tests. The latter is a project reference to the target assembly we are testing.

There are two important attributes related to testing with Team Test.

First, the designation of a method as a test is through the TestMethodAttribute attribute. In addition, the class containing the test method has a TestClassAttribute attribute.

Both of these attributes are found in the:

Microsoft.VisualStudio.QualityTools.UnitTesting.Framework namespace.

Team Test uses reflection to search a test assembly and find all the TestClass decorated classes, and then find the corresponding TestMethodAttribute decorated methods to determine what to execute.

One other important criterion, validated by the execution engine but not the compiler, is that the test method signature be an instance method that takes no parameters.

The test method AddTest() instantiates the target SampleVB class before checking for assertion.

When the test is run, the Assert.Inconclusive() provides an indication that it is likely to be missing the correct implementation.



10. Providing input values to test method

Updated addTest() Implementation after editing to provide input values

Note that the checks are done using the Assert.AreEqual() method.

11. Running Tests:

To run all tests within the project simply requires running the test project. To enable this action, we need to:

Right-click on the VSTSVBDemo.Test project within the solution explorer and click Set as Startup Project.

Next, use the Debug->Start (F5) or Debug->Start Without Debugging (Ctrl+F5) menu items to begin running the tests.

To view additional details on the test, we can double click on it to open up the AddTest() Results:


Please note that the message in the assert statement does not appear for a "passing" test. It appears only when a test fails along with "Expected" and "Actual" values.

Lets assume that by mistake(even though its highly unlikely) we have put total=x*y instead of x+y in source code file. Let's try to run the same test and see the results:

Yes, as expected, test fails. Please read the results above for details.

12. Loading Test data from Database:

We are loading test data from SQL server database as below:

In Test View, right Click on AddTest()-->Properties-->Chose Data Connection String, Data Table Name and Data Access method as sequential or random.

This adds a line before test method as below:

<DataSource("System.Data.SqlClient", "Data Source=SUPRABHAT;Initial Catalog=I3LEMPLOYEES;User ID=userid;Password=" ", "TestTable1", DataAccessMethod.Sequential)> <testMethod> Public sub Addtest()

The Test Data is loaded from a Data table called: "TestTable1"

Here is the sample data in TestTable1:

Value1 Value2
1 10
22 25
589 236
56 202
45 56
879 563

13. Associating data with AddTest()

Within test method, change x and y as below:

Dim x As Integer = convert.ToInt32(testContextInstance.DataRow("Value1")
Dim y As Integer = convert.ToInt32(testContextInstance.DataRow("Value2")

The important characteristic here is the TestContext.DataRow calls. TestContext is a property that the generator provided when we Created Tests.

The test execution engine at runtime automatically assigns the property. so that within a test we can access data associated with the test context.

Now Run the testmethod. Please note results are available for each data row as below:

14. Code Coverage

9. Testing Private Methods

To generate a unit test for a private method

  1. Open a source code file that contains a private method.
  2. Right-click the private method and select Create Unit Tests.
  3. This displays the Create Unit Tests dialog box. In the visible tree structure, only check box for the private method is selected.
  4. (Optional) In the Create Unit Tests dialog box, you can change the Output project. You can also click Settings to reconfigure the way unit tests are generated.
  5. Click OK.
  6. This creates a new file named VSCodeGenAccessors, which contains special accessor methods that retrieve values of private entities in the class being tested. You can see the new file displayed in Solution Explorer in the test project folder.
  7. If your test project had no unit tests before this point, a source code file to house unit tests is also created. As with the file that contains private accessors, the file that contains unit tests is also visible in your test project in Solution Explorer.

  8. Open the file that contains your unit tests and scroll to the test for the private method. Find the statements that are marked with // TODO: comments and complete them by following the directions in the comments. This helps the test produce more accurate results.

  9. The unit test for the private method is now ready to run.

If the signature for a private method changes, you must update the unit test that exercises that private method.

Regenerate Private Accessors

  1. Open the source-code file that contains the private method that has changed.
  2. Right-click in this private method, point to Create Private Accessor, and select the test project into which to place the updated private accessors file.
  3. To the VSCodeGenAccessors file, this adds a new accessor class that contains methods for retrieving values of the entities in the private class being tested.
    Note: Do not edit the VSCodeGenAccessors file by hand.
  4. This creates up-to-date private accessors for all the private methods in your code-under-test file, whether private accessors for them existed previously.

10. Manual Testing

A manual test is a description of test steps that a tester performs. You use manual tests in situations where other test types, such as unit tests or Web tests, would be too difficult or too time consuming to create and run. You would also use a manual test when the steps cannot be automated, for example to determine a component's behavior when network connectivity is lost; this test could be performed by manually unplugging the network cable.

10.1. Creating Manual Tests and mapping them to MSVSTS

10.2. To author a manual test

10.3. To execute a manual test

11. Limitations of unit testing with MSVSTS 2005

11.1. Database operations testing: two approaches

The first is to replace the database API that your DAL is talking to with an object of your own creation that mimics the database's interface, but does not actually perform any tasks. This method is often referred to as "mocking" or "stubbing.

The second testing method involves your DAL calling the real database behind the scenes. This usually means that you are performing state-based testing.

11.2. Using mock objects

11.3. Using state based testing approach

12. Best Practices

13. Conclusion

Overall, the VSTS unit testing functionality is comprehensive on its own. Furthermore, the inclusion of code coverage analysis is invaluable to evaluating how comprehensive the tests are. By using VSTS, you can correlate the number of tests compared to the number of bugs or the amount of code written. This provides an excellent indicator into the health of a project.

This paper provides not only an introduction to the basic unit testing functionality in the Team Test Suite, but also delves into some of the more advanced functionality relating to data driven testing. By beginning the practice of unit testing your code, you will establish a suite of tests that will prove invaluable throughout the life of a product. Team Test makes this easy with its strong integration into Visual Studio and the rest of the VSTS product line.