Lesson 3: Debugging

Lesson 3: Debugging

Testing is probably one of the few endeavors in which failure is a kind of success. In this lesson, you ll learn how to use those successes to fix problems in your code. The topics covered in this lesson build on the discussion of the Visual Studio debugging tools begun in Chapter 1, Introduction to Web Programming. This includes fixing specific problems uncovered by testing, adding diagnostic code to an application, and debugging a Web application as it runs on a remote server.

After this lesson, you will be able to

  • Apply the results of unit tests to fix common problems

  • Use the Debug and Trace diagnostic classes to display alerts and generate logs during development

  • Configure a Web server to allow remote workstations to debug Web applications

  • Debug Web applications as they run on a remote server

Estimated lesson time: 30 minutes

Putting Test Results to Work

Something you probably noticed if you ran the unit tests for the FlashCards application shown in Lesson 1 is that FlashCards didn t pass the tests. That s because FlashCards is a simplified demonstration program, not a robust application intended for commercial use. Try that excuse at work sometime!

Seriously, though, the results are instructive. The first set of errors you encounter with the FlashCardClass unit tests are overflows, because you used integer MinValue and MaxValue properties to initialize the random numbers. Adding two values near the integer s maximum value results in a number larger than an integer. The related code is shown here:

Visual Basic .NET

' Test code Function TestFlashCard() As Boolean 'Create class Dim FlashCard As New vbFlashCards.FlashCardClass() 'Test is class exists. If IsNothing(FlashCard) Then Console.WriteLine("FlashCardClass failed") ' Return false and end here. Return False End If 'Test shuffle method. FlashCard.Shuffle(Integer.MinValue, Integer.MaxValue) 'Test properties. If (FlashCard.Answer <> FlashCard.FirstNumber + FlashCard.SecondNumber) _ Then Console.Write("Error: Answers don't match") End If End Function ' FlashCardClass code with error. ' Calculates answer based on current operation. Public Function Answer() As Integer Select Case mstrOp Case "+" Return mintFirstNumber + mintSecondNumber 'Overflow!!!! Case "x", "*" Return mintFirstNumber * mintSecondNumber Case "-" Return mintFirstNumber mintSecondNumber Case Else Return 0 End Select End Function

Visual C#

//Test code. static bool TestFlashCardClass() { //Create class csFlashCards.FlashCardClass FlashCard = new csFlashCards.FlashCardClass(); //Test is class exists. if (FlashCard == null) { Console.WriteLine("FlashCardClass failed"); //Return false and end here. return false; } //Test shuffle method using maximum and minimum values. FlashCard.Shuffle(int.MinValue, int.MaxValue); //Test properties. int intFirst = FlashCard.FirstNumber; int intSecond = FlashCard.SecondNumber; double dblAnswer = intFirst + intSecond; if (dblAnswer != (double)FlashCard.Answer()) { Console.WriteLine("Error: Numbers don't add up!"); } } //FlashCardClass code with error. //Calculates answer based on current operation. public int Answer() { switch(mstrOp) { case "+": return mintFirstNumber + mintSecondNumber; case "x": return mintFirstNumber * mintSecondNumber; case "*": return mintFirstNumber * mintSecondNumber; case "-": return mintFirstNumber - mintSecondNumber; default : return 0; } }

You have two ways to tackle this problem: restrict the range of possible FirstNumber and SecondNumber property values, or change the return type for the Answer method. The second approach is more obvious from a user s standpoint because integers are a common input type and it would be hard to explain a new, smaller type for those properties.

The following code shows the changes to the Answer method that allow it to pass its unit test:

Visual Basic .NET

Public Function Answer() As Double Select Case mstrOp Case "+" Return CDbl(mintFirstNumber) + CDbl(mintSecondNumber) Case "x", "*" Return CDbl(mintFirstNumber) * CDbl(mintSecondNumber) Case "-" Return CDbl(mintFirstNumber) - CDbl(mintSecondNumber) Case "/" Return CDbl(mintFirstNumber) / CDbl(mintSecondNumber) Case Else Return 0 End Select End Function

