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

第 33 页

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

up around test cases. (Again, attributes are used to mark the appropriate methods that should be

used to initialize and clean up the test cases.)

The attributes for initializing and cleaning up around test cases are broken down into three levels:

those that apply to individual tests, those that apply to an entire test class, and those that apply to

an entire test project.

testinitialize and testcleanup

As their names suggest, the TestInitialize and TestCleanup attributes indicate methods that

should be run before and after each test case within a particular test class. These methods are

useful for allocating and subsequently freeing any resources that are needed by all test cases in the

test class.

classinitialize and classcleanup

Sometimes, instead of setting up and cleaning up after each test, it can be easier to ensure

that the environment is in the correct state at the beginning and end of running an entire test

class. Previously, we explained that test classes are a useful mechanism for grouping test cases;

this is where you put that knowledge to use. Test cases can be grouped into test classes that

contain one method marked with the ClassInitialize attribute and another marked with the

ClassCleanup attribute. These methods must both be marked as static, and the one marked with

ClassInitialize must take exactly one parameter that is of type UnitTesting.TestContext,

which is explained later in this chapter.

assemblyinitialize and assemblycleanup

The fi nal level of initialization and cleanup attributes is at the assembly, or project, level. Methods

that are intended to initialize the environment before running an entire test project, and cleaning up

after, can be marked with the AssemblyInitialize and AssemblyCleanup attributes, respectively.

Because these methods apply to any test case within the test project, only a single method can

be marked with each of these attributes. Like the class - level equivalents, these methods must

both be static and the one marked with AssemblyInitialize must take a parameter of type

UnitTesting.TestContext .

For both the assembly - level and class - level attributes, it is important to remember that even if only

one test case is run, the methods marked with these attributes will also be run.

When you use the Create Unit Test menu to generate a unit test, it generates

stubs for the TestInitialize , TestCleanup , ClassInitialize , and

ClassCleanup methods in a source code region that is commented out.

It is a good idea to put the methods marked with AssemblyInitialize and

AssemblyCleanup together into their own test class to make them easy to fi nd.

If there is more than one method marked with either of these attributes, then

running any tests in the project results in a runtime error.

testinG context

When you are writing test cases, the testing engine can assist you in a number of ways, including

by managing sets of data so you can run a test case with a range of data, and by enabling you

to output additional information for the test case to aid in debugging. This functionality is

available through the TestContext object that is generated within a test class and passed into the

AssemblyInitialize and ClassInitialize methods.

data

The CurrentStatusTest method generated in the fi rst section of this chapter tested only a single

path through the CurrentStatus property. To fully test this method, you could have written

additional statements and assertions to set up and test the Subscription object. However, this

process is fairly repetitive and would need to be updated if you ever changed the structure of the

CurrentStatus property. An alternative is to provide a DataSource for the CurrentStatusTest

Testing Context . 207

208 .

chaPter 11 uniT TeSTing

method whereby each row of data tests a different path through the property. To add appropriate

data to this method, use the following process:

1 Create a local SQL CE database and database table to store the various test data. In this

case, create a database called LoadTest with a table called Subscription_CurrentStatus.

The table has an Identity bigint column called Id, a nullable datetime column called

PaidUp, and an nvarchar(20) column called Status.

2 Add appropriate data values to the table to cover all paths

through the code. Test values for the CurrentStatus

property are shown in Figure 11-7.

3 Select the appropriate test case in the Test View window

and open the Properties window. Select the Data

Connection String property and click the ellipsis button

to open the Connection Properties dialog.

fiGure 11-7

4 Use the Connection Properties dialog to connect to the database created in Step 1. You

should see a connection string similar to the following:

data source=|DataDirectory|\LoadTest.sdf

5 If the connection string is valid, a drop-down box appears when you select the DataTable

property, enabling you to select the database table you created in Step 1.

6 To open the test case in the main window, return to the Test View window and select Open

Test from the right-click context menu for the test case. Notice that a DataSource attribute

