Microsoft Visual Studio 2005 Team System Web 测试简介

上一篇 / 下一篇  2007-10-17 14:15:21

  • 文件版本: V1.0
  • 开发商: 本站原创
  • 文件来源: 本地
  • 界面语言: 简体中文
  • 授权方式: 免费
  • 运行平台: Win9X/Win2000/WinXP
Microsoft Visual Studio 2005 Team System Web 测试简介
   


本文中将要测试的站点是个人网站。这是 Microsoft Visual Studio 2005 附带的向导创建的站点之一。创建站点的步骤如下:
1. 单击 File(文件)菜单,再单击 New Web Site(新建网站)。请注意,在 Visual Studio 2005 中,新建网站项目与其他新建项目选项位于不同的对话框中。
2. 选择 Personal Web Site Starter Kit(个人网站入门工具包),再选择编程语言。在本文中,我们将使用 Microsoft C#。
 
图 1:创建新网站
创建站点之后,创建新帐户。我们将手动创建新帐户,目的只是验证是否一切运行正常。稍后,我们将提供使用新帐户登录到站点的自动测试。
1. 单击 Website(网站),再单击 ASP.NET Configuration(ASP.NET 配置)来打开网站管理工具。
2. 单击 Security(安全)链接,再单击 Create User(创建用户)链接。
3. 输入测试用户的信息,选择 Administrators(管理员)角色,然后再单击 Create User(创建用户)。请注意,电子邮件地址的格式必须有效,并且密码必须是七个字符(至少包括一个非字母数字的字符)。
4. 创建帐户后,关闭 ASP.NET Configuration(ASP.NET 配置)网站。
在 Visual Studio 中,我们可以启动网站并使用新帐户登录,来验证是否一切运行正常。
默认情况下,Microsoft Internet Information Server (IIS) 不用于驻留站点。相反,Visual Studio 2005 启动 Microsoft ASP.NET Development Server,如图 2 中的系统任务栏图标所示。
 
图 2:ASP.NET Development Server 系统任务栏图标
ASP.NET Development Server 使用与 Web 项目名称对应的虚拟路径,随机选择开放端口并开始在该端口驻留站点。但是,端口可能在 Visual Studio 启动间更改,因此根据原始端口记录的任何测试都不再有效。为了避免这种情况,我们可以将该端口冻结为特定值:
1. 在 Visual Studio 中,通过按 F4 转到 Web 项目的 Properties(属性)窗口来获取端口号。请注意,这不是项目的 Property Pages(属性页)对话框,而是 Visual Studio 2005 中的固定窗口。Use Dynamic Ports(使用动态端口)的默认值为 True。
2. 要防止 Visual Studio 选择其他端口号,请将 Use Dynamic Ports(使用动态端口)选项更改为 False。
启动网站的另一种方法是直接运行 WebDev.WebServer.exe。这也提供指定驻留站点的端口号的方法。命令行如下。
WebDeb.WebServer /port:<端口号> /path:<物理路径> [/vpath:<虚拟路径>]
例如,我们可以使用下面的命令行启动个人网站。
start /B webdev.webserver.exe /port:4955
/path:"c:\documents and settings\MMichael\Local
Settings\Temp\HelloWorldWebSite"  /vpath:/HelloWorldWebSite
Start 确保命令返回,而不是等待它退出。
如果没有指定端口,则默认端口为 80,但如果 IIS 正在运行并使用同一端口,将会失败。 除了允许使用特定端口之外,WebDev.WebServer.exe 的重要性还体现在可以作为生成/测试脚本的一部分进行调用,而无需启动 Visual Studio 2005。
验证站点是否正在工作时,记录站点默认页的 URL(包括端口和虚拟目录)并关闭浏览器窗口。记录 Web 测试用例后,我们将即刻使用 URL。但是,我们需要测试项目,才能运行 Web 测试。
创建测试项目
创建测试项目,方法与创建任意 VSTS 单元测试项目相同。创建的步骤如下。为了成功记录测试,网站必须处于运行状态。
1. 右键单击解决方案,然后单击 Add Project(添加项目)。
2. 选择编程语言,再选择测试节点。
3. 将项目命名为 HelloWorldWebSite.Test。
 
