饭饭TXT > 学习管理 > 《Visual Studio 2010 高级编程(英文出书版)》作者:Nick Randolph/等【完结】 > [Visual.Studio.2010.高级编程].Professional.Visual.Studio.2010.txt

第 34 页

作者:Nick Randolph/等 当前章节:15440 字 更新时间:2026-6-18 14:51

testing Private Members

One of the selling points of unit testing is that it is particularly effective for testing the internals

of your class to ensure that they function correctly. The assumption here is that if each of your

components works in isolation, there is a better chance that they will work together correctly; and

in fact, you can use unit testing to test classes working together. However, you might be wondering

how well the unit-testing framework handles testing private methods.

One of the features of the .NET Framework is the capability to reflect over any type that has been

loaded into memory and to execute any member regardless of its accessibility. This functionality

does come at a performance cost, because the reflection calls obviously include an additional level

of redirection, which can prove costly if done frequently. Nonetheless, for testing, reflection enables

you to call into the inner workings of a class and not worry about the potential performance

penalties for making those calls.

The other, more significant issue with using reflection to access non-public members of a class

is that the code to do so is somewhat messy. Fortunately, Visual Studio 2010 does a very good

job of generating a wrapper class that makes testing even private methods easy. To show this,

return to the CurrentStatus property, change its access from public to private, and rename it

PrivateCurrentStatus. Then regenerate the unit test for this property as you did earlier.

The following code snippet is the new unit-test method that is generated:

Vb

<TestMethod(), _

DeploymentItem(“Subscriptions.dll“)> _

Public Sub PrivateCurrentStatusTest()

Dim target As Subscription_Accessor = New Subscription_Accessor()

‘ TODO: Initialize to an appropriate value

Dim actual As Subscription.Status

actual = target.PrivateCurrentStatus

Assert.Inconclusive(“Verify the correctness of this test method.”)

End Sub

Code snippet SubscriptionTests\SubscriptionTest.vb

c#

[TestMethod()]

[DeploymentItem(“Subscriptions.dll“)]

public void PrivateCurrentStatusTest()

{

Subscription_Accessor target = new Subscription_Accessor();

Subscription.Status actual;

actual = target.PrivateCurrentStatus;

Assert.Inconclusive(“Verify the correctness of this test method.”);

}

Code snippet SubscriptionTests\SubscriptionTest.cs

214 .

chaPter 11 uniT TeSTing

As you can see, the preceding example uses an instance of a new Subscription_Accessor class to

access the PrivateCurrentStatus property. This is a class that was auto-generated and compiled

into a new assembly by Visual Studio. A new file was also added to the test project with the

.accessor extension, which is what causes Visual Studio to create the new accessor classes.

You can add a private accessor class to a test project without generating a unit test. To do this, open

the class that you want a private accessor for and select Create Private Accessor from the context

menu of the editor.

You don’t need to create a private accessor for every class in a project

individually. Each .accessor file actually relates of a single project and creates an

accessor class for all of the classes in that project.

testinG code contracts

If you are using the new Code Contracts feature described in Chapter 13, then you might want to

write tests that verify the behavior of your contracts. The simplest way to do this is to open the

Code Contracts project properties page and uncheck the Assert on Contract Failure checkbox.

When you do this the Code Contracts API will raise exceptions instead of causing Assertion

failures. You can check for these exceptions with an ExpectedException attribute if you know

the type of exception to expect. By default, the Code Contracts tools generate the exceptions that

will be thrown and their type cannot be known at runtime. Many of the contract methods have an

overload which accepts an exception type as a generic parameter.

Here is a simple class which performs a mathematical operation on positive integers and a unit test

to check the case where a negative number is passed in.

Vb

Class Calculator

Public Function Factorial(ByVal n As Integer) As Integer

Contract.Requires(Of ArgumentOutOfRangeException)(n > = 0, “ n “ )

If n = 0 Then Return 1

Return n * Factorial(n -1)

End Function

End Class

< TestMethod(), ExpectedException(GetType(ArgumentOutOfRangeException)) >

Public Sub NegativeTest()