Visual C#

public double Answer() { switch(mstrOp) { case "+": return mintFirstNumber + mintSecondNumber; case "x": return mintFirstNumber * mintSecondNumber; case "*": return mintFirstNumber * mintSecondNumber; case "-": return mintFirstNumber - mintSecondNumber; default : return 0; } }

Another problem arises with FlashCardClass if you specify an Operation property other than +, -, /, * or x. The Operation property simply returns 0, which is a little sloppy. The following changes ensure that only valid operations are used:

Visual Basic .NET

Public Property Operation() As String Get Operation = mstrOp End Get Set(ByVal Value As String) If InStr("+-/x*", Value) Then mstrOp = Value Else Throw New Exception("Unrecognized operator") End If End Set End Property

Visual C#

public string Operation { get { return mstrOp; } set { if (" +-/x*".IndexOf(value, 1) != 0) mstrOp = value; else throw(new Exception("Unrecognized operator")); } }

These bug fixes illustrate how important it is to perform unit tests before checking new classes into a project. When a class is part of a larger project, it becomes much harder to locate the cause of an error.

Using the Debug and Trace Classes

The .NET Framework includes the Debug and Trace classes in the System.Diagnostics namespace as tools to help you ferret out errors and unexpected behaviors in your application. These classes let you display alerts or write messages based on results within your application.

The difference between the two classes is how they are handled in release builds. By default, Debug methods and properties are automatically stripped out of code compiled for release. Trace methods and properties are retained in release code by default. This gives you two levels of diagnostics: one for debugging errors prior to release, and one for diagnosing performance and problems in the field.

Because Debug and Trace are part of a .NET namespace, you need to add an Imports or using statement to code modules before using them:

Visual Basic .NET

Imports System.Diagnostics

Visual C#

using System.Diagnostics;

Displaying Alerts and Messages

The Debug and Trace classes Assert method tests a value and displays an alert if the value is False. Use Assert to halt an application for an unexpected result. For example, the following code displays an alert if the numbers shown on the FlashCards form don t add up as expected:

Visual Basic .NET

Private Sub txtAnswer_TextChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles txtAnswer.TextChanged If txtAnswer.Text = FlashCard.Answer Then lblFeedback.Text = "Correct!" Debug.Assert(CInt(txtAnswer.Text) = CInt(lblFirst.Text) + _ CInt(lblSecond.Text), "Form values don't add up!") ' Get another set of numbers. FlashCard.Shuffle() ' Refresh display to show new numbers. RefreshDisplay() ' Clear answer txtAnswer.Text = "" Else lblFeedback.Text = "Oops! Try Again." End If End Sub

Visual C#