图 3:创建测试项目
因为我们已经创建了初始网站,所以我们可以记录该站点的活动。
创建定义为 Web 测试项目的项目没有特别之处。相反,添加到该项目的测试文件是专用的 Web 测试文件,而不是其他测试文件类型(单元测试、负载测试、手动测试、一般测试等)。因此,下一步是添加 Web 测试用例。由于我们不打算使用添加到测试项目的任何其他类型的测试文件,因此可以将它们删除。
1. 右键单击该项目,然后单击 Add(添加),再单击 Web Test(Web 测试)。将打开带有 Web Test Recorder(Web 测试记录器)资源管理器栏的浏览器。
 
图 4:记录 Web 测试用例
2. 在地址栏中,输入个人网站的 URL,包括 ASP.NET Development Server 选择的端口。像输入的任何其他 URL 一样,对此位置的浏览将被记录在 Web Test Recorder(Web 测试记录器)资源管理器栏中。
3. 输入前面添加的用户名和密码。单击 Login(登录)按钮后,将会记录另一个条目和窗体发布参数。这样,在测试运行时,将会自动发送相同的数据。甚至单击按钮的 X 坐标和 Y 坐标也将作为测试的一部分保存,因为这些坐标也已作为请求的一部分提交了。
4. 添加其他测试步骤,方法是注销站点,然后使用无效凭据重试登录。
5. 记录所需的测试后,关闭浏览器窗口并保存测试。
此时,项目将自动包括 Web 测试用例文件和记录的每个请求。
 
图 5:查看记录的 Web 测试用例
选择 WebTest 树中的任意节点都可以修改 Properties(属性)窗口中的数据。
我们还可以使用事务将请求编组在一起。注意,不要将术语“事务”与编程概念(其中事务的状态为都提交或都未提交)混淆在一起。在 Web 测试用例中,事务仅将操作封装到稍后可以使用代码枚举的组中。此外,报告负载(如每秒的事务量)时也使用事务。
可以向每个请求和整个 Web 测试用例添加的另一个调整是注释。方法是右键单击某个请求,然后单击 Insert Comment(插入注释)。注释显示在请求之间,提供编制已提交数据的文件和任何可以添加的响应验证的方法。
运行 Web 测试用例
记录测试之后,我们准备开始执行该测试。若要执行项目中的所有测试,只需运行该项目。这将打开测试结果窗口并在每个测试运行时将其标记为挂起,执行完毕后,标记为通过/失败。从 Test Manager(测试管理器)窗口和 Test View(测试查看)窗口也可以选择和执行测试。
 
图 6:选择和执行测试
各个 Web 测试文件(测试用例或测试硬件)也可以运行,方法是打开这些文件,然后单击 Run(运行)按钮。
 
图 7:运行设置对话框
请求也可以使用标准身份验证方法提供用于登录到目标站点的凭据。使用凭据的对话框可以从数据源加载登录数据。
每个请求结果都被保存,选择每个请求可以浏览其详细信息,查看结果页的 HTML 或原始请求/响应文本。
 
图 8:测试结果查看器
在测试执行过程中,Web 测试引擎会检查页上的所有 URL,以验证它们是否为有效的链接。这些链接显示为请求下的子节点,并且每个链接都显示请求返回到该 URL 的 HTTP 状态。
请求规则
尽管检查响应页上的有效超链接很有用,但这对于验证页是否运行正常是不够的。例如,在输入有效凭据时,Web 测试需要验证登录是否成功。同样,在凭据无效时,我们需要检查页上是否显示了相应的错误信息。为了提供支持,每个 Web 请求可以包括提取规则和验证规则。
提取规则
提取规则捕获响应值,以便以后可以在请求中使用该值。提取规则提供集中响应中特定数据项的方法,而不是手动分析整个 HTTP 响应。然后,可以验证提取的数据项或在后续回发中再次使用。在登录时,记录的示例自动添加了提取规则。
 