Dim generator As New Calculator()

Dim actual = generator.Factorial( - 1)

Assert.Fail( “ Contract not working “ )

End Sub

Code snippet CodeContracts1\CalculatorTests.vb

Testing Code Contracts .

215

c#

class Calculator

{

public int Factorial(int n)

{

Contract.Requires<ArgumentOutOfRangeException>(n >= 0, “n“);

if (n == 0) return 1;

return n * Factorial(n - 1);

}

}

[TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]

public void NegativeTest()

{

var generator = new Calculator();

var actual = generator.Factorial(-1);

Assert.Fail(“Contract not working“);

}

Code snippet CodeContracts1\CalculatorTests.cs

Although this method of testing Code Contracts works, it is not really recommended as it may

cover up errors in the code. A better option is to hook into the Code Contracts system and

override its default behavior from within the test project itself. You do this by registering for

the ContractFailed event on the static Contract class inside of an AssemblyInitialize

method. Inside of the event handler you tell the Code Contracts API that you have handled the

contract failure and that you would like to throw an appropriate exception.

Vb

<AssemblyInitialize()>

Public Shared Sub AssemblyInitialize(ByVal testContext As TestContext)

AddHandler Contract.ContractFailed, Sub(sender As Object,

e As ContractFailedEventArgs)

e.SetHandled()

e.SetUnwind()

End Sub

End Sub

<TestMethod(), ExpectedException(GetType(Exception), AllowDerivedTypes:=True)>

Public Sub NegativeTest()

Dim generator As New Calculator()

216 .

chaPter 11 uniT TeSTing

Dim actual = generator.Factorial( - 1)

Assert.Fail( “ Contract not working “ )

End Sub

Code snippet CodeContracts2\CalculatorTests.vb

c#

[AssemblyInitialize]

public static void AssemblyInitialize(TestContext testContext)

{

Contract.ContractFailed += (s, e) = >

{

e.SetHandled();

e.SetUnwind();

};

}

[TestMethod , ExpectedException(typeof(Exception), AllowDerivedTypes = true)]

public void NegativeTest()

{

var generator = new Calculator();

var actual = generator.Factorial( - 1);

Assert.Fail( “ Contract not working “ );

}

Code snippet CodeContracts2\CalculatorTests.cs

When Code Contracts are configured to cause Asserts, the intended exception

is lost, so the code sample checks for any subclass of Exception. The

actual exception that gets thrown is a System.Diagnostics.Contracts

.ContractException, which is private to the .NET Framework, so you can’t

detect it directly.

ManaGinG larGe nuMbers of tests

Visual Studio provides both the Test View window and the Test List Editor to display a list of all of

the tests in a solution. The Test View window, which was shown earlier in the chapter in Figure 11 - 2,

simply displays the unit tests in a fl at list. However, if you have hundreds, or even thousands, of unit

tests in your solution, trying to manage them with a fl at list will quickly become unwieldy.

The Test List Editor enables you to group and organize related tests into test lists. Because test lists

can contain both tests and other test lists, you can further organize your tests by creating a logical,

hierarchical structure. All the tests in a test list can then be executed together from within Visual

Studio, or via a command-line test utility.

summary .

217

You can open the Test List Editor from the

Test Windows menu, or you can double-click

the Visual Studio Test Metadata (.vsmdi) file

for the solution. Figure 11-10 shows the Test

List Editor for a solution with a number of

tests organized into a hierarchical structure

of related tests.

On the left in the Test List Editor window is

a hierarchical tree of test lists available for

the current solution. At the bottom of the tree

are two project lists, one showing all the test

cases (All Loaded Tests) and one showing those test cases that haven’t been put in a list (Tests Not

in a List). Under the Lists of Tests node are all the test lists created for the project.

To create a new test list, click Test . Create New Test List. Test cases can be dragged from any

existing list into the new list. Initially, this can be a little confusing because a test will be moved to

the new list and removed from its original list. To add a test case to multiple lists, either hold the

Ctrl key while dragging the test case or copy and paste the test case from the original list to the new

list.