has been added to the test case. This attribute is used by the testing engine to load the

appropriate data from the specified table. This data is then exposed to the test case through

the TestContext object.

If you are using a SQL Server CE database, you’ll also get a DeploymentItem

attribute added by default. This ensures that the database will be copied if the

test assembly is deployed to another location.

7 Modify the test case to access data from the TestContext object and use the data to drive

the test case, which gives you the following CurrentStatusTest method:

Vb

<DataSource(“System.Data.SqlServerCe.3.5”, _

“data source=|DataDirectory|\LoadTest.sdf”, _

“Subscription_CurrentStatus”, DataAccessMethod.Sequential)> _

<DeploymentItem(“SubscriptionTests\LoadTest.sdf”)> _

<TestMethod()>_

Public Sub CurrentStatusDataTest()

Dim target As Subscription = New Subscription

Testing Context .

209

If Not IsDBNull(Me.TestContext.DataRow.Item(“PaidUp”)) Then

target.PaidUpTo = CType(Me.TestContext.DataRow.Item(“PaidUp”), Date)

End If

Dim val As Subscription.Status = _

CType([Enum].Parse(GetType(Subscription.Status), _

CStr(Me.TestContext.DataRow.Item(“Status”))), Subscription.Status)

Assert.AreEqual(val, target.CurrentStatus, _

“Subscripiton.CurrentStatus was not set correctly.”)

End Sub

Code snippet SubscriptionTests\SubscriptionTest.vb

c#

[DataSource(“System.Data.SqlServerCe.3.5”,

“data source=|DataDirectory|\\LoadTests.sdf”,

“Subscription_CurrentStatus”,

DataAccessMethod.Sequential)]

[DeploymentItem(“SubscriptionTests\\LoadTests.sdf“)]

[TestMethod()]

public void CurrentStatusDataTest()

{

var target = new Subscription();

var date = this.TestContext.DataRow[“PaidUp“] as DateTime?;

if (date != null)

{

target.PaidUpTo = date;

}

var val = Enum.Parse(typeof(Subscription.Status),

this.TestContext.DataRow[“Status“] as string);

Assert.AreEqual(val, target.CurrentStatus,

“Subscription.CurrentStatus was not set correctly.”);

}

Code snippet SubscriptionTests\SubscriptionTest.cs

When this test case is executed, the CurrentStatusTest method is executed four times (once for

each row of data in the database table). Each time it is executed, a DataRow object is retrieved

and exposed to the test method via the TestContext.DataRow property. If the logic within the

CurrentStatus property changes, you can add a new row to the Subscription_CurrentStatus

table to test any code paths that may have been created.

Before moving on, take one last look at the DataSource attribute that was applied to the

CurrentStatusTest. This attribute takes four arguments, the first three of which are

used to determine which DataTable needs to be extracted. The remaining argument is a

DataAccessMethod enumeration, which determines the order in which rows are returned from the

DataTable. By default, this is Sequential, but it can be changed to Random so the order is different

every time the test is run. This is particularly important when the data is representative of end user

data but does not have to be processed in any particular order.

210 . chaPter 11 uniT TeSTing

writing test output

Writing unit tests is all about automating the process of testing an application. Because of this,

these test cases can be executed as part of a build process, perhaps even on a remote computer. This

means that the normal output windows, such as the console, are not a suitable place for outputting

test - related information. Clearly, you also don ’ t want test - related information interspersed

throughout the debugging or trace information being generated by the application. For this reason,

there is a separate channel for writing test - related information so it can be viewed alongside the test

results.

The TestContext object exposes a WriteLine method that takes a String and a series of String.

Format arguments that can be used to output information to the results for a particular test. For

example, adding the following line to the CurrentStatusDataTest method generates additional

information with the test results:

Vb

TestContext.WriteLine( “ No exceptions thrown for test id {0} ” , _

CInt(Me.TestContext.DataRow.Item(0)))

Code snippet SubscriptionTests\SubscriptionTest.vb

c#