图 9:请求之间的提取规则可以相互链接
该规则是 ExtractHiddenFields 规则,其数据在 Web 测试用例的第二个请求中回发。在后续请求期间,此数据被提交回页的隐藏字段中。其他提取规则选项是 ExtractAttributeValue、ExtractHttpHeader、ExtractRegularExpression 和 ExtractText。提取规则可以根据需要手动添加和自定义,而不是依赖于自动记录的隐藏字段数据。
验证规则
测试编写器使用验证规则检查整个 HTTP 响应并验证该响应是否正确。例如,有效凭据应该使 LOGOUT 超链接和“欢迎 <用户名>”显示在 HTML 响应中。应该添加用于检查响应中这些项的验证规则。验证规则验证此文本是否显示在响应正文中。
 
图 10:检查 LOGOUT 的验证规则
如果特定规则失败,则请求将标记为失败,并且 Details(详细信息)选项卡将提供失败的原因。
 
图 11:显示验证和提取规则结果
此类型的验证规则是 ValidationRuleFindText,用于搜索整个响应正文,查找指定文本。为了处理复杂的搜索,支持在 ValidationRuleFindText 中使用正则表达式。
除了 ValidationRuleFindText 之外,内置验证规则还包括 ValidationRuleRequestTime、ValidationRuleRequiredAttributeValue 和 ValidationRuleRequiredTag。
将测试数据绑定到数据源
验证规则和提取规则均在每个虚拟节点的 Properties(属性)窗口提供文本输入。但是,使 Visual Studio Web 测试功能强大的真正原因是可以从数据库中提取文本。以登录为例,这意味着我们可以定义新用户并确保不允许使用不符合指定强密码要求的弱密码集合。
若要使用数据源进行测试,请单击 Web测试工具栏上的 Add Data Source(添加数据源)按钮。在随后打开的对话框中,指定 OLE DB 访问接口,或许使用也能添加到测试项目中的 *.mdf 文件。在服务器资源管理器中打开数据库后,定义将包含所需测试数据的表。在图 12 中,我们使用具有主键列、用户名列和密码列的 TestUser 表。
 