After creating a test list, you can run the whole list by checking the box next to the list in the Test

Manager. The Run button executes all lists that are checked. Alternatively, you can run the list with

the debugger attached using the Debug Checked Tests menu item.

suMMary

This chapter described how you can use unit testing to ensure the correct functionality of your

code. The unit-testing framework within Visual Studio is quite comprehensive, enabling you to both

document and manage test cases.

You can fully exercise the testing framework using an appropriate data source to minimize the

repetitive code you have to write. You can also extend the framework to test all the inner workings

of your application.

Visual Studio Premium and Ultimate contain even more functionality for testing, including the

ability to track and report on code coverage, and support for load and web application testing.

Chapter 56 provides more detail on these advanced testing capabilities.

fiGure 11-10

12

Documentation with XMl

Comments

what’s in this chaPter?

.

Adding inline documentation to your code using XML comments

.

Using the GhostDoc Visual Studio Add-In to automatically generate

XML comments

.

Producing stand-alone documentation from XML comments with

Sandcastle

.

Using Task List comments to keep track of pending coding tasks

and other things to do

Documentation is a critical, and often overlooked, feature of the development process.

Without documentation, other programmers, code reviewers, and project managers have

a more difficult time analyzing the purpose and implementation of code. You can even

have problems with your own code once it becomes complex, and having good internal

documentation can aid in the development process.

XML comments are a way of providing that internal documentation for your code without

having to go through the process of manually creating and maintaining a separate document.

Instead, as you write your code, you include metadata at the top of every definition to explain

the intent of your code. Once the information has been included in your code, it can be

consumed by Visual Studio to provide Object Browser and IntelliSense information.

GhostDoc is a free third-party add-in for Visual Studio that can automatically insert an XML

comment block for a class or member.

Sandcastle is a set of tools that act as a documentation compiler. These tools can be used

to easily create standalone documentation in Microsoft compiled HTML help or Microsoft

Help 2 format from the XML comments you have added to your code.

220 .

chaPter 12 documenTATion WiTh xml commenTS

inline coMMentinG

All programming languages supported by Visual Studio provide a method for adding inline

documentation. By default, all inline comments are highlighted in green.

C# supports both single line comments and comment blocks. Single line comments are denoted by

// at the beginning of the comment. Block comments typically span multiple lines and are opened

by /* and closed off by */, as shown in the following code:

c#

// Calculate the factorial of an integer

public int Factorial(int number)

{

/* This function calculates a factorial using an

* iterative approach.

*/

int intermediateResult = 1;

for (int factor = 2; factor <= number; factor++)

{

intermediateResult = intermediateResult * factor;

}

return intermediateResult; //The calculated factorial

}

VB just uses a single quote character to denote anything following it to be a comment, as shown in

the following code:

Vb

' Calculate the factorial of an integer

Public Function Factorial(ByVal number As Integer) As Integer

' This function calculates a factorial using an

' iterative approach.

'

Dim intermediateResult As Integer = 1

For factor As Integer = 2 To number

intermediateResult = intermediateResult * factor

Next

Return intermediateResult 'The calculated factorial

End Function

xMl coMMents

XML comments are specialized comments that you include in your code. When the project goes

through the build process, Visual Studio can optionally include a step to generate an XML file based

on these comments to provide information about user-defined types such as classes and individual

members of a class (user defined or not), including events, functions, and properties.

XMl Comments .

221

XML comments can contain any combination of XML and HTML tags. Visual Studio performs

special processing on a particular set of predefined tags, as you see throughout the bulk of this

chapter. Any other tags are included in the generated documentation file as is.

adding xMl comments

XML comments are added immediately before the property, method, or class definition they are

associated with. Visual Studio automatically adds an XML comment block when you type the

目录
设置
设置
阅读主题
字体风格
雅黑 宋体 楷书 卡通
字体大小
适中 偏大 超大
保存设置
恢复默认
手机
手机阅读
扫码获取链接,使用浏览器打开
书架同步,随时随地,手机阅读
首 页 < 上一章 章节列表 下一章 > 尾 页