private void txtAnswer_TextChanged(object sender, System.EventArgs e) { if(txtAnswer.Text == FlashCard.Answer().ToString()) { lblFeedback.Text = "Correct!"; Debug.Assert(Convert.ToInt32(txtAnswer.Text) == Convert.ToInt32(lblFirst.Text) + Convert.ToInt32(lblSecond.Text),  "Form values don't add up!"); //Get another set of numbers. FlashCard.Shuffle(); //Refresh display to show new numbers. RefreshDisplay(); //Clear answer txtAnswer.Text = ""; } else { lblFeedback.Text = "Oops! Try Again."; } }

In a Web application, the alert is displayed on the server. If you re running the Web application s server on your local machine, this alert appears as expected, as shown in Figure 10-22. If you re running the Web application on a remote server, however, you won t see the alert if you re attached to the application s process running on the server only for remote debugging, as described later in this lesson.

figure 10-22 displaying an alert (local server)

Figure 10-22. Displaying an alert (local server)

Use the Write or WriteLine methods to write a message without halting the application. By default, these messages are displayed in the Visual Studio .NET Output window during debugging.

Logging Debug and Trace Messages

To record debug and trace messages on a deployed application, create a TextWriterTraceListener class and add it to the Debug or Trace class s Listeners collection. For example, the following code directs debug messages to the server s console:

Visual Basic .NET

Debug.Listeners.Add(New TextWriterTraceListener(Console.Out)) Debug.WriteLine("Starting tests.")

Visual C#

Debug.Listeners.Add(new TextWriterTraceListener(Console.Out)); Debug.WriteLine("Starting tests.");

To write messages to a file rather than to the console, specify a file name and use the Flush method to write the output. For example, the following code writes a message to the Results.log file:

Visual Basic .NET

Debug.Listeners.Add(New TextWriterTraceListener("Results.log")) Debug.WriteLine("Starting tests.") Debug.Flush()

Visual C#

Debug.Listeners.Add(new TextWriterTraceListener("Results.log")); Debug.WriteLine("Starting tests."); Debug.Flush();

Remote Debugging

You usually debug a Web application by running the code locally on your development machine, but that s not the environment in which the application ultimately runs. To resolve problems with Web applications in real-world situations, you need to be able to debug them as they run on a remote server.

To debug an application on a remote server, follow these steps:

  1. Install the Visual Studio .NET remote debugging server components on the Web application server.

  2. Configure the server permissions to allow you to debug applications remotely.

  3. Attach to the remote Web application process from your debug machine.

The following sections describe these steps in greater detail.

Installing Remote Components

The Visual Studio .NET Setup Wizard includes an option for installing remote components. Run Visual Studio .NET Setup on the server, and choose the Full Remote Debugging option during installation, as shown in Figure 10-23.

figure 10-23 installing remote debugging components

Figure 10-23. Installing remote debugging components

Setup installs the required components and configures the server to allow remote debugging.

Setting Server Permissions

To be able to debug processes running on a server, you must have a user account on the server and that account must belong to the Debugger Users group. The Visual Studio .NET Setup Wizard creates this group when you install the remote debugging components. You should make sure that all users who need debugging privileges on the server belong to this group.

Use the MMC to add users to this group, as shown in Figure 10-24.

figure 10-24 adding remote debugger users

Figure 10-24. Adding remote debugger users

Attaching to a Remote Process

Visual Studio .NET can attach to processes running on a remote server. While attached to the process, Visual Studio .NET can receive Output window messages, display alerts from the Assert method, set breakpoints, view variables, and step through code running on the remote server.

To attach to a remote process, follow these steps:

  1. From the Tools menu, choose Debug Processes. Visual Studio .NET displays the Processes dialog box, as shown in Figure 10-25.

    figure 10-25 attaching to a process

    Figure 10-25. Attaching to a process

  2. By default, Web applications run in the process named aspnet_wp.exe. Select the remote process you want to debug, click Attach, and then click Close.

When attached to a remote process, Visual Studio .NET can step into the code by setting breakpoints. The easiest way to do this with a Web application is to set a breakpoint for the Page_Load function to halt the application at the beginning of a Web form and then set breakpoints or watches within the remote code as desired.

To set a breakpoint in a remote process, follow these steps:

  1. Click the Breakpoints tab in Visual Studio .NET, as shown in Figure 10-26.

    figure 10-26 breakpoints window

    Figure 10-26. Breakpoints window

  2. Click the New button on the Breakpoints window toolbar. Visual Studio .NET displays the New Breakpoint dialog box, as shown in Figure 10-27.

    figure 10-27 adding a breakpoint

    Figure 10-27. Adding a breakpoint

  3. Enter a procedure name in the Function box, and click OK. For Web applications, it s easiest to stop the application at the Page_Load event procedure and then set additional breakpoints as required.

When a remote process is stopped at a breakpoint, you can use Visual Studio .NET s debugging tools to view variables, step through code, or execute commands as you would with a local process.



MCAD(s)MCSD Self-Paced Training Kit(c) Developing Web Applications With Microsoft Visual Basic. Net and Microsoft V[.  .. ]0-315
MCAD(s)MCSD Self-Paced Training Kit(c) Developing Web Applications With Microsoft Visual Basic. Net and Microsoft V[. .. ]0-315
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 118

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net