- 浏览: 849722 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
贝塔ZQ:
读取excel文件,插件pageoffice也可以实现。
POI读写Excel文件(转)- - -
springmvc-freemarker:
java开源项目源码实例下载
java开源项目源代码 -
xuning2516:
第一种方法是个死循环啊。。。
Java NIO 拷贝文件(使用compact) -
u012046856:
...
SessionFactory.getCurrentSession与openSession的区别 -
Season_Wang:
赞一个呀,挺实用的
java swing 中的FileDialog
http://msdn.microsoft.com/zh-cn/magazine/cc163479
AJAX 测试自动化
James McCaffrey 博士
代码下载位置:
TestRun2007_02.exe
(574 KB)
Browse the Code Online
过
去一年中,使用 AJAX (Asynchronous JavaScript And XML) 技术的 Web
应用程序越来越受到用户的推崇。与非 AJAX Web 应用程序相比,正确编写的 AJAX Web 应用程序可显著提升性能和改善用户体验。但由于
AJAX Web
应用程序采用的是异步工作模式,因而传统同步测试自动化技术在此处通常便无用武之地。在本月的专栏中,我将介绍一项技术,利用该技术您便可编写小型测试自
动化软件,以此来验证 AJAX Web 应用程序的功能。
就我而言,向您传达本专栏中所述观点的最佳方法是借助一些屏幕快照。图 1
是一个使用了 AJAX 技术的简单但极具代表性的 ASP.NET Web 应用程序。该应用程序模拟映射工具,如 Microsoft®
Windows Live™ Local。当用户单击某定向按钮控件时,该应用程序会从 Web
服务器中提取适当的映射图像,然后在中心区域中显示新映射。不太容易从屏幕快照中看出的是 Web 应用程序使用 Microsoft ASP.NET
AJAX 以异步方式发送和检索映射图像。当然,您的 Web 应用程序会更为复杂,但我将向您介绍的技术适用于任何复杂的应用程序,并可用于任何启用
AJAX 的应用程序,不论实施何种技术。
手动测试图 1
中的应用程序是一件既费时低效又枯燥乏味的差事。更好的测试方法是编写小型测试自动化软件,如图 2
所示。这种测试工具是由两个框架构成的简单的 HTML 页面。右侧框架是 Web 应用程序的宿主,用户未进行任何修改或检测。左侧框架是含有
JavaScript 代码的单个 HTML 页面的宿主,JavaScript 代码可使用 Internet Explorer®
文档对象模式 (DOM) 在另一个框架中处理 Web 应用程序。
虽
然该测试技术是专用于处理使用异步操作的应用程序,但此技术也可用于使用传统同步 HTTP 请求/响应机制的 Web
应用程序。在本专栏中,我将简要介绍一下待测试的 Web 应用程序,从而使您了解传统测试自动化技术对 AJAX
应用程序无效的原因。然后,我将详细说明生成图 2
中的图像的测试工具,并说明如何才能修改和扩展此处介绍的技术以满足您自己的需求。最后,我相信您会发现这项技术是对开发人员和测试人员技能要求的一个有用补充。
图 1 待测试的 AJAX Web 应用程序
(单击该图像获得较大视图)
待测试的 Web 应用程序
我使用 ASP.NET AJAX 代码库(极大地简化了 AJAX 应用程序的创建过程)创建了如图 1
所示的 AJAX 映射应用程序。我没有使用真正的映射图像,而仅使用了从数字 1 到数字 9 的九个虚拟图像,图像名称依次为 1.jpg 到
9.jpg。(有关使用 Microsoft TerraServer 来获取真正的映射图像的示例,请参阅本期中 Jeff Prosise
关于“超酷代码”专栏。)缩图区域由 3 行 3 列的网格构成,第一行为 1、2 和 3,第二行为 4、5 和 6,第三行为 7、8 和 9。5
是该区域的中心,并且如果用户从 5 单击“北”控制按钮,则应用程序应显示 2。“北”按钮的逻辑如图 3
所示。
Figure 3 “北”按钮的隐藏代码
protected void Button1_Click(object sender, EventArgs e) { string imageUrl = Image1.ImageUrl.ToString(); if (!(imageUrl == "~/1.JPG" || imageUrl == "~/2.JPG" || imageUrl == "~/3.JPG")) { string oldNum = imageUrl.Substring(2, 1); int oldNumAsInt = int.Parse(oldNum); int newNumAsInt = oldNumAsInt - 3; string newNum = newNumAsInt.ToString(); string newImageURL = imageUrl.Replace(oldNum, newNum); Image1.ImageUrl = newImageURL; } }
图 2 测试运行示例
(单击该图像获得较大视图)
如
果当前映射位于该区域的首行(1、2、3),则单击“北”后不会产生任何影响。其他情况下,我将得到当前映射位置的数字,这个数字减去 3
后即可确定相应的新 JPEG 图像,并更新该图像控件的 ImageUrl 属性。“南”、“东”和“西”按钮控件的处理程序与之类似。
需
要强调的是,在此我并没有为了保持应用程序代码的简短易读而故意不采用更好的编码方法。在实际的 Web 应用程序中,代码逻辑很可能需要访问后台
SQL 或 XML 存储库并从中提取数据,然后使用这些数据更新应用程序状态。由于本专栏中的技术通过 Internet Explorer DOM
测试 Web 应用程序,因而如何确定应用程序状态并不重要 - 任何用户输入都可能导致应用程序状态的改变,用户输入将反映在应用程序的 UI
中,用户可通过 Internet Explorer DOM 访问这些 UI。
传
统的非 AJAX 方法向 Web 服务器发布 HTTP 请求,并以“窗体”对象或查询字符串的形式传递请求信息。映射应用程序不需使用 AJAX
技术便能运行,但这种方法存在两个缺点。第一,由于 HTTP 请求/响应机制是同步的,因此,尽管请求由 Web
服务器进行处理,但用户在该响应返回客户端之前几乎无法与 Web 应用程序进行交互。第二,多数情况下 HTTP
请求会导致创建整个响应页面,因此当由 Internet Explorer
收到响应时,将重新绘制整个页面。如果请求/响应相对较快(或更糟),这将导致出现恼人的页面闪烁效果;如果操作较慢,则将导致页面变为空白。
AJAX
可解决上述两个问题。AJAX 通过发送 XMLHTTP 请求而非 HTTP 请求进行工作。XMLHTTP 请求是异步的。因此,在后台处理
XMLHTTP 请求的同时,用户可继续与 Web 应用程序进行交互。并且当收到 XMLHTTP 响应时,系统可使用 Internet
Explorer DOM 仅重新绘制存放新数据的网页区域,而不必重新绘制整个页面。
我
不是通过编写“原始”JavaScript 来启用 ASP.NET 映射应用程序上的 AJAX,而是使用 Microsoft ASP.NET
AJAX 框架来启用它。Microsoft ASP.NET AJAX 框架的使用方法相当简单,因为它在安装时提供了一个 Visual
Studio®
AJAX 网站模板。选择该模板便可将所需的程序集引用添加到 Web 应用程序项目中。为了在映射应用程序中启用 AJAX 功能,我向源文件添加了下列标记:
<asp:ScriptManager ID="sm" runat="server" />
然后,我将图像控件(我想在异步请求-响应后更新该控件)封装在 ASP.NET AJAX UpdatePanel 控件中,如下所示:
<asp:UpdatePanel ID="up1" runat="server"> <ContentTemplate> <asp:Image ID="Image1" runat="server" ImageUrl="~/5.JPG" (other attributes omitted) /> </ContentTemplate> <Triggers> <asp:AsyncPostbackTrigger ControlID="Button1" EventName="Click" /> <asp:AsyncPostbackTrigger ControlID="Button2" EventName="Click" /> </Triggers> </asp:UpdatePanel>
这就是对 Microsoft ASP.NET AJAX 框架所做的全部工作。非常好!该框架将处理所有杂乱的细节,如创建 XMLHTTP 对象、侦听异步响应、错误处理、跨浏览器差异等。
请
注意,仅当存在对 Button1(“北”)控件和 Button2(“南”)控件的单击事件时(而非对所有四个定向控件的单击事件),我才会启用
AJAX
异步请求/响应。我这样做的目的是为了说明本月专栏中介绍的测试技术既可用于异步请求也可用于同步请求。如果您使用本文附带的代码下载内容尝试运行该应用
程序,则会发现“北”请求和“南”请求 (AJAX) 与“东”请求和“西”请求(非 AJAX)之间的区别。
大
多数传统测试自动化技术都对 AJAX Web 应用程序不起作用。测试 Web 应用程序功能的最基本方法是以编程方式发送 HTTP
请求(该请求对应于某用户向 Web 服务器输入信息后所生成的请求)、提取 HTTP
响应,然后检查此响应以确定“pass/fail”(通过/失败)结果。这种方法不适用于 AJAX 应用程序,因为这些应用程序使用特殊的
XMLHTTP 请求。
另一种传统方法是使用
JavaScript 操纵 Internet Explorer DOM 以向 Web 服务器发送请求,等到 onload
事件触发(发出客户端已收到并已加载响应的信号)后,然后使用 JavaScript 和 Internet Explorer DOM
来检查网页的新状态以确定“pass/fail”(通过/失败)结果。使用此方法产生的问题是,由于 AJAX 采用的是异步工作模式,因而您无法使用
onload 事件来确定客户端收到响应的时间。但您可对这种方法稍作修改,以创建适用于 AJAX
应用程序的小型测试自动化软件。收到响应时,您不必使用 onload
事件来发出信号,而是可通过编写代码来监视应用程序,使应用程序状态按照要求发生某些变化,然后将控制权转至回调函数。
测试自动化
图 2
屏幕快照中所示的 AJAX 应用程序测试工具系统由三个文件组成。图 4
显示了该工具整体结构的框图。工具本身(即 TestHarness.aspx)是包含两个框架的简单的网页。右侧框架包含待测试的 AJAX Web
应用程序。左侧框架包含测试方案页面,其中列出了一些最小 UI 和所有 JavaScript 代码,用于处理和检查待测试的 Web
应用程序。为保持一致,我打算将上述三个页面编写为 .aspx 文件,尽管这会使我无法将基本 HTML 用于测试工具和测试方案页面。下面是
TestHarness.aspx 页面的完整源代码:
<html> <head> <title>Test Harness for AJAX Web Apps</title> </head> <frameset cols="45%,*"> <frame src="http://localhost/AjaxTest/TestScenario001.aspx" name="leftFrame"> <frame src="http://localhost/AjaxApplication/Default.aspx" name="rightFrame"> </frameset> </html>
图 4 测试工具的结构
(单击该图像获得较大视图)
如
您所见,主要的测试工具页面实际上就是一个容器文件。通过调用程序定义函数 asyncCall 开始运行测试方案,该函数会使待测试的应用程序向
Web 服务器发送异步 XMLHTTP 请求,同时调用程序定义的 delay 函数。该 delay 函数在 Web
服务器处理请求时进行循环,返回异步响应,并不时检查 Web 应用程序的状态。客户端收到响应且应用程序状态被更新后,delay
函数会发现网页的状态已发生改变,然后便可进行新的异步调用。
asyncCall 内部
AJAX 测试自动化技术的核心是一对程序定义函数,即 asyncCall 和 delay,用户应搭配使用这两个函数。asyncCall 方法如下:
function asyncCall(action, checkFunc, arg, callback, pollTime) { numTries = 0; action(); window.setTimeout("delay(" + checkFunc + ", " + "'" + arg + "'" + ", " + callback + ", " + pollTime + ")", pollTime); }
我传入了五个参数。第一个参
数 action 是指向某例程的函数指针,该例程使用 Internet Explorer DOM 来触发操作,从而启动异步 XMLHTTP
请求。第二个参数 checkFunc 是指向某例程的函数指针,该例程在 Web 应用程序的状态表明异步响应已完成时返回 true。第三个参数
arg 是传递给 checkFunc 函数的参数。第四个参数 callback
是指向某例程的函数指针,系统会在异步响应已完成时调用该例程。最后一个参数 pollTime 用于指定合作伙伴 delay
函数中两次调用之间的等待时间(以毫秒为单位)。
在
asyncCall 函数内部,我首先将全局 numTries 计数器设置为 0。我使用该变量来跟踪进入 delay
函数的次数,以便在查找可表明异步响应已发生的尝试达到指定次数后能够退出。接下来,我调用 action
参数,该参数进而触发异步请求。请注意,附加到函数名的括号是用来调用函数的语法机制。
下
面才是真正的技巧所在:我调用内部 window.setTimeout 函数。如您所见,setTimeout
接受两个参数。第一个参数是仅执行一次的 JavaScript 语句。第二个参数是在执行第一个参数前延迟的时间(以毫秒为单位)。如果检查
asyncCall 中的代码,您便会发现我传递给 setTimeout 的第一个参数变成了如下形式:
delay(checkFunc, 'arg', callback, pollTime)
第二个 arg 就是 pollTime。简言之,在 pollTime 毫秒的延迟后,我调用了程序定义的 delay 函数。
对 asyncCall 函数的调用如下所示:
asyncCall(clickNorth, imgIsTwo, "2", clickSouth, 200);
该调用可解释为“调用名为 clickNorth 的函数,然后进入 delay 循环,每隔 200 毫秒调用一次带有参数‘2’的函数 imgIsTwo,并在 imgIsTwo 最终返回 true 时,将控制权转至名为 clickSouth 的函数。”
在 asyncCall 方法的定义中,arg 周围的单引号字符非常重要。如果 asyncCall 定义中没有单引号,则参数将按引用进行传递,如下所示:
asyncCall(doThis, findX, "X", doThat, 200);
此类调用会生成错误,指出变量 X 未被定义。如果使用了单引号,则参数将按值进行传递。在本例中,您希望参数按值传递。
还有另一种有趣的方法可用来调用 asyncCall 内部的 window.setTimeout 函数。通常,您需要编写类似下列内容的代码:
window.setTimeout("delay(" + checkFunc + ", " + "'" + arg + "'" + ", " + callback + ", " + pollTime + ")", pollTime);
此外,您还可使用 JavaScript 的匿名函数功能,并编写下列代码:
window.setTimeout( function(){delay(checkFunc, arg, callback, pollTime);}, pollTime);
由于删除了单引号字符和字符
串连接,因而此类代码比非匿名代码要略显简洁一些。另外,它的效率比非匿名代码略胜一筹,因为非匿名代码要求浏览器创建新的脚本环境来处理该脚本。但如果
没有使用单引号字符来分隔传递给 checkFunc 的 arg 参数,则无法明显表示 arg
是按值进行传递的(尽管简单的注释可避免发生任何可能的误解)。
Delay 内部
下面介绍 asyncCall 的合作伙伴 delay 函数:
function delay(checkFunc, arg, callback, pollTime) { ++numTries; if (numTries > maxTries) finish(); else if (checkFunc(arg)) callback(); else window.setTimeout("delay(" + checkFunc + ", " + "'" + arg + "'" + ", " + callback + ")", pollTime); }
delay 函数接受四个参数,这些参数与进行传递以调用 asyncCall 函数的最后四个参数完全对应。
在
delay 内部,我首先递增全局 numTries 计数器。我们知道,在上文中我使用该计数器来跟踪进入 delay
函数的次数,或换言之,我检查 Web 应用程序状态的次数,以判断异步响应是否已完成。如果全局计数器的读数大于全局常量
maxTries,则或是服务器端的 Web 应用程序超时,或是 XMLHTTP 响应不正确,因此,我将控制权转至 finish
函数,以确定具体情况。
如果 delay
未超时,我便会调用 checkFunc 函数来测试用来指示正确响应的条件是否为 true。如果 checkFunc 返回 true,我便可调用
callback 函数以继续执行测试方案。但如果 checkFunc 函数返回 false,我便需继续等待,因此我将再次调用内部
setTimeout 函数,该函数将在等待 pollTime 毫秒后再次调用 delay。
delay
函数不是完全递归函数,因为它无法直接调用它自己,但它是自引用函数,因为它通过 setTimeout
函数间接调用它自己。实际效果是产生一个等待循环,该循环或将控制权转至 finish 函数(如果超过了 delay
循环中的最大次数),或将控制权转至 callback 函数(如果某 Web 应用程序状态变为
true)。这种方法会使人产生一种山重水复疑无路,柳暗花明又一村的感觉。当然,其他方法也能解决上述问题,但实践证明该方法的确简单高效。
如同在 asyncCall 函数中一样,您不必使用指定的函数参数来调用 window.setTimeout 函数,而是可以使用匿名函数功能,如下所示:
window.setTimeout( function(){delay(checkFunc, arg, callback);}, pollTime);
构建测试页
处理了 asyncCall 函数和 delay 函数后,现在我便可开始构建测试方案页面了。图 5
介绍了测试方案的整体结构。
Figure 5 测试方案结构
<html> <head> <script type="text/javascript"> var maxTries = 10; var numTries; var polling = 200; // 毫秒 function asyncCall(action, checkFunc, arg, callback, pollTime) { // 在此处编写代码 } function delay(checkFunc, arg, callback, pollTime) { // 在此处编写代码 } // 在此处添加其他函数 </script> </head> <body bgcolor="#22EE66"> <h3>此为测试方案脚本页面</h3> <p>动作:</p><p><textarea id="comments" rows="16" cols="34"></textarea></p> <input type="button" value="运行测试" onclick="runTest();" /> </body> </html>
测
试方案页面 <正文> 部分仅包含一个标题、一个要显示注释且具有
ID“comments”的文本区,以及一个用于启动自动化的按钮控件。<标题> 部分包括我的所有 JavaScript
代码。我声明并初始化全局常量 maxTries 以指定要进入 delay 函数的最大次数,并检查可表明异步响应已完成的条件。全局变量
numTries 跟踪进入 delay 函数的次数。全局常量 polling 设置对 delay 函数进行两次连续调用之间的延迟时间。
根
据待测试的 AJAX Web 应用程序的复杂度,您可能需要修改 maxTries 和 polling 的值。在这里,10 次调用(将 200
毫秒作为两次调用之间的延迟时间)仅用时 2 秒,Web 服务器可能无法在如此短的时间内处理 XMLHTTP 请求并将响应返回至客户端。
测试方案首先调用 runTest 函数:
function runTest() { try { logRemark("测试方案 001"); logRemark("开始测试运行\n"); step1(); // 从 5 开始,将 N 转至 2 } catch(ex) { logRemark("致命错误: " + ex); } } }
我所做的是使用程序定义的
logRemark 函数在工具正文的 <文本区> 中显示两条消息,然后将控制权转至 step1 函数。我将代码封装到简单的
try/catch 块中,以便在测试运行期间出现任何例外时都能激起并捕获这些代码。我的 logRemark 函数非常简单:
function logRemark(comment) { var currComment = document.all["comments"].value; var newComment = currComment + "\n" + comment; document.all["comments"].value = newComment; }
我检索具有 ID“comments”的 <文本区> 元素的当前内容,将换行字符和新注释文本附加到当前内容中,然后使用更新的注释集替换 <文本区> 内容。这不是一种高效的方法,但在小型测试自动化软件中,简洁往往要比效率更重要。
step1 函数开始处理待测试的 AJAX Web 应用程序:
function step1() { logRemark("单击“北”,等待“2”"); asyncCall(clickNorth, checkImageSrc, "2", step2, polling); }
记录注释后,我调用
asyncCall 函数,该函数是测试自动化的关键所在。该调用在这里表示:调用函数 clickNorth,然后进行 delay 循环直到
checkImgSrc("2") 返回 true 为止,在两次检查之间暂停 200 毫秒,然后将控制权转至函数 step2。如果调用
delay 循环的次数超过 10 (maxTries) 次,则会将控制权转至 finish 函数。
clickNorth 函数非常简单:
function clickNorth() { var btnNorth = parent.rightFrame.document.all["Button1"]; if (!btnNorth) throw "未找到 btnNorth"; btnNorth.click(); }
我使用 Internet
Explorer DOM 来获得对 Button1 控件的引用,然后调用该控件的 click 方法。请注意,由于自动化软件位于一个框架中,而
AJAX 应用程序位于另一个框架中,为了从测试脚本访问应用程序上的控件,因而我必须使用 parent
关键字来“上升”一个级别,然后使用应用程序容器的框架 ID。我喜欢使用 document.all
集合来获得对网页控件的引用,而我的一些同事则更喜欢使用 getElementById 方法,如下所示:
var btnNorth = parent.rightFrame.document.getElementById("Button1");
checkImageSrc 函数可告知自动化软件有关异步响应更新待测试 AJAX 应用程序上的 Image1 控件的时间:
function checkImageSrc(target) { try { var s = parent.rightFrame.document.all["Image1"].src; return s.indexOf(target) >= 0; } // 尚未装载 Image1 的陷阱案例 // logRemark("CheckImageSrc() 中存在错误: " + ex); catch(ex) { return false; } }
通常,我只检查
Image1 控件的 src 属性,以此来确定该属性是否包含目标字符串。例如,如果图像的 src 属性包含“2”(如在 map 2
的文件名“~/2.jpg”中),则当调用 checkImageSrc("2") 时将返回 true。在编写您自己的 AJAX
自动化软件时,您必须创建适当的 check 函数。例如,假设 Web 应用程序要更新具有 ID“TextBox1”的 TextBox
控件。一个可能的 check 函数为:
function checkTextBoxValue(target) { try { var s = parent.rightFrame.document.all["TextBox1"].value; return s.indexOf(target) >= 0; } // 尚未装载 TextBox1 的陷阱案例 // logRemark("checkTextBoxValue() 中存在错误: " + ex); catch(ex) { return false; } }
请注意
checkImageSrc 函数中的 try/catch 块。与大多数情况下将 try/catch 用来捕获异常错误条件不同,在这里我将
try/catch 用作标准函数逻辑的一部分。其间的思路是在重新绘制网页期间,用户无法获得对 Image1 控件的引用,而任何尝试获得对
Image1 控件的引用的操作都将引发异常。这并不一定意味着 Web
应用程序的状态不正确,而仅表明该应用程序处于未完成状态,因而我希望系统捕获异常并返回 false。通过取消对 logRemark
调用的注释并将轮询时间设置得非常短(如 10 毫秒)可观察该行为。
顺便提一下,人们通常认为将 try/catch 用作标准函数逻辑的一部分是很糟糕的编码样式,但在本例中,由于将 try/catch 用于标准逻辑流程可简化代码,因而我认为这是可以接受的。
我
的测试方案脚本定义了一些与 step1 函数极其类似的函数 step2、step3、step4 和 step5。step2 函数可调用函数
clickEast,等到映射显示区域中出现“3”后,便紧接着调用 step3。step3 函数可调用函数
clickSouth,并等到“6”出现后,便紧接着调用 step4,依此类推。step5 函数可调用暂作过渡之用的 finish 函数
step6:
function step6() { finish(); }
在这里,我只需将控制权转至真正的 finish 函数(如图 6
所示)。我们知道,finish 函数还可处理对 delay 函数的调用次数超过了最大允许次数的情况。
Figure 6 Finish 函数
function finish() { if (numTries > maxTries) { logRemark("\nnumTries 已超出 maxTries"); logRemark("\n*失败*"); } else { logRemark("检查最终状态"); var is = parent.rightFrame.document.all["Image1"].src; if (is.indexOf("8") >= 0) logRemark("\n*通过*"); else logRemark("\n*失败*"); } logRemark("\n已全部完成"); }
首
先,我将处理全局计数器 numTries 的读数超过了全局常量 maxTries 的情况。在下列两种情况中都可能发生这种情况:第一种情况是
AJAX 应用程序的逻辑正确,但应用程序更新页面状态超时;第二种情况是应用程序的逻辑不正确,并且 check
函数无法找到正确的状态。在这里,我随意选择了一种导致测试方案失败的简单解决方案。
finish 中的第二个逻辑分支会检查应用程序的最终状态以确定“pass/fail”(通过/失败)结果。在本例中,如果我从“5”开始逐个单击“北”、“东”、“南”和“西”这几个控件,便可检查最终映射图像是否为“8”(正常情况下应为“8”)。
扩展测试工具
我在本文中介绍的测试自动化系统规模很小,专为便于您进行修改而设计。对于杂志文章,我通常会删除其中大多数错误检查以保持主要观点的鲜明性。但您可能希望随意添加一些错误陷阱 - 但测试自动化软件机敏睿智,并且错误是常事而非例外。
请注意,测试工具并不是完全自动化的:您必须手动单击“进行测试”按钮来启动自动化软件。您可通过各种方法使该工具实现完全自动化。一种简单的方法就是将 onload 处理程序添加到测试工具框架中:
<frame src="http://localhost/AjaxApplication/Default.aspx" name="rightFrame" onload="leftFrame.launch();" >
在本例中,测试方案代码中的 launch 函数定义如下:
var started = false; function launch() { if (!started) runTest(); }
此外,还需编辑本专栏中介绍的 runTest 函数,使其以下列语句开头:
started = true;
当加载包含待测试的
AJAX Web 应用程序的右侧框架时,系统会调用 launch 函数。首次执行 launch 时,处于启用状态的全局变量为
false,并且将控制权转至 runTest 函数,该函数将处于启用状态的变量设置为 true,然后执行自动化软件。加载(发生于定期 HTTP
请求/响应操作时)Web 应用程序的后续页面时,系统将调用 launch 函数,但由于处于启用状态的全局变量为
true,因而不会再次将控制权转至 runTest。借助完全自动化版本的测试工具,您便可创建多个工具页面和方案页面,然后通过将下列语句添加到
BAT 文件中并紧接着使用 Windows Task Scheduler 来启动自动化软件,以执行多个方案:
iexplore http://localhost/AjaxTest/TestHarness01.aspx iexplore http://localhost/AjaxTest/TestHarness02.aspx
请注意,小型系统的缺点是您
无法方便地对该系统进行参数化。尽管您可轻松地将测试方案页面中的公共 JavaScript 代码添加到独立的单个 .js
文件中,但要协调单个测试工具页面中的多个测试方案的执行却无简便方法可循。这并意味着您无法实现该操作,我只是要告诉您这并非易事。
AJAX
测试自动化软件的另一个扩展是使保存测试方案结果的过程实现自动化。本文中介绍的系统不会记录结果,但您可通过下列几种方法来实现该操作。一种方法是将
“窗体”元素添加到测试方案页面中,在该窗体内部放置一个用来存放测试方案结果的文本字段,然后将结果 POST 到服务器,如下所示:
您可根据下列代码行向 finish 函数内部的结果字段提供“pass/fail”(通过/失败)值:
<form name="resultForm" method="Post" action="saveResults.aspx"> <p>Result: <input type="text" name="result"></p> <p><input type="submit" name="saver" value="Save Results"></p> </form>
if (is.indexOf("8") >= 0) { logRemark("\n*通过*"); theForm.result.value = "Pass"; } else { logRemark("\n*失败*"); theForm.result.value = "Fail"; }
现在,您可通过单击“保存结果”按钮来手动保存方案结果,或者您也可通过将下列代码添加到方案代码中来自动进行保存:
document.all["theForm"].submit();
结束语
我
在本文中介绍的测试工具只是可用来测试 AJAX Web
应用程序的众多方法中的一种。阅读本专栏后,您应当能够使用我介绍的小型方法和更为复杂的工具来测试 AJAX Web 应用程序。随着
ASP.NET AJAX 框架的发布,AJAX Web
应用程序也会随之很快普及。编写小型测试自动化软件的能力会变得越来越重要,它是对您个人技能集的重要补充。
将您想向 James 询问的问题和提出的意见发送至 testrun@microsoft.com .
James McCaffrey 博士
供
职于 Volt Information Sciences, Inc.,在那里他负责 Microsoft 的软件工程师的技术培训。他已为多种
Microsoft 产品效过力,包括 Internet Explorer 和 MSN Search。James 是《.NET Test
Automation Recipes》(.NET 测试自动化菜单)(Apress,2006)的作者。James 的联系方式如下:jmccaffrey@volt.com
或 v-jammc@microsoft.com
感谢 Doug Walter、Shawn Burke 和 Scott Guthrie(全部供职于 Microsoft),他们的意见使本专栏的内容更为丰富精彩。
相关推荐
《Selenium2 Python 自动化测试实战》是一本专注于使用Python和Selenium2进行Web自动化测试的专业书籍。这本书详尽地介绍了如何利用Selenium2这个强大的工具,配合Python语言,来构建高效、可靠的自动化测试框架,以...
在IT行业中,自动化测试是一种广泛采用的技术,特别是对于Web应用程序来说。它可以帮助开发人员和测试工程师提高测试效率,减少手动测试的时间和出错率。在这个名为"web自动化测试"的例子中,我们关注的是如何利用...
Web自动化测试中的接口测试是一种重要的测试手段,主要是针对Web应用中后端服务的接口进行测试,以确保各个服务模块之间能正确交互。本文主要针对Web自动化测试中的接口测试方法、工具和技术等方面的知识进行深入...
【自己动手写Web自动化测试框架】的文档是一个指导如何构建基于C#的Web自动化测试工具的教程。这个框架旨在帮助测试人员高效编写自动化测试代码,并在出现错误时快速定位问题。文档提到了两个主要的非托管类库:...
通过合理运用Selenium API,处理好Ajax和动画效果,以及避免使用低效的同步等待方法,可以大大提高Web自动化测试的效率和质量。通过本文的介绍,希望读者能够掌握构建健壮Web自动化测试模式的关键技术,并在实际工作...
Selenium自动化测试培训旨在提供全面的知识和技能,帮助学员掌握Selenium工具的使用,自动化测试脚本的设计,以及自动化测试框架的构建。 ### 自动化测试基础 在开始学习Selenium之前,理解自动化测试的基本原理至...
"Selenium自动化测试:基于Python语言.pdf"可能是本书的电子版,详细讲解了Selenium的基础知识、安装配置、元素定位方法(如CSS选择器、XPath、ID、Name等)、各种操作(如点击、输入、截屏)以及高级用法,如模拟...
### 构建简单的web自动化测试模型 #### 一、引言 随着软件开发技术的不断发展,Web应用变得越来越复杂,为了确保这些应用的质量,自动化测试成为了一种必不可少的方法。本篇文章将详细介绍如何构建一个简单而健壮的...
【标题】"Web自动化测试学习以及JavaScript学习(四)"主要涵盖了两个核心主题:Web自动化测试和JavaScript编程。本文将深入探讨这两个领域的关键知识点,并结合实际应用进行详细讲解。 在Web自动化测试方面,通常...
Java全栈自动化课程将教授学员如何利用自动化测试工具,如JUnit、Selenium和TestNG等,进行单元测试、集成测试、系统测试等。学员将学习自动化测试的设计原则,测试用例的编写,测试流程的管理,以及持续集成和持续...
自动化测试框架RobotFramework+Selenium2 自动化测试框架RobotFramework+Selenium2是结合RobotFramework框架和Selenium2Library实现自动化测试的解决方案。下面是该框架的详细介绍: 简介 Robot Framework是一个...
【网站自动化测试工具 Web测试工具介绍】 在软件测试领域,特别是针对Web应用的测试,自动化测试工具扮演着至关重要的角色,能够显著提高测试效率并减少人为错误。QTester是一款广泛使用的自动化测试工具,专为网站...
自动化测试的场景和特点包括自动化测试的优点、自动化测试的类型、自动化测试的流程等内容。 单元测试 单元测试是一种软件测试方法,通过对软件的每个单元进行测试,确保软件的每个单元都能正确工作。单元测试的...
接口自动化测试是软件开发过程中的重要环节,尤其在现代Web应用程序中,接口测试扮演着验证系统组件间通信的关键角色。本文将深入探讨接口自动化测试,包括其重要性、使用工具,特别是结合Chrome插件进行测试的方法...
### 自动化测试工具详解 #### 一、引言 随着软件开发的速度加快和技术更新迭代的频率提升,软件测试已成为确保软件质量不可或缺的一环。自动化测试作为软件测试的一个重要分支,能够有效提高测试效率和准确性,...
本示例主要关注的是如何利用Ajax实现一种自动保存功能,常见于博客、论坛等在线文本编辑场景,确保用户在输入内容时,即使意外关闭浏览器或发生其他故障,也能找回未保存的信息。 首先,理解Ajax的工作原理至关重要...
QTP,全称为QuickTest Professional,现在被称为UFT(Unified Functional Testing),是一款功能强大的自动化测试工具,尤其在企业级应用中广泛使用。本文将深入探讨UFT的三种自动化测试框架,以及如何利用它们进行...