图 12:将参数指定给数据源
使用数据源配置测试之后,必须返回到 Edit Run Settings(编辑运行设置)对话框(图 7),并将运行计数更改为 one run per data source row(每个数据源行运行一次)。这样,将对新配置数据源中的每一行重复该测试,并且在每次运行期间,与数据源关联的参数将被指定为特定行的列中的值。
生成 Web 测试代码
利用我们目前考虑到的所有功能不需要编写任何代码。但是,附加 Web 测试自定义需要使用代码。处理测试中的构造(如循环和分支)或调用其他 Web 测试时都必须使用代码。VSTS Web 测试提供了生成特定测试用例的代码的工具。Generate Code(生成代码)按钮包含在 Web 测试用例的工具栏中。单击此按钮后,系统会提示您输入测试名称,然后生成与 Web 用例对应的 CS/VB 文件。生成的代码包括可以添加的每个验证和提取规则。另外,会将数据(如视图状态)作为 Web 请求的一部分进行设置和传递。上述测试用例的生成代码如下所示。
namespace HelloWorldWebSite.Test
{
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.QualityTools.WebTestFramework;
using Microsoft.VisualStudio.QualityTools.WebTestFramework.Rules;


public class LogonCoded :WebTest
  {

public LogonCoded()
      {
      }

public override IEnumerator<WebTestRequest> GetRequestEnumerator()
      {
WebTestRequest request1 =
new WebTestRequest("http://localhost:4955/HelloWorldWebSite");
request1.ThinkTime = 17;
ExtractHiddenFields rule1 = new ExtractHiddenFields();
rule1.ContextParameterName = "1";
request1.ExtractValues +=
new EventHandler<ExtractionEventArgs>(rule1.Extract);
yield return request1;

// 重定向到默认页面。

WebTestRequest request2 =
new WebTestRequest(
"http://localhost:4955/HelloWorldWebSite/default.aspx");
request2.ThinkTime = 7;
request2.Method = "POST";
BindHiddenFields request2BindHiddenFields =
new.BindHiddenFields();
request2BindHiddenFields.HiddenFieldGroup = "1";
request2.PreRequest +=
new EventHandler<PreRequestEventArgs>(
request2BindHiddenFields.PreRequest);
FormPostHttpBody request2Body = new FormPostHttpBody();
request2Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$UserName", "Administrator");
request2Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$Password", "G00d-P@ssw0rd");
request2Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$LoginButton.x", "45");
request2Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$LoginButton.y", "5");
request2.Body = request2Body;
ValidationRuleFindText rule2 = new ValidationRuleFindText();
rule2.FindText = "Administrator";
rule2.PassIfTextFound = true;
request2.ValidateResponse +=
new EventHandler<ValidationEventArgs>(rule2.Validate);
ValidationRuleFindText rule3 = new ValidationRuleFindText();
rule3.FindText = "LOGOUT";
rule3.PassIfTextFound = true;
rule3.IgnoreCase = true;
request2.ValidateResponse +=
new EventHandler<ValidationEventArgs>(rule3.Validate);
ValidationRuleRequestTime rule4 =
new ValidationRuleRequestTime();
rule4.MaxRequestTime = 500;
request2.ValidateResponse +=
new EventHandler<ValidationEventArgs>(rule4.Validate);
yield return request2;

// 使用有效凭据登录并验证成功的登录。

WebTestRequest request3 =
new WebTestRequest(
"http://localhost:4955/HelloWorldWebSite/default.aspx");
request3.ThinkTime = 17;
request3.Method = "POST";
FormPostHttpBody request3Body = new FormPostHttpBody();
request3Body.FormPostParameters.Add(
"__EVENTTARGET", "ctl00$LoginStatus1$ctl00");
request3Body.FormPostParameters.Add(
"__EVENTARGUMENT", "");
request3Body.FormPostParameters.Add(
"__VIEWSTATE", ...);
request3.Body = request3Body;
ExtractHiddenFields rule5 = new ExtractHiddenFields();
rule5.ContextParameterName = "1";
request3.ExtractValues +=
new EventHandler<ExtractionEventArgs>(rule5.Extract);
yield return request3;

// 注销

WebTestRequest request4 =
new WebTestRequest(
"http://localhost:4955/HelloWorldWebSite/default.aspx");
request4.Method = "POST";
BindHiddenFields request4BindHiddenFields =
new BindHiddenFields();
request4BindHiddenFields.HiddenFieldGroup = "1";
request4.PreRequest +=
new EventHandler<PreRequestEventArgs>(
request4BindHiddenFields.PreRequest);
FormPostHttpBody request4Body = new FormPostHttpBody();
request4Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$UserName", "IMontoya");
request4Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$Password", "bad-password");
request4Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$LoginButton.x", "64");
request4Body.FormPostParameters.Add(
"ctl00$Main$LoginArea$Login1$LoginButton.y", "10");
request4.Body = request4Body;
ValidationRuleFindText rule6 = new ValidationRuleFindText();
rule6.FindText = "LOGIN";
rule6.IgnoreCase = true;
rule6.PassIfTextFound = true;
request4.ValidateResponse +=
new EventHandler<ValidationEventArgs>(rule6.Validate);
ValidationRuleFindText rule7 = new ValidationRuleFindText();
rule7.FindText = "LOGOUT";
rule7.IgnoreCase = true;
rule7.PassIfTextFound = false;
request4.ValidateResponse +=
new EventHandler<ValidationEventArgs>(rule7.Validate);
yield return request4;

// 使用无效凭据登录并验证
// 失败的登录。
      }
  }
}
对于 C# 项目,使用了新的 C# 2.0 迭代程序:在每个请求后,代码会通过分隔请求的 yield return 语句返回下一个 Web 请求。
显然,在不打算自定义代码的情况下不需要生成代码,但如果这样做,可以为自定义特定 Web 测试用例(甚至带有少量重构的多个用例)提供一个良好的开端。
扩展 VSTS Web 测试
可用请求规则和编写生成的 Web 测试的自定义代码的功能适用于最常见的 Web 测试方案。但是,有时通过创建自定义验证和提取规则或通过对自定义 Web 测试插件进行编码来扩展 VSTS Web 测试会更加合理。这样的扩展必须在单独的程序集中定义,但可以在多个 Web 测试项目中使用。新的 Web 测试扩展程序集经定义后,可能会被 Web 测试项目引用,因此会显示在 Add(添加)对话框的请求选择中。
可用的对话框不仅适用于验证规则和提取规则,还适用于请求插件和测试插件。请求回调可以分别添加到每个请求中,根据请求执行前截取和后截取。测试回调对整个请求集运行前截取和后截取代码。在测试用例开始时初始调用前截取和后截取代码,然后在同一测试用例结束时再次调用。例如,考虑定义一个检查测试中的所有网页是否都符合 XHTML 的回调,或设置用于每个 Web 请求的 cookie 的回调。如果执行此验证的插件是请求回调,那么该插件可以分别添加到测试的每个请求中。回调也可以是在预测试执行期间挂接了对所有请求的验证的测试回调。创建 Web 测试回调的步骤如下:
1. 创建名为 WebTestFramework 的新类库项目。
2. 向 Microsoft.VisualStudio.QualityTools.UnitTestFramework 和 Microsoft.VisualStudio.QualityTools.WebTestFramework 添加引用。
3. 将从 Microsoft.VisualStudio.QualityTools.WebTestFramework.WebTestPlugin 派生的新类的名称定义为 ValidationRuleXHTML。
4. 执行抽象方法 PreWebTest() 和 PostWebTest()。
最后这两个方法符合标准事件签名,sender 为第一个参数,PreWebTestEventArgs/PostWebTestEventArgs 为第二个参数。以下是示例 Web 测试插件类,说明了如何创建 XHTML 验证程序。
namespace WebTestFramework
{
public class ValidationRuleXHTML :
Microsoft.VisualStudio.QualityTools.WebTestFramework.WebTestPlugin
    {
public override void PostWebTest(
object sender, PostWebTestEventArgs args)
        {
// 不需要 PostWebTest 处理。已实现
// 因为它是基类中的抽象方法。
        }

void WebTestPostRequest(
object sender, PostRequestEventArgs args)
        {
// 1. 从 args.Response.ResponseBody 检索
//    ResponseBody。
// 2. 验证 ResponseBody。
// 3. 如果 HTML 是无效 XHTML,则引发异常。 
//    确保尽可能将异常信息设置为
//    描述信息。
        }

public override void PreWebTest(
object sender, PreWebTestEventArgs args)
        {
// 为测试中的每个 PostRequest 注册
// 事件回调。
args.WebTest.PostRequest += WebTestPostRequest;
        }
    }
}
在本示例中,PreWebTest() 为 PostRequest 事件注册委托 (WebTestPostRequest())。这样,每次 Web 测试引擎处理请求时,请求都将调用注册的委托侦听器。委托的 PostRequestEventArgs 参数包括 WebTest 属性,用于提供 stringResponseBody 属性。当检查 XHTML 时,最后这个属性将提供对响应正文的所需访问。对于 XML 验证程序之类的对象,请注意一点,那就是当运行负载测试时,它们会占用大部分负载生成容量。验证测试需要大量资源,在大量使用时应保留在负载测试方案中未使用的单元测试中。
图 13 中显示了创建 Web 测试插件的对象模型。
 
