Walkthrough: Test-First Support with the Generate From Usage Feature
Note
This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here
This topic demonstrates how to use the Generate From Usage feature, which supports test-first development.
Test-first development is an approach to software design in which you first write unit tests based on product specifications, and then write the source code that is required to make the tests succeed. Visual Studio supports test-first development by generating new types and members in the source code when you first reference them in your test cases, before they are defined.
Visual Studio generates the new types and members with minimal interruption to your workflow. You can create stubs for types, methods, properties, fields, or constructors without leaving your current location in code. When you open a dialog box to specify options for type generation, the focus returns immediately to the current open file when the dialog box closes.
The Generate From Usage feature can be used with test frameworks that integrate with Visual Studio. In this topic, the Microsoft Unit Testing Framework is demonstrated.
Note
Your computer might show different names or locations for some of the Visual Studio user interface elements in the following instructions. The Visual Studio edition that you have and the settings that you use determine these elements. For more information, see Personalizing the IDE.
To create a Windows Class Library project and a Test project
In Visual C# or Visual Basic, create a new Windows Class Library project. Name it
GFUDemo_VB
orGFUDemo_CS
, depending on which language you are using.In Solution Explorer, right-click the solution icon at the top, point to Add, and then click New Project. In the New Project dialog box, in the Project Types pane on the left, click Test.
In the Templates pane, click Unit Test Project and accept the default name of UnitTestProject1. The following illustration shows the dialog box when it appears in Visual C#. In Visual Basic, the dialog box looks similar.
New Project dialog box
Click OK to close the New Project dialog box.
In your class project, in Solution Explorer, right-click the References entry and click Add Reference.
In the Reference Manager dialog box, select Projects and then select your unit test project.
Click OK to close the Reference Manager dialog box.
In the Class1 file, immediately after the last of the existing using statements, add a using statement for the test project:
In Visual Basic, add
Using UnitTestProject1
In C#, add
using UnitTestProject1;
Save your solution. You are now ready to begin writing tests
To generate a new class from a unit test
The test project contains a file that is named UnitTest1. Double-click this file in Solution Explorer to open it in the Code Editor. A test class and test method have been generated.
Locate the declaration for class
UnitTest1
and rename it toAutomobileTest
. In C#, if aUnitTest1()
constructor is present, rename it toAutomobileTest()
.Note
IntelliSense now provides two alternatives for IntelliSense statement completion: completion mode and suggestion mode. Use suggestion mode for situations in which classes and members are used before they are defined. When an IntelliSense window is open, you can press CTRL+ALT+SPACEBAR to toggle between completion mode and suggestion mode. See Using IntelliSense for more information. Suggestion mode will help when you are typing
Automobile
in the next step.Locate the
TestMethod1()
method and rename it toDefaultAutomobileIsInitializedCorrectly()
. Inside this method, create a new instance of a class namedAutomobile
, as shown in the following illustrations. A wavy underline appears, which indicates a compile-time error, and a smart tag appears under the type name. The exact location of the smart tag varies, depending on whether you are using Visual Basic or Visual C#.Visual Basic
Visual C#
Rest the mouse pointer over the smart tag to see an error message that states that no type named
Automobile
is defined yet. Click the smart tag or press CTRL+. (CTRL+period) to open the Generate From Usage shortcut menu, as shown in the following illustrations.Visual Basic
Visual C#
Now you have two choices. You could click Generate 'Class Automobile' to create a new file in your test project and populate it with an empty class named
Automobile
. This is a quick way to create a new class in a new file that has default access modifiers in the current project. You can also click Generate new type to open the Generate New Type dialog box. This provides options that include putting the class in an existing file and adding the file to another project.Click Generate new type to open the Generate New Type dialog box, which is shown in the following illustration. In the Project list, click GFUDemo_VB or GFUDemo_CS to instruct Visual Studio to add the file to the source code project instead of the test project.
Generate New Type dialog box
Click OK to close the dialog box and create the new file.
In Solution Explorer, look under the GFUDemo_VB or GFUDemo_CS project node to verify that the new Automobile.vb or Automobile.cs file is there. In the Code Editor, the focus is still in
AutomobileTest.DefaultAutomobileIsInitializedCorrectly
. You can continue to write your test with a minimum of interruption.
To generate a property stub
Assume that the product specification states that the
Automobile
class has two public properties namedModel
andTopSpeed
. These properties must be initialized with default values of"Not specified"
and-1
by the default constructor. The following unit test will verify that the default constructor sets the properties to their correct default values.Add the following line of code to
DefaultAutomobileIsInitializedCorrectly
.Assert.IsTrue((myAuto.Model == "Not specified") && (myAuto.TopSpeed == -1));
Assert.IsTrue((myAuto.Model = "Not specified") And (myAuto.TopSpeed = -1))
Because the code references two undefined properties on
Automobile
, a smart tag appears. Click the smart tag forModel
and then click Generate property stub. Generate a property stub for theTopSpeed
property also.In the
Automobile
class, the types of the new properties are correctly inferred from the context.The following illustration shows the smart tag shortcut menu.
Visual Basic
Visual C#
To locate the source code
Use the Navigate To feature to navigate to the Automobile.cs or Automobile.vb source code file so that you can verify that the new properties have been generated.
The Navigate To feature enables you to quickly enter a text string, such as a type name or part of a name, and go to the desired location by clicking the element in the result list.
Open the Navigate To dialog box by clicking in the Code Editor and pressing CTRL+, (CTRL+comma). In the text box, type
automobile
. Click the Automobile class in the list, and then click OK.The Navigate To window is shown in the following illustration.
Navigate To window
To generate a stub for a new constructor
In this test method, you will generate a constructor stub that will initialize the
Model
andTopSpeed
properties to have values that you specify. Later, you will add more code to complete the test. Add the following additional test method to yourAutomobileTest
class.[TestMethod] public void AutomobileWithModelNameCanStart() { string model = "Contoso"; int topSpeed = 199; Automobile myAuto = new Automobile(model, topSpeed); }
<TestMethod()> Public Sub AutomobileWithModelNameCanStart() Dim model As String = "Contoso" Dim topSpeed As Integer = 199 Dim myAuto As New Automobile(model, topSpeed) End Sub
Click the smart tag under the new class constructor and then click Generate constructor stub. In the
Automobile
class file, notice that the new constructor has examined the names of the local variables that are used in the constructor call, found properties that have the same names in theAutomobile
class, and supplied code in the constructor body to store the argument values in theModel
andTopSpeed
properties. (In Visual Basic, the_model
and_topSpeed
fields in the new constructor are the implicitly defined backing fields for theModel
andTopSpeed
properties.)After you generate the new constructor, a wavy underline appears under the call to the default constructor in
DefaultAutomobileIsInitializedCorrectly
. The error message states that theAutomobile
class has no constructor that takes zero arguments. To generate an explicit default constructor that does not have parameters, click the smart tag and then click Generate constructor stub.
To generate a stub for a method
Assume that the specification states that a new
Automobile
can be put into a Running state if itsModel
andTopSpeed
properties are set to something other than the default values. Add the following lines to theAutomobileWithModelNameCanStart
method.myAuto.Start(); Assert.IsTrue(myAuto.IsRunning == true);
myAuto.Start() Assert.IsTrue(myAuto.IsRunning = True)
Click the smart tag for the
myAuto.Start
method call and then click Generate method stub.Click the smart tag for the
IsRunning
property and then click Generate property stub. TheAutomobile
class now contains the following code.public class Automobile { public string Model { get; set; } public int TopSpeed { get; set; } public Automobile(string model, int topSpeed) { this.Model = model; this.TopSpeed = topSpeed; } public Automobile() { // TODO: Complete member initialization } public void Start() { throw new NotImplementedException(); } public bool IsRunning { get; set; } }
Public Class Automobile Sub New(ByVal model As String, ByVal topSpeed As Integer) _model = model _topSpeed = topSpeed End Sub Sub New() ' TODO: Complete member initialization End Sub Property Model() As String Property TopSpeed As Integer Property IsRunning As Boolean Sub Start() Throw New NotImplementedException End Sub End Class
To run the tests
On the Unit Test menu, point to Run Unit Tests, and then click All Tests. This command runs all tests in all test frameworks that are written for the current solution.
In this case, there are two tests, and they both fail, as expected. The
DefaultAutomobileIsInitializedCorrectly
test fails because theAssert.IsTrue
condition returnsFalse
. TheAutomobileWithModelNameCanStart
test fails because theStart
method in theAutomobile
class throws an exception.The Test Results window is shown in the following illustration.
Test Results window
In the Test Results window, double-click on each test result row to go to the location of each test failure.
To implement the source code
Add the following code to the default constructor so that the
Model
,TopSpeed
andIsRunning
properties are all initialized to their correct default values of"Not specified"
,-1
, andTrue
(true
).public Automobile() { this.Model = "Not specified"; this.TopSpeed = -1; this.IsRunning = true; }
Sub New() Model = "Not specified" TopSpeed = -1 IsRunning = True End Sub
When the
Start
method is called, it should set theIsRunning
flag to true only if theModel
orTopSpeed
properties are set to something other than their default value. Remove theNotImplementedException
from the method body and add the following code.public void Start() { if (this.Model != "Not specified" || this.TopSpeed != -1) this.IsRunning = true; else this.IsRunning = false; }
Sub Start() If Model <> "Not specified" Or TopSpeed <> -1 Then IsRunning = True Else IsRunning = False End If End Sub
To run the tests again
On the Test menu, point to Run, and then click All Tests in Solution. This time the tests pass. The Test Results window is shown in the following illustration.
Test Results window
See Also
Generate From Usage Writing Code Using IntelliSense Unit Test Your Code