简介: 众所周知,Eclipse 不仅是一个功能强大的开发框架,更是一个成熟的、精心设计的可扩展的体系架构。尽管在现有的测试工作中,已经存在许多对代码和工程进行测试、分析和监视的工具,但是很少能够集成为一个全面而且通用的工具包。因此对于每种测试工具都要花费测试人员宝贵的时间和精力来学习,掌握许多不同的用户界面(UI)、编译器和诊断技术;此外,在时间和资金两方面,开发专有的测试工具也需要很大的投资。
在这种情况下,Eclipse Test and Performance Tools Platform(TPTP)就应运而生了。TPTP 项目成立于 2004 年 8 月,被列为 Eclipse 的顶级项目,它是一种软件体系架构以及几个扩展了 Eclipse 平台的组件,它在 Eclipse 平台上提供了测试、性能和监视工具,其源码开放并且工具是可扩展的,任何厂商或开发人员都可以创建新工具或者对现有工具进行改进。一些 Java、C 和 C++ 开发人员可以使用 TPTP 为其他开发人员构建独特的工具,也可以将 TPTP 提供的工具和 Eclipse 的其他特性组合起来,构建和部署供用户使用的应用程序。下图即 TPTP 在 Eclipse 整体架构中的位置。
图 1.TPTP 在 Eclipse 架构中的位置
本文着重介绍 TPTP 对 Web 测试行为自动记录并自动生成测试脚本以及自动生成 TPTP 下的 JUnit 测试脚本的过程。此外,作者分析了这种方法的不足并提出了利用已有框架进行 Web 应用测试的扩充方法及其应用。
简单地说,TPTP 就是“构建一个通用的可扩展的基于标准的工具平台,软件开发人员可以在这个平台上创建专用的可互操作的测试和性能工具”。TPTP 分为四个子项目:TPTP Platform Project、Testing Tools Project、Tracing and Profiling Tools Project、Monitoring Tools Project。其中核心和提供基础服务的是 Platform 子项目,其余三个子项目都是建立在此基础之上。Testing Tools 是提供测试用的工具,Tracing and Profiling Tools 是提供跟踪和分析的工具,Monitoring Tools 是提供实时监控的工具。基于这些现成的平台和工具,我们也很容易开发自己定制的测试、分析、和监控工具。
以下是 TPTP 的当前版本包括核心工具和三种核心衍生工具的详细介绍。
TPTP Platform
TPTP 为 UI 开发、数据收集、基于规则的数据查询以及应用程序的控制提供了基础代码。例如,TPTP 提供了其他工具可以重用和扩展的许多向导。它还提供了编程接口和一个守护进程,以便帮助从正在运行的本地或远程进程中收集数据。
TPTP Testing Tools
这个项目是在 TPTP 之上构建的,提供了对应用程序进行各种自动化测试所需的其他服务。当前版本支持 JUnit 自动测试、一种指向和点击脚本编程系统(用于进行手工测试并记录结果)和一个用于测试 Web 应用程序的自动化系统,包括一个可以记录和回放 Web 浏览会话并对结果进行验证的记录器。在 Eclipse V4.1 版本之后还包括一个图形用户界面(GUI)记录器,它可以记录和回放基于 SWT 的界面中的鼠标和键盘事件。
TPTP Monitoring Tools
这个项目对来自日志文件或来自应用程序收集的统计数据的数据进行收集、分析和图形显示。
TPTP Tracing and Profiling Tools
这个项目也扩展了 TPTP,用来收集和分析正在运行的应用程序中的资源使用数据,包括 CPU 和内存。这个跟踪工具还允许与正在运行的进程进行交互。例如,可以手工地实施垃圾收集并检查剩余的对象池,从而寻找和修复内存“泄漏”。
下图是 TPTP 这四个子项目的相互协作关系:
图 2.TPTP 架构图
由于 TPTP 的功能覆盖面太广,仅以一篇文章无法进行全面介绍,而目前业界最流行的就是对 Web 应用的开发和测试,因此本文只把注意力放在 Testing Tools 子模块上,并且着重介绍 HTTP test 和浏览器recording 部分。
在介绍 TPTP 具体应用之前,需要在 Eclipse 上安装好 TPTP 插件。您可以在官方网站上一起下载:http://www.eclipse.org/TPTP/home/downloads。
自动记录 URL 脚本、生成 TPTP 测试脚本、并进行测试的过程。
第一步:选择 File -> New -> Other,会弹出一个 Eclipse 框架的 Dialog Wizard,在 Test 目录下选择“Test From Recording”, 点击“Next”。如下图所示:
图 3. 建立新工程“Test From Recording”
第二步:弹出 Dialog Wizard 第二页,选择“HTTP Recording”,点击“Next”;弹出第三页,为生成的测试文件选择一个工程目录,并且填写记录文件和生成 TPTP 测试文件的名称,点击“Finish”。如下图所示:
图 4. 生成 testsuite 工程目录和生成文件名
此时程序会启动本机系统默认的浏览器,并根据其句柄和端口记录其 send 和 receive 的 HTTP 数据包。用户对浏览器的任何操作,包括所有浏览的站点、发送的请求和接收到的 Web 页面,都会被实时的动态存储在 <test name>.rec 记录文件中。
第三步:关闭浏览器或者点击 Test Recorder 的“停止”按钮结束记录。记录停止后 TPTP 根据记录文件(<test name>.rec)生成 TPTP 自己的测试文件,即:<test name>.testsuite。
Testsuite 文件是一个序列化的 XML 文件,它是 TPTP 自身设计的脚本文件,是一个测试集合的基本单位。我们可以双击打开 <test name>.testsuite 文件(如图 5),可以看到所有浏览过的 HTTP Request 列表,点击“More”可以进入每一个 Loop 或者 Testcase 中修改,修改 HTTP Request 相关的各种信息。这个 testsuite 文件在 TPTP 中可以作为 test 文件直接运行,并且记录自己的 log,具体操作方法为:选中 testsuite 文件,由菜单选择 Run->Test。本文不对此进行详细说明,读者可自行尝试。
由 testsuite 向 TPTP JUnit 转换的过程。
首先打开“Test Navigator”视图(Eclipse 中,“Window->Show View->Other”选择“Test 目录下的 Test Navigator”),在“Test Navigator”视图中右键点击 testsuite 文件,选择“Generate”,如下图:
图 5. 由 testsuite 生产 Java 测试文件
然后,在弹出的 Dialog Wizard 对话框中,选择生产 Java 文件的工程和所在目录,点击“Finish”。Eclipse 会自动切换视图到“Package Explorer”,展示在大家面前的就是根据 testsuite 生产的 TPTP JUnit 文件。
这个自动生成的 Java 文件可以直接在 TPTP 下运行,并产生自己的 log。其特点是既保留了原本 JUnit 的底层实现又结合了现在 TPTP testsuite 的特点。
自动记录所生成的测试脚本往往不能满足实际的工作需要,因为在测试工作中我们经常需要对返回的页面内容进行分析或验证。为了达到实际测试工作的要求,我们需要对 TPTP 的测试脚本进行一些客户化的修改。要理解这个过程并利用其进行自己的测试验证工作,就必须要弄清楚 TPTP 生产的这两种文件的结构。下图所示就是 testsuite 文件的基本结构:一个 testsuite 包括很多 Loop,每个 Loop 中又包含有多个 Http Request;每个 HTTP Request 可以看成一个 case,当然也可以把整个 loop 甚至 testsuite 看成一个 case。在 TPTP 中,我们可以控制 Loop 的次数、可以修改每个 HTTP Request 或者 Loop 甚至整个 testsuite。
图 6.testsuite 内部结构
由 testsuite 生成的 Java 测试脚本,是以 JUnit 为基础,从 JUnit 的基本测试类继承而来的 TPTP 自己的 JUnit 测试类 - HyadesTestCase,其中的测试方法对于 JUnit 的固有类进行了进一步的继承和封装。由于这个自动生成的 Java 文件是由 testsuite 脚本而来,所以它的结构与 testsuite 相对应,大致结构如下图:
图 7.TPTP 产生的 JUnit 文件结构
testsuite 中每一个 Loop 和 HTTP Request 在生成的 Java 测试文件中都有映射;同时,这个 Java 测试文件还会派生出一系列公共的方法,供每个 test 调用。其中有一个最基本的公共方法 executeRequest,它是每个 test 调用的公共断言,负责执行每个 HTTP Request 以及其断言。下面是一段公共方法调用代码示例。
protected void executeRequest(HttpRequest request) throws Exception {
……
HttpResponse response = m_httpExecutor[nUser].execute(request);
……
//If (response.getCode() < 400) then the request has failed.
assertTrue(text, response.getCode() < 400 && response.getCode() > 0);
}
|
从上面的代码可以看出,每个 test 断言的依据仅仅是判断了 response 的 getCode 代码:
assertTrue(text, response.getCode() < 400 && response.getCode() > 0);
|
并没有对返回的具体内容做出任何判断,这对于 tester 来说基本上是毫无用处的,因为真正的测试中往往要求对返回的页面上一个具体字符串进行验证。而每一个 TPTP 自动生成的 Java 测试脚本中所有 HTTP test 都仅使用上面这个方法来做验证,所以这个自动生成的脚本用处就很有限。为了更好的利用 TPTP 来进行 Web 测试,我们需要自己手动修改其断言方法。
但是,在这个类中的 response 对象并非 JUnit 公共的 HttpResponse 对象,而是 TPTP 自己封装在 org.eclipse.hyades.test.http.runner 包中的 HttpResponse 类。所以我们只能对 TPTP 的 HttpResponse 类进行定制。
研究了 org.eclipse.hyades.test.http.runner 包内的源代码之后,不难看出,在 HttpExecutor 类中,其实是可以取得整个 HTTP 协议返回的内容的,但是在 TPTP 定义的执行过程中对其返回内容进行了取舍,只提取了 HTTP Content-Type 的内容并将其封装在 HttpResponse 对象中。因此如果使用 TPTP 封装的 HttpResponse 类,就无法取得服务器端返回的全部内容,从而无法对内容进行验证。
在 HttpResponse 类的最初设计中,要求把 Web 服务器端返回的所有内容都保存在这个类的 body 属性中。但是由于 TPTP 的自动化生成需求,这个 body 属性暂时没有用处,TPTP 的开发团队也就暂时没有实现这个功能,所以目前不能从 HttpResponse 对象中读出返回页面的内容。
对于内容验证的缺陷,最直接的办法是等待 TPTP 新版本的发布,可惜的是由于 Eclipse TPTP 项目计划的原因,我们几乎等不到这么一个版本了。在目前的情况下,我们还可以自己动手来修改源文件以实现我们的需求。
我们从 executeRequest 方法作为入口进行分析,其大致调用结构图如下。
图 8. 执行 HTTP 测试过程静态类图
通过研究,不难发现,服务器端返回值的处理是在 HttpRequestHandler 类中的 getServerResponse 方法中进行的,因此我们只要在具体测试项目的源代码中重写这个方法即可;同时我们还要覆盖调用该方法的 HttpExecutor 类。本文给出一个比较简单的实现。
分别构造上面两个类的子类:DHttpRequestHandler 和 DHttpExecutor,并覆盖相关方法。代码如下(省略部分请参考 TPTP 源代码里的实现):
package org.eclipse.hyades.test.http.runner.internal.exec;
public class DHttpRequestHandler extends HttpRequestHandler {
……
// 这里我们覆盖 HttpRequestHandler 的 getServerResponse 方法
public boolean getServerResponse(HttpRequest request, HttpResponse response, \
InputStream inputStream, int bufSize){
……
// 将读到的返回消息放入 content 字符串
String content = null;
while ((bytes_read = inputStream.read(buffer)) != -1){
content.append( new String(buffer, 0, bytes_read, "UTF8") );
……
}
// 设置 response 对象的 body 属性内容为 content 字符串
response.setBody( content.toString() );
}
}
|
package org.eclipse.hyades.test.http.runner;
public class DHttpExecutor extends HttpExecutor {
……
// 这里我们覆盖 HttpExecutor 的 execute 方法
public HttpResponse execute(HttpRequest request) throws Exception
{
……
// 将原来的 HttpRequestHandler 类替换为我们修改后的 DHttpRequestHandler 类
if (httpRequestHandler == null){
httpRequestHandler = new DHttpRequestHandler();
……
}
}
……
}
|
最后,将以上重写的类封装到测试项目中。在对自动生成的 TPTP JUnit 测试文件进行修改时,如果需要对 HTTP 返回的内容进行验证,就可以把 HttpExecute 对象替换自己写的 DHttpExecute 类对象,这样返回的内容就可以由 DHttpExecute 对象的 getBody() 方法得到。在此基础上可以实现对具体返回内容的验证。由于只是简单的继承了 TPTP 两个原有类,所以不会对其它 TPTP 的测试脚本有所影响。
以上对于 TPTP 的应用和扩展也许有一定局限性,但通过这些实践我们可以更充分的理解 TPTP 作为一个测试平台的强大功能和可扩展性。TPTP 这个测试平台给我们提供了丰富的工具,更重要的是,它是一个开源的框架,我们可以通过对其本身的研究来汲取营养,可以挖掘其本身的一些功能模块来从事我们的应用,更可以把另外一个测试环境下的脚本移植成在 TPTP 上可执行的 Java 语言脚本。如何更好的利用这个开源的平台,是一个值得研究的问题。
学习
- Testing, Profiling and Monitoring Web Applications with TPTP:2007 年 Eclipse 开发者大会上对 TPTP 项目介绍的 PPT。
- Java Application Profiling Using TPTP:使用 TPTP 对 Java 应用进行概要分析
- Eclipse Test and Performance Tools Platform:使用 TPTP 对 Java 程序进行概要分析、检视、测试的教程,共 3 部分
- TPTP API Java Doc:TPTP 应用程序接口文档
- TPTP 官方站点
- developerWorks Java 技术专区:这里有数百篇关于 Java 编程各个方面的文章。
讨论