This chapter is taken from book
"Moving to Microsoft Visual Studio 2010" by Patrice Pelland, Pascel Pare, and
Ken Haines published for Microsoft Press.
After reading this chapter, you will be able to
- Use the new debugger features of Microsoft
Visual Studio 2010
- Create unit tests and execute them in
Visual Studio 2010
- Compare what was available to you as a
developer in Visual Studio 2005
As we were writing this book, we realized how
much the debugging tools and developer aids have evolved over the last three
versions of Visual Studio. Focusing on debugging an application and writing unit
tests just increases the opportunities we have to work with Visual Studio 2010.
Visual Studio 2010 Debugging Features
In this chapter, you'll go through the different debugging features using a
modified Plan My Night application. If you installed the companion content at
the default location, you'll find the modified Plan My Night application at the
following location: %userprofile%\Documents\Microsoft Press\Moving to Visual
Studio 2010\Chapter 7\Code. Double-click the PlanMyNight.sln file.
First, before diving into the debugging session itself, you'll need to set up a
few things:
- In Solution Explorer, ensure that
PlanMyNight.Web is the startup project. If the project name is not in bold,
right-click on PlanMyNight.Web and select Set As StartUp Project.
- To get ready for the next steps, in the
PlanMyNight.Web solution open the Global.asax.cs file by clicking the
triangle beside the Global.asax folder and then double-clicking the
Global.asax.cs file, as shown in Figure 7-1:
FIGURE 7-1 Solution Explorer before opening the file Global.asax.cs
Managing Your Debugging Session
Using the Plan My Night application, you'll examine how a developer can manage
and share breakpoints. And with the use of new breakpoint enhancements, you'll
learn how to inspect the different data elements in the application in a much
faster and more efficient way. You'll also look at new minidumps and the
addition of a new intermediate language (IL) interpreter that allows you to
evaluate managed code properties and functions during minidump debugging.
New Breakpoint Enhancements
At this point, you have the Global.ascx.cs file opened in your editor. The
following steps walk you through some ways to manage and share breakpoints:
- Navigate to the
Application_BeginRequest(object sender, EventArgs e) method, and set a
breakpoint on the line that reads var url = HttpContext.Current.Request.Url;
by clicking in the left margin or pressing F9. Look at Figure 7-2 to see
this in action:
FIGURE 7-2 Creating a breakpoint
- Press F5 to start the application in debug
mode. You should see the developer Web server starting in the system tray
and a new browser window opening. The application should immediately stop at
the breakpoint you just created. The Breakpoints window might not be visible
even after starting the application in debug mode. If that is the case, you
can make it visible by going to the Debug menu and selecting Windows and
then Breakpoints, or you can use the keyboard shortcut: Ctrl+D+B.
You should now see the Breakpoints window as shown in Figure 7-3:
FIGURE 7-3 Breakpoints window
- In the same method, add three more
breakpoints so that the editor and the Breakpoints window look like those
shown in Figure 7-4:
FIGURE 7-4 Code editor and Breakpoints window with three new breakpoints
Visual Studio 2005 As a reader and a professional developer who used Visual
Studio 2005 often, you probably noticed a series of new buttons as well as
new fields in the Breakpoints window in this exercise. As a reminder, take a
look at Figure 7-5 for a quick comparison of what it looks like in Visual
Studio 2005.
FIGURE 7-5 Visual Studio 2005 Breakpoints window
- Notice that the Labels column is now
available to help you index and to search breakpoints.
It is a really nice and useful feature that Visual Studio 2010 brings to the
table. To use this feature, you simply right-click on a breakpoint in the
Breakpoints window and select Edit Labels or use the keyboard shortcut
Alt+F9, L, as shown in Figure 7-6:
FIGURE 7-6 Edit Labels option
- In the Edit Breakpoint Labels window, add
labels for the selected breakpoint (which is the first one in the
Breakpoints window). Type ContextRequestUrl in the Type A New Label text
box, and click Add. Repeat this operation on the next breakpoint, and type a
label name of url. When you are done, click OK. You should see a window that
looks like Figure 7-7 while you are entering them, and to the right you
should see the Breakpoints window after you are done with those two
operations:
FIGURE 7-7 Adding labels that show up in the Breakpoints window
Note You can also right-click on the breakpoint in the left margin
and select Edit Labels to accomplish the same tasks I just outlined.
Note You'll see that when adding labels to a new breakpoint you can
choose any of the existing labels you have already entered. You'll find
these in the Or Choose Among Existing Labels area, which is shown in the
Edit Breakpoint Labels dialog box on the left in the preceding figure.
- Using any of the ways you just learned,
add labels for each of the breakpoints, and make sure your Breakpoints
window looks like Figure 7-8 after you're done.
FIGURE 7-8 Breakpoints window with all labels entered
When you have a lot of code and are in the midst of a debugging session, it
would be great to be able to filter the displayed list of breakpoints.
That's exactly what the new Search feature in Visual Studio 2010 allows you
to do.
- To see the Search feature in action, just
type url in the search text box and you'll see the list of breakpoints is
filtered down to breakpoints containing url in one of their labels.
In a team environment where you have many developers and testers working
together, often two people at some point in time are working on the same
bugs. In Visual Studio 2005, the two people needed to sit near each other,
send one another screen shots, or send one another the line numbers of where
to put breakpoints to refine where they should look while debugging a
particular bug.
Important One of the great new additions to breakpoint management in Visual
Studio 2010 is that you can now export breakpoints to a file and then send
them to a colleague, who can then import them into his own environment.
Another scenario that this feature is useful for is to share breakpoints
between machines. We'll see how to do that next.
- In the Breakpoints window, click the
Export button to export your breakpoints to a file, and then save the file
on your desktop. Name the file breakexports.xml.
- Delete all the breakpoints either by
clicking the Delete All Breakpoints Matching The Current Search Criteria
button or by selecting all the breakpoints and clicking the Delete The
Selected Breakpoints button . The only purpose of deleting them is to
simulate two developers sharing them or one developer sharing breakpoints
between two machines.
- You'll now import your breakpoints by
clicking the Import button and loading them from your desktop. Notice that
all your breakpoints with all of their properties are back and loaded in
your environment. For the purposes of this chapter, delete all the
breakpoints.
Inspecting the Data
When you are debugging your applications, you know how much time one can spend
stepping into the code and inspecting the content of variables, arguments, and
so forth. Maybe you can remember when you were learning to write code, a while
ago, when debuggers weren't a reality or when they were really rudimentary. Do
you remember (maybe not-you might not be as old as we are) how many printf or
WriteLn statements you had to write to inspect the content of different data
elements?
Visual Studio 2005 In Visual Studio 2005, things were already a big improvement
from the days of writing all kinds of statements to the console, because Visual
Studio had a real debugger with new functionalities. New data visualizers
allowed you to see XML as a well-formed XML snippet and not as a long string.
Furthermore, with those data visualizers, you could view arrays in a more useful
way, with the list of elements and their indices, and you accomplished that by
simply hovering your mouse over the object. Take a look at Figure 7-9 for an
example:
FIGURE 7-9 Collection view versus an array view in the debugger in Visual Studio
2010 and in Visual Studio 2005
Although those DataTip data visualization techniques are still available in
Visual Studio 2010, a few great enhancements have been added that make DataTips
even more useful. The DataTip enhancements have been added in conjunction with
another new feature of Visual Studio 2010, multimonitor support. Floating
DataTips can be valuable to you as a developer. Having the ability to put
DataTips on a second monitor can make your life a lot easier while debugging,
because it keeps the data that always needs to be in context right there on the
second monitor. The following steps demonstrate how to use these features:
- In the Global.ascx.cs file, insert
breakpoints on lines 89 and 91, lines starting with the source code var
authority and var pathAndQuery, respectively.
- You are now going to experiment with the
new DataTip features. Start the debugger by pressing F5. When the debugger
hits the first breakpoint, move your mouse over the word url and click on
the pushpin, as seen in Figure 7-10:
FIGURE 7-10 The new DataTip pushpin feature
- To the right of the line of code, you
should see the pinned DataTip (as seen in the following
figure on the left). If you hover your mouse over the DataTip, you'll get
the DataTip management bar (as seen in Figure 7-11 on the right):
FIGURE 7-11 On the left is the pinned DataTip, and on the right is the
DataTip management bar
Note You should also see in the breakpoint gutter a blue pushpin
indicating that the DataTip is pinned. The pushpin should look like this: .
Because you have a breakpoint on that line, the pushpin is actually
underneath it. To see the pushpin, just toggle the breakpoint by clicking on
it in the gutter. Toggle once to disable the breakpoint and another time to
get it back.
Note If you click the double arrow pointing down in the DataTip
management bar, you can insert a comment for this DataTip, as shown in
Figure 7-12. You can also remove the DataTip altogether by clicking the X
button in the DataTip management bar.
FIGURE 7-12 Inserting a comment for a DataTip
- One nice feature of the new DataTip is
that you can insert any expression to be evaluated right there in your
debugging session. For instance, right-click on the DataTip name, in this
case url, select Add Expression, type authority, and then add another one
like this: (authority != null). You'll see that the expressions are
evaluated immediately and will continue to be evaluated for the rest of the
debugging session every time your debugger stops on those breakpoints. At
this point in the debugging session, the expression should evaluate to null
and false, respectively.
- Press F10 to execute the line where the
debugger stopped, and look at the url DataTip as well as both expressions.
They should contain values based on the current context, as shown in Figure
7-13:
FIGURE 7-13 The url pinned DataTip with the two evaluated expressions
- Although it is nice to be able to have a
mini–watch window where it matters-right there where the code is
executing-you can also see that it is superimposed on the source code being
debugged. Keep in mind that you can move the DataTip window anywhere you
want in the code editor by simply dragging it, as illustrated in Figure
7-14:
FIGURE 7-14 Move the pinned DataTip away from the source code
- Because it is pinned, the DataTip window
stays where you pinned it, so it will not be in view if you trace into
another file. But in some cases, you need the DataTip window to be visible
at all times. For instance, keeping it visible is interesting for global
variables that are always in context or for multimonitor scenarios. To move
a DataTip, you have to first unpin it by clicking the pushpin in the DataTip
management bar. You'll see that it turns yellow. That indicates you can now
move it wherever you want-for instance, over Solution Explorer, to a second
monitor, over your desktop, or to any other window. Take a look at Figure
7-15 for an example:
FIGURE 7-15 Unpinned DataTip over Solution Explorer and the Windows desktop
Note If the DataTip is not pinned, the debugger stops in another file
and method, and the DataTip contains items that are out of context, the
DataTip windows will look like Figure 7-16. You can retry to have the
debugger evaluate the value of an element by clicking on this button: .
However, if that element has no meaning in this context, it's possible that
nothing happens.
FIGURE 7-16 DataTip window with out-of-context items
Note You'll get an error message if you try to pin outside the
editor, as seen in Figure 7-17:
FIGURE 7-17 Error message that appears when trying to pin a DataTip outside
the code editor
Note Your port number might be different than in the screen shots
just shown. This is normal-it is a random port used by the personal Web
server included with Visual Studio.
Note You can also pin any child of a pinned item. For instance, if you look
at url and expand its content by pressing the plus sign (+), you'll see that
you can also pin a child element,
as seen in Figure 7-18:
FIGURE 7-18 Pinned child element within the url DataTip
- Before stopping the debugger, go back to
the Global.ascx.cs if you are not already there and re-pin the DataTip
window. Then stop the debugging session by clicking the Stop Debugging
button in the debug toolbar ( ) or by pressing Shift+F5. Now if you hover
your mouse over the blue pushpin in the breakpoint gutter, you'll see the
values from the last debug session, which is a nice enhancement to the watch
window. Take a look at Figure 7-19 for what you should see:
FIGURE 7-19 Values from the last debug session for a pinned DataTip
Note As with the breakpoints, you can export or import the DataTips
by going to the Debug menu and selecting Export DataTips or Import DataTips,
respectively.
Using the Minidump Debugger
Many times in real-world situations, you'll have access to a minidump from your
product support team. Apart from their bug descriptions and repro steps, it
might be the only thing you have to help debug a customer application. Visual
Studio 2010 adds a few enhancements to the minidump debugging experience.
Visual Studio 2005 In Visual Studio 2005, you could debug managed application or
minidump files, but you had to use an extension if your code was written in
managed code. You had to use a tool called SOS and load it in the debugger using
the Immediate window. You had to attach the debugger both in native and managed
mode, and you couldn't expect to have information in the call stack or Locals
window. You had to use commands for SOS in the Immediate window to help you go
through minidump files. With application written in native code, you used normal
debugging windows and tools. To read more about this or just to refresh your
knowledge of the topic, you can read the Bug Slayer column in MSDN magazine
here:
http://msdn.microsoft.com/en-us/magazine/cc164138.aspx.
Let's see the new enhancements to the minidump debugger. First you need to
create a crash from which you'll be able to generate a minidump file:
- In Solution Explorer in the
PlanMyNight.Web project, rename the file Default.aspx to DefaultA.aspx. Note
the A appended to the word "Default."
- Make sure you have no breakpoints left in
your project. To do that, look in the Breakpoints window and delete any
breakpoints left there using any of the ways you learned earlier in the
chapter.
- Press F5 to start debugging the
application. Depending on your machine speed, soon after the build process
is complete you should see an unhandled exception of type HttpException.
Although the bug is simple in this case, let's go through the steps of
creating the minidump file and debugging it. Figure 7-20 shows what you
should see at this point:
FIGURE 7-20 The unhandled exception you should expect
- It is time to create the minidump file for
this exception. Go to the Debug menu, and select Save Dump As, as seen in
Figure 7-21. You should see the name of the process from which the exception
was thrown. In this case, the process from which the exception was thrown
was Cassini or the Personal Web Server in Visual Studio. Keep the file name
proposed (WebDev.WebServer40.dmp), and save the file on your desktop. Note
that it might take some time to create the file because the minidump file
size will be close to 300 MB.
FIGURE 7-21 Saving the minidump file
- Stop Debugging by pressing Shift+F5 or the
Stop Debugging button.
- Next, go to the File menu and close your
solution.
- In the File menu, click Open and point to
the desktop to load your minidump file named WebDev.WebServer40.dmp. Doing
so opens the Minidump File Summary page, which gives you some summary
information about the bug you are trying to fix. (Figure 7-22 shows what you
should see.) Before you start to debug, you'll get basic information from
that page such as the following: process name, process architecture,
operating system version, CLR version, modules loaded, as well as some
actions you can take from that point. From this place, you can set the paths
to the symbol files. Conveniently, the Modules list contains the version and
path on disk of your module, so finding the symbols and source code is easy.
The CLR version is 4.0; therefore, you can debug here in Visual Studio 2010.
FIGURE 7-22 Minidump summary page
- To start debugging, locate the Actions
list on the right side of the Minidump File Summary page and click Debug
With Mixed.
- You should see almost immediately a
first-chance exception like the one shown in Figure 7-23. In this case, it
tells you what the bug is; however, this won't always be the case. Continue
by clicking the Break button.
FIGURE 7-23 First-chance exception
- You should see a green line indicating
which instruction caused the exception If you look at the source code,
you'll see in your Autos window that the controllerExport variable is null,
and that just before that we specified that if the variable was null we
wanted to have an HttpException thrown if the file to load was not found. In
this case, the file to look for is Default.aspx, as you can see in the
Locals window in the controllerName variable. You can glance at many other
variables, objects, and so forth in the Locals and Autos windows containing
the current context. Here, you have only one call that belongs to your code,
so the call stack indicates that the code before and after is external to
your process. If you had a deeper chain of calls in your code, you could
step back and forth in the code and look at the variables. Figure 7-24 shows
a summary view of all that:
FIGURE 7-24 Autos, Locals, and Call Stack windows, and the next instruction
to execute
- OK, you found the bug, so stop the
debugging by pressing Shift+F5 or clicking the Stop Debugging button. Then
fix the bug by reloading the PlanMyNight solution and renaming the file back
to default.aspx. Then rebuild the solution by going to the Build menu and
selecting Rebuild Solution. Then press F5, and the application should be
working again.
Web.Config Transformations
This next new feature, while small, is one that will delight many developers
because it saves them time while debugging. The feature is the Web.Config
transformations that allow you to have transform files that show the differences
between the debug and release environments. As an example, connection strings
are often different from one environment to the other; therefore, by creating
transform files with the different connection strings-because ASP.NET provides
tools to change (transform) web.config files-you'll always end up with the right
connection strings for the right environment. To learn more about how to do
this, take a look at the following article on MSDN:
http://go.microsoft.com/fwlink/?LinkId=125889.
Creating Unit Tests
Most of the unit test framework and tools are unchanged in Visual Studio 2010
Professional. It is in other versions of Visual Studio 2010 that the change in
test management and test tools is really apparent. Features such as UI Unit
Tests, IntelliTrace, and Microsoft Test Manager 2010 are available in other
product versions, like Visual Studio 2010 Premium and
Visual Studio 2010 Ultimate. To see which features are covered in the
Application Lifecycle Management and for more specifics, refer to the following
article on MSDN:
http://msdn.microsoft.com/en-us/library/ee789810(VS.100).aspx.
Visual Studio 2005 With Visual Studio 2005, you had to own either Visual Studio
2005 Team System or Visual Studio 2005 Team Test to have the ability to create
and execute tests out of the box within Visual Studio 2005. Another option back
then was to go with a third-party option like Nunit.
In this part of the chapter, we'll show you how to add a unit test for a class
you'll find in the Plan My Night application. We won't spend time defining what
a unit test is or what it should contain; rather, we'll show you within Visual
Studio 2010 how to add tests and execute them.
You'll add unit tests to the Plan My Night application for the Print Itinerary
Add-in. To create unit tests, open the solution from the companion content
folder. If you do not remember how to do this, you can look at the first page of
this chapter for instructions. After you have the solution open, just follow
these steps:
- In Solution Explorer, expand the project
PlanMyNight.Web and then expand the Helpers folder. Then double-click on the
file ViewHelper.cs to open it in the code editor. Take a look at Figure 7-25
to make sure you are at the right place:
FIGURE 7-25 The PlanMyNight.Web project and ViewHelper.cs file in Solution
Explorer
- In the code editor, you can add unit tests
in two different ways. You can right-click on a class name or on a method
name and select Create Unit Tests. You can also go to the Test menu and
select New Test. We'll explore the first way of creating unit tests. This
way Visual Studio automatically generates some source code for you.
Right-click on the GetFriendlyTime method, and select Create Unit Tests.
Figure 7-26 shows what it looks like:
FIGURE 7-26 Contextual menu to create unit tests from by right-clicking on a
class name
- After selecting Create Unit Tests, you'll
be presented with a dialog that, by default, shows the method you selected
from that class. To select where you want to create the unit tests, click on
the drop-down combo box at the bottom of this dialog and select
PlanMyNight.Web.Tests. If you didn't have an existing location, you would
have simply selected Create A New Visual C# Test Project from the list.
Figure 7-27 shows what you should be seeing:
FIGURE 7-27 Selecting the method you want to create a unit test against
- After you click OK, the dialog switches to
a test-case generation mode and displays a progress bar. After this is
complete, a new file is created named TimeHelperTest.cs that has
autogenerated code stubs for you to modify.
- Remove the method and its attributes
because you'll create three new test cases for that method. Remove the
following code:
///
<summary>
///A
test for GetFriendlyTime
///</summary>
// TODO: Ensure that the UrlToTest
attribute specifies a URL to an ASP.NET page (for
// example, http://.../Default.aspx).
This is necessary for the unit test to be
// executed on the web server,
// whether you are testing a page,
web service, or a WCF service.
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\\Users\\Patrice\\Documents\\Chapter
7\\code\\PlanMyNight.Web",
"/")]
[UrlToTest("http://localhost:48580/")]
public void
GetFriendlyTimeTest()
{
int totalMinutes = 0;
// TODO: Initialize to an appropriate value
string expected =
string.Empty; //
TODO: Initialize to an appropriate value
string actual;
actual = TimeHelper.GetFriendlyTime(totalMinutes);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the
correctness of this test method.");
}
- Add the three simple test cases validating
three key scenarios used by Plan My Night. To do that, insert the following
source code right below the method attributes that were left behind when you
deleted the block of code in step 5:
[TestMethod]
public void
ZeroReturnsSlash()
{
Assert.AreEqual("-",
TimeHelper.GetFriendlyTime(0));
}
[TestMethod]
public void
LessThan60MinutesReturnsValueInMinutes()
{
Assert.AreEqual("10m",
TimeHelper.GetFriendlyTime(10));
}
[TestMethod()]
public void
MoreThan60MinutesReturnsValueInHoursAndMinutes()
{
Assert.AreEqual("2h 3m",
TimeHelper.GetFriendlyTime(123));
}
- In the PlanMyNight.Web.Tests project,
create a solution folder called Helpers. Then move your TimeHelperTests.cs
file to that folder so that your project looks like Figure 7-28 when you are
done:
FIGURE 7-28 TimeHelperTest.cs in its Helpers folder
- It is time to execute your newly created
tests. To execute only your newly created tests, go into the code editor and
place your cursor on the class named public class TimeHelperTest. Then you
can either go to the Test menu, select Run, and finally select Test In
Current Context or accomplish the same thing using the keyboard shortcut
CTRL+R, T. Look at Figure 7-29 for a reference:
FIGURE 7-29 Test execution menu
- Performing this action executes only your
three tests. You should see the Test Results window (shown in Figure 7-30)
appear at the bottom of your editor with the test results.
FIGURE 7-30 Test Results window for your newly created tests
More Info Depending on what you select, you might have a different behavior
when you choose the Tests In Current Context option. For instance, if you
select a test method like ZeroReturnsSlash, you'll execute only this test
case. However, if you click outside the test class, you could end up
executing every test case, which is the equivalent of choosing All Tests In
Solution.
New Threads Window
The emergence of computers with multiple cores and the fact that language
features give developers many tools to take advantage of those cores creates a
new problem: the difficulty of debugging concurrency in applications. The new
Threads window enables you, the developer, to pause threads and search the
calling stack to see artifacts similar to those you see when using the famous
SysInternals Process Monitor (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx).
You can display the Threads window by going to Debug and selecting Windows And
Threads while debugging an application. Take a look at Figure 7-31 to see the
Threads window as it appears while debugging Plan My Night.
FIGURE 7-31 Displaying the Threads window while debugging Plan My Night
The Threads window allows you to freeze threads and then thaw them whenever you
are ready to let them continue. It can be really useful when you are trying to
isolate particular effects. You can debug both managed code and unmanaged code.
If your application uses threads, you'll definitely love this new feature of the
debugger in Visual Studio 2010.
Visual Studio 2005 In Visual Studio 2005, you had to uses many tools not
integrated into Visual Studio or third-party tools. And in most cases, you still
had to rely on your instinct and experience to find concurrency bugs.
Summary
In this chapter, you learned how to manage your debugging sessions by using new
breakpoint enhancements and employing new data-inspection and data-visualization
techniques. You also learned how to use the new minidump debugger and tools to
help you solve real customer problems from the field. The chapter also showed
you how to raise the quality of your code by writing unit tests and how Visual
Studio 2010 Professional can help you do this. Multicore machines are now the
norm, and so are multithreaded applications. Therefore, the fact that Visual
Studio 2010 Professional has specific debugger tools for finding issues in
multithreaded
applications is great news.
Finally, throughout this chapter you also saw how Visual Studio 2010
Professional has raised the bar in terms of debugging applications and has given
professional developers the tools to debug today's feature-rich experiences. You
saw that it is a clear improvement over what was available in Visual Studio
2005. The exercises in the chapter scratched the surface of how you'll save time
and money by moving to this new debugging environment and showed that Visual
Studio 2010 is more than a small iteration in the evolution of Visual Studio. It
represents
a huge leap in productivity for developers.
The various versions of Visual Studio 2010 give you a great list of improvements
related to the debugger and testing. My personal favorites are IntelliTrace-http://msdn.microsoft.com/en-us/library/dd264915(VS.100).aspx-which
is available only in Visual Studio 2010 Ultimate and Microsoft Test Manager.
IntelliTrace enables test teams to have much better experiences using Visual
Studio 2010 and Visual Studio 2010 Team Foundation Server-http://msdn.microsoft.com/en-us/library/bb385901(VS.100).aspx.