TestContext.WriteLine( “ No exceptions thrown for test id {0} ” ,

this.TestContext.DataRow[0]);

Code snippet SubscriptionTests\SubscriptionTest.cs

Data - driven tests are not just limited to database tables; they can be driven by

Excel spreadsheets or even from Comma - Separated Values (CSV) fi les.

Although you should use the TestContext.WriteLine method to capture details

about your test executions, the Visual Studio test tools will collect anything

written to the standard error and standard output streams and add that data to

the Test Results window.

After the test run is completed, the Test Results window is displayed, listing all the test cases that

were executed in the test run along with their results. The Test Results Details window, shown in

advanced Unit Testing .

211

Figure 11-8, displays any additional information that was

outputted by the test case. You can view this window by

double-clicking the test case in the Test Results window.

In Figure 11-8, you can see in the Additional Information

section the output from the WriteLine method you added to

the test method. Although you added only one line to the test

method, the WriteLine method was executed for each row

in the database table. The Data Driven Test Results section

of Figure 11-8 provides more information about each of the

test passes, with a row for each row in the table. Your results

may differ from those shown in Figure 11-8, depending on

the code you have in your Subscription class.

adVanced unit testinG

Up until now, you have seen how to write and execute unit tests. This section goes on to examine

how you can add custom properties to a test case, and how you can use the same framework to test

private methods and properties.

custom Properties

The testing framework provides a number of test attributes that you can apply to a method

to record additional information about a test case. This information can be edited via the

Properties window and updates the appropriate attributes on the test method. At times you

might want to drive your test methods by specifying your own properties, which can also be

set using the Properties window. To do this, add TestProperty attributes to the test method.

For example, the following code adds two attributes to the test method to enable you to specify

an arbitrary date and an expected status. This might be convenient for ad hoc testing using the

Test View and Properties window:

Vb

<TestMethod()>

<TestProperty(“SpecialDate”, “1/1/2008”)>

<TestProperty(“SpecialStatus”, “Suspended”)>

Public Sub SpecialCurrentStatusTest()

Dim target As New Subscription

target.PaidUpTo = CType(Me.TestContext.Properties.Item(“SpecialDate”), _

Date)

Dim val As Subscription.Status = _

[Enum].Parse(GetType(Subscription.Status), _

CStr(Me.TestContext.Properties.Item(“SpecialStatus”)))

Assert.AreEqual(val, target.CurrentStatus, _

fiGure 11-8

212 .

chaPter 11 uniT TeSTing

“Correct status not set for Paidup date {0}”, target.PaidUpTo)

End Sub

Code snippet SubscriptionTests\SubscriptionTest.vb

c#

[TestMethod]

[TestProperty( “ SpecialDate ” , “ 1/1/2008 “ )]

[TestProperty( “ SpecialStatus ” , “ Suspended “ )]

public void SpecialCurrentStatusTest()

{

var target = new Subscription();

target.PaidUpTo = this.TestContext.Properties[ “ SpecialDate “ ] as DateTime?;

var val = Enum.Parse(typeof(Subscription.Status),

this.TestContext.Properties[ “ SpecialStatus “ ] as string);

Assert.AreEqual(val, target.CurrentStatus,

“ Correct status not set for Paidup date {0} ” , target.PaidUpTo);

}

Code snippet SubscriptionTests\SubscriptionTest.cs

By using the Test View to navigate to this test case and accessing

the Properties window, you can see that this code generates two

additional properties, SpecialDate and SpecialStatus, as

shown in Figure 11-9.

You can use the Properties window to adjust the SpecialDate

and SpecialStatus values. Unfortunately, the limitation here is

that there is no way to specify the data type for the values. As a

result, the property grid displays and enables edits as if they were

String data types.

fiGure 11-9

In the previous version of Visual Studio the TestContext.Properties

dictionary was not automatically filled in and you had to do this by hand in your

TestInitialize method. In Visual Studio 2010 this is all handled for you.

advanced Unit Testing .

213

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