图 13:Web 测试插件对象模型
此模型概述了在 Web 测试插件中可访问的功能以及由此在 Web 测试插件中可提供的验证。使用前/后 Web 测试方法,我们可以访问有关整个 Web 测试用例的信息(例如,与测试关联的数据)以及凭据信息。最重要的可能是,这些方法提供了对前/后请求事件的访问,使我们可以对每个请求上挂接 XHTML 验证程序回调。
前请求和后请求事件签名均通过各自的 EventArgs 类提供了对 WebTest 对象的访问,还提供了对 WebTestRequest 对象的访问,用于访问有关请求自身的详细信息。PostRequestEventArgs 属性包括对 WebTestResponse 对象的访问,从而能够检查从请求返回的数据。
前面,我们提到过可以自定义验证和提取规则。要创建验证和提取规则,我们要从 Microsoft.VisualStudio.QualityTools.WebTestFramework.Validation 和 Microsoft.VisualStudio.QualityTools.WebTestFramework.ExtractionRule 派生,而不是从 Microsoft.VisualStudio.QualityTools.WebTestFramework.WebTestPlugin 或 Microsoft.VisualStudio.QualityTools.WebTestFramework.WebTestRequestPlugin 派生。图 14 中显示了规则基类的概述。
 
图 14:使用自定义提取规则和验证规则扩展
ValidationEventArgs 类和 ExtractionEventArgs 类分别是规则的 Validate() 方法和 Extract() 方法的类型参数。将这些事件参数与各个请求一起使用时,可以直接访问与请求及其插件对应部分相关的数据,但与请求的关系更为密切。此外,IsValid 之类的属性提供了一个报告错误的方法,该方法比前面介绍的 Web 测试插件的引发异常机制更好。但是,如前面所述,规则必须插入单个请求,而不是整套测试。插件方法的另一个优点是它可以截取请求本身 — 不仅是在生成请求和返回响应后调用。总之,请使用验证规则和提取规则,除非提供所有请求的验证或在将请求提交到服务器之前需要截取该请求。
浏览器用户界面测试
VSTS Web 测试功能不支持通过 Javascrīpt、ActiveX 控件和小程序的 Web 请求。同样,VSTS Web 测试也不是一种用户界面 (UI)测试工具。它不会执行客户端 Javascrīpt,也不会验证结果。该工具甚至不会模拟简单的菜单单击展开类型的操作。即使它模拟到服务器的特定浏览器客户端,它也不会验证回应在客户端浏览器中是否正常显示(即使它是 Microsoft Internet Explorer)。VSTS Web 测试是基于线路的测试协议。它验证通过线路发送和接收的内容,不提供用于测试浏览器显示数据方式的内置功能。
提供此类型的测试既困难又繁琐。但是,对于某些情况,可以考虑使用某些方法。假设如果同一响应出现多次,那么它将以同一方式在浏览器中显示和运行,这是合理的。因此,如果您手动验证特定响应是否正确 — 例如,通过检查 Javascrīpt 运行正常且页显示正确 — 则同一响应将在下一次正常运行。利用此原则,可以直观地验证响应,手动检查脚本运行是否正常。现在可以创建验证测试来检查类似的响应,使用通配符处理细微的数据更改(如,数据时间、用户名、公布等的变化)。如果页在将来运行测试时发生更改,那么应该重新验证响应并相应更新测试,从而为页提供更改控件的级别。这不是小组要全盘部署的内容,但是它提供良好的基本测试机制并强制受控变化。
测试驱动开发
我们通篇测试了现有网站,而未采用测试驱动开发 (TDD) 方法(先编写测试,然后写入页)来满足那些测试。如果未使用测试驱动方法,则隐含的驱动力是 VSTS Web 测试的一项记录功能。不是手动输入每个请求的 URL,而是浏览网站并使 Web 记录器将每个请求自动保存到测试中。
记录功能具有很大的优势,比手动输入每个请求好。然而,它还可以利用测试驱动方法。首先,设计页,包括与正进行的请求对应的所有链接和提交请求的所有按钮。除此之外,编码应简单。其次,记录站点周围的导航,将相应请求添加到测试用例结构中。最后,打开 Web 测试用例并将对其修改以包括验证和提取规则。这时,运行 Web 测试用例将产生失败的结果,因为还未添加执行规则的代码。因此,我们准备按 TDD 方法的规定,先编写测试,然后编写代码。
以使用 TDD 的登录方案为例。首先,开发人员创建登录页,并添加提交凭据的 Login(登录)按钮。然后,我们打开 Web 记录器,并记录提交的请求。在编写实现之前,我们向存根添加验证,来验证用户 ID 是否显示在响应中以及是否存在注销链接。此时运行测试表示我们测试失败并且需要编写所测试内容的实现。

TAG:

 

评分:0

我来说两句

alextowxm

alextowxm

高级测试工程师

我的栏目

日历

« 2024-04-21  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 61889
  • 日志数: 77
  • 文件数: 19
  • 书签数: 1
  • 建立时间: 2007-10-15
  • 更新时间: 2014-03-13

RSS订阅

Open Toolbar