您的位置:首页 > 编程语言

使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码(详解)

2008-08-20 09:15 671 查看
[原英文链接]:

Visual Studio 2005 Technical Articles
Author:Scott Dockendorf

Telligent Systems, Inc.
标题:Unit Testing and Generating Source Code for Unit Test Frameworks Using Visual Studio 2005 Team System
链接:http://msdn.microsoft.com/en-us/library/ms364064.aspx

简介

随着业务的革新和发展,运行它们的系统也需要进行更新。随业务的发展、革新以及与合作伙伴、客户和供应商的结合,这些系统将在复杂性方面持续扩增。

这种复杂性迫使 IT 的领导者们在开发过程中(即,在实现之前)确保质量。有一种方法可使开发人员减少进入 QA 环节的故障数量,即,针对自定义代码严格执行自动化单元测试。在开发过程中强制使用自动化单元测试可为团队成员提供有关如何使用自定义代码的示例(这些示例易于使用并自行记录)。

使用结构化、自动化单元测试面临的挑战之一是完成这些任务所需的代码总数。(测试代码需要使用大量代码!)代码生成的概念(简单定义为“创建软件的软件”)正随着时间的快速推移而逐渐深入到团队 IT 开发之中。有些人认为代码生成有助于缩短“推向市场”策略的时间,强制内部标准/协定,并促进开发过程。

Microsoft 认识到这一需要后提供了一个功能丰富、带有下一代开发平台 Visual Studio 2005 Team System (VSTS) 的代码生成引擎。本文提供针对单元测试代码生成的循序渐进的指导,并深入探讨如何在用例中使用。

重新思考单元测试

请考虑以下情况:您负责为公司生成下一代系统,同时您是较大的开发团队中的一员。您是 UI 开发人员,负责尽可能多地创建 Microsoft ASP.NET/Microsoft WinForms。您依赖“中间层”团队完成其中间层组件 — 这些组件用于执行数据库 CRUD (Create-Retrieve-Update-Delete) 以及与该系统中每个实体相关的业务规则。

经过几周的 UI 开发,您完成了窗体并且收到了中间层开发人员打算向您提交其类库的消息。表 1 提供一段对话示例,说明我们大多数人在开发过程中都会遇到的一些事情。

表 1. UI 开发人员和中间层开发人员间的示例对话
中间层:

“这些对象随时供您使用 — 为此,只需获取 OurSystemBL.dll 的最新版本。”

UI

“谢谢。您有供我们查看文档吗?”

中间层:

“哈哈!是的,当然有!我们花了很多时间编写它!请查看 Design Document — 噢,请等一等,它还没有完成……(不久之后即可完成!)”

UI

“您使用 XML 文档了吗?”

中间层:

“在构造函数中,但许多方法都不使用。”

UI

“显示如何创建、执行并删除对象的示例代码,怎么样?”

中间层:

“我已经附加了一个示例 WinForms 应用程序(从我的工作区),它应该能够提供一些您所需的内容……,虽然它不在 Microsoft Visual SourceSafe 中。”

在考虑如何进行这样有趣的项目之后,您打定了主意,决定检验中间层的单元测试套件。在深入钻研该代码之后,您注意到该窗体有两个未标记的文本框,以及三个标记为 button1button2button3 的按钮(幸运的话,它们将排列在窗体上)。

接下来,在查看与这些按钮相关的事件之后,您认识到这些代码都未经注释,并且数据变量都被命名为 x、y、z。如果幸运,您还会注意到 button1button2 执行该对象的 Save() 方法,而 button3 执行 Delete() 方法。执行时,您会接收到很多 System.Exception 错误,这是因为遗漏了很多配置设置。

这显然是一个特例,我希望多数开发团队不要进行这一试验,下面让我们看一下该方案中“单元测试”遇到的问题:

这种形式的单元测试代码不是结构化的:代码充斥到按钮单击事件中并且难以编译。

这种形式的单元测试代码记录得不太好。

这种形式的单元测试并不基于“已知”为好或坏的数据 — 它完全依赖于输入到那些未标记的文本框的内容。

单元测试代码不能自动重复,它基于输入的代码。

单元测试代码覆盖是未知的 — 用数据指示实际测试的代码量。

实现的详细信息不易于在团队成员间进行传播。

输入自动化单元测试

xUnit 框架在 1998 年作为 eXtreme 编程的核心概念引入。它提出了一个有效的机制,有助于开发人员将结构化、有效且自动的单元测试添加常规开发活动中。从那以后,该框架演化为针对自动化单元测试框架的实际标准。

创建自动化单元测试的用例

简单说,自动化单元测试是:

结构化的。

自行记录的。

自动且可重复的。

基于已知数据。

旨在测试积极和消极操作。

非常适合跨不同计算机的测试实现。

配置、实现和执行的示例。

xUnit 框架元素

表 2 分析 xUnit 框架以及对应于 Visual Studio 2005 Team System 的 Unit Testing Framework 等价物的基本概念。

表 2. 相应的 xUnit 框架和 VSTS Unit Testing Framework 概念
xUnit 框架概念VS 2005 等价物(参见下面的属性)描述
测试

TestMethod

简单说,这些是您的测试。测试预期结果的逻辑,并报告未取得结果(如果有)。请将它看作您的“方法”。

测试装置

TestClass

针对大量测试的一个逻辑分组。请将它看作您的“类”。

测试套件

测试列表 **

针对大量测试装置的一个逻辑分组。请将它看作您的“类库”。

注不需要一个属性。

测试运行器

VS 2005 VSTS Unit Testing Framework

GUI/Console 应用程序负责发现、执行和报告测试结果。Visual Studio 2005 Team System 将作为本文的测试运行器。

测试装置示例

请考虑以下针对 BankAccount 类的类关系图,以及一个示例测试装置 (BankAccountTests.cs)。

Code

/// <summary>

///DepositMoney (float) 的测试

///</summary>

[TestMethod()]

public void DepositMoneyTest()

{

float initialBalance = 500; // TODO: 初始化为适当的值

BankAccount target = new BankAccount(initialBalance);

float depositAmount = 10; // TODO: 初始化为适当的值

target.DepositMoney(depositAmount);

Assert.AreEqual(initialBalance + depositAmount, target.CurrentBalance, "Deposit Test: Deposit not applied correctly");

//Assert.Inconclusive("无法验证不返回值的方法。");

}

重新生成单元测试代码

好消息是,代码生成过程不会让您重写以前生成(和修改)的单元测试。使用 Visual Studio 2005 Team System 的 Beta 2 版本,代码生成选项提供一个启用/禁用创建已存在测试的复选框。如果选择它,而且该过程找到了一个具有相同名称的现有测试,则该过程将忽略该测试方法,并创建后续测试,从而将一个数字附加到该方法名的末尾。这通常在对象中使用重载的方法或构造函数时发生,或者当单击 Generate 按钮而不取消选定现有测试时发生。

自动化单元测试建议

虽然本节可以独立成文,但这里只是一些您在创建单元测试时可以采纳的基本建议。

设计彼此独立的单元测试,其中它们可以独立运行(由于可以通过测试 UI 随意选择或取消选定它们)。

不要只进行正面测试。请确保代码能够响应任何方案,包括发生意外时(资源不可用,数据库只读等)。

把自己当作一个 QA 人员,想象成一个测试人员,而不仅仅是一个开发人员。您花在设计单元测试上的时间将有助于减少日后解决故障所用的时间。请注意对象的几个小细节:数据如何在对象之间传输?谁使用它们?销毁对象容易吗?如果我“进行此操作”,将会发生什么?

跳出您自己的思维模式。尽可能多地对测试进行头脑风暴。当您完成时,回头查看您可能漏掉的内容。来自团队成员的请求反馈 — 例如,他们创建了什么其他类型的测试?其他人可能提供一个对熟悉自己代码的开发人员而言非常困难的观点。

代码覆盖。使用 VSTS 代码覆盖规范提供有关每个测试运行中实际执行多少代码的信息(代码的行数,占所有代码的百分比)。如果编码完成,并且通过了所有测试,但代码覆盖显示只执行了该逻辑的一小部分,那么您的测试真的成功了吗?高代码覆盖不一定意味着您具有一个完整的“测试”集,而未覆盖的代码通常非常适用于一个新的测试用例。

当生成单元测试时,要帮助其他人了解您的代码:

使用一个项目结构,该结构映射所测试程序集的结构。

每个程序集有一个相关的测试程序集。

每个类有一个相关的测试类。

在各自的测试方法中包含每个方法名(即,Load() 将有 PositiveLoadTest()NegativeLoadTest()PositiveScalarLoadTest() 等的测试方法)。

使用一致的命名协定,包括对象的属性和方法名。

此外,当其他所有测试都失败时,请进行调试。自动化单元测试应该有助于减少您用在调试器上的时间。但是,如果测试结果和代码覆盖无法提供测试失败的原因,那么您大可不必担心调试单元测试。从 Beta 2 版的 Visual Studio 2005 Team System 开始,开发人员可以使用 Test Manager 中的 Debug checked tests 选项调试他们的单元测试程序集。

小结

自动化单元测试为开发环节提供了一个结构化、自行纪录、高度便携且可重复的过程。如果在搜索现有程序集,或者如果开发环境需要在开始开发之前进行完整的设计,则请考虑使用内置到 Microsoft Visual Studio 2005 Team System 中的代码生成引擎。Visual Studio 2005 Team System 的单元测试代码生成功能可以为您节省宝贵的时间,而且有助于强制团队的开发标准和约定。通过生成用于自动化单元测试的基本内容,包括生成带有对象创建的测试方法、参数变量和基断言类,您应该能够顺利地在您的开发方法论中采用自动化单元测试。

作者简介

作为针对 telligent 系统的专业服务主管,Scott Dockendorf 擅长于用 .NET 提供高性能、可伸缩的应用程序。Scott 热衷于解决方案体系结构、安全开发,他通过标准和已通过验证的方法论帮助企业采用推荐的实践。Scott 是 .NET 社区的一个积极成员,他自愿作为 North Dallas .NET User Group 的程序主管。他还参加了面向本地 .NET 用户组的会议,而且是 INETA's International Academic Committee for Texas 的活跃分子。您可以通过他的电子邮件 (scottd@telligent.com) 或网络日记 (http://weblogs.asp.net/scottdockendorf) 与他联系。

转到原英文页面
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