使用开源工具测试 Web 应用程序

如果您使用了云环境,那么测试对于确保应用程序的可靠性至关重要。学习使用开源工具 Selenium、Windmill 和 twill 进行自动化功能测试。本文讨论的技术适用于 Google App Engine、博客软件或自己编写的应用程序。

Noah Gift, 创始人, GiftCS, LLC

Noah Gift 是 O'Reilly 出版的 Python For Unix and Linux System Administration 一书的合著者,并且现在还在为 Manning 编著 Google App Engine In Action 一书。他是一名作家、演说家、顾问和社区负责人,并为 IBM developerWorks、Red Hat MagazineO'Reilly 和 MacTech 撰稿。他的咨询公司的网站是 http://www.giftcs.com,他的个人网站是 http://noahgift.com。 Noah 拥有加州洛杉矶的 CIS 的硕士学位,加州 Poly San Luis Obispo 的营养科学学士学位,他还是通过 Apple 和 LPI 认证的系统管理员,他曾经在许多公司工作过,如加利福尼亚理工学院、Disney Feature Animation、Sony Imageworks 和 Turner Studios。他目前在新西兰的 Weta Digital 工作。在空闲的时候,他喜欢和妻子 Leah 以及他们的儿子 Liam 一起度过,谱写钢琴曲、参加马拉松比赛以及积极地参与体育活动。


developerWorks 投稿作者

2009 年 5 月 07 日

简介

随着应用程序渐渐脱离独立的宿主模型并进入到云中,可靠性和可预测性变得更加重要。在云环境中,有许多因素是我们无法控制的,因此编写健壮的经过测试的代码比以往更加迫切。

twill 和 Google App Engine 介绍

参考资料 小节中,有一篇详尽的文章介绍如何从头构建可以运行的 “Hello World” 应用程序。在 OS X 平台上,您可以下载 Google App Engine Launcher,它将为您创建 “Hello World” 应用程序的模板(boilerplate)文件。

要开始使用 twill,需要运行命令:sudo easy_install twill。接下来,仅需调用 twill-sh 脚本工具交互地测试您的应用程序。

大部分开发人员(不管他们是否测试自己的代码)至少都了解过关于代码测试的课程。Web 开发人员 — 比大部分开发人员更了解代码测试 — 需要快速交付应用程序,因此常常会因为交付期限紧迫而忽略单元测试。在某些流程中,忽略对代码进行单元测试是不妥当的,因为单元测试能够测试应用程序的实际组件,并且向其他开发人员解释代码的内部工作。对 Web 应用程序进行功能测试则是另一回事,并且由于各种原因没有得到重视。

在本文中,我讲解了几个能够帮助您对 Web 应用程序进行功能测试的工具。在这里,我使用的应用程序是 Google App Engine,但这些测试技巧适用于任何 Web 应用程序。我还要强调的是,放弃功能测试并不是总是正确的,因为执行功能测试很快很容易,至少低级的测试是这样的。在本文中,我讲解了 3 个功能测试工具:Windmill、Selenium 和 twill。Windmill 和 Selenium 都是 Web 功能测试框架,它们允许在 Web 浏览器中自动化测试 JavaScript 和 Asynchronous JavaScript and XML (Ajax) 应用程序的用户界面。Twill 是一个轻量级 Web 脚本工具,它负责非-JavaScript 应用程序的功能测试。

使用 twill 进行功能测试

Easy Install

Easy Install 是一个帮助您从本地或网络安装 Python 包的工具。通常使用 easy_install 命令从网络安装包。

我将从轻量级命令行 Web 浏览器和脚本工具(twill)以及默认的 Google App Engine 项目开始讨论功能测试。

首先,建立一个与您的应用程序的连接。为此,需要使用 go 命令,如清单 1 所示。注意,如果您输入 show,它将显示实际的输出结果。

清单 1. 示例 show 输出
# twill-sh
-= Welcome to twill! =-
>> go localhost:8087
==> at http://localhost:8087
current page: http://localhost:8087
>> show
Hello World!
current page: http://localhost:8087

twill 的另一个有趣特性是查看 http 状态代码。

清单 2. 示例 twill 输出 http 状态代码
> go http://localhost:8087
==> at http://localhost:8087
current page: http://localhost:8087
>> code 200
current page: http://localhost:8087
>> code 400
ERROR: code is 200 != 400
current page: http://localhost:8087

从命令的输出可以看到,如果获得的状态代码与预期的代码不匹配,将返回一个错误。twill 还支持以脚本的形式运行这些行为。您可以随意命名该文件并将其传递到 twill-sh。如果将这些命令放到名为 test_twill.script 的文件中,您将看到类似于清单 3 的输出。

清单 3. 更多的示例 twill 输出
# twill-sh test_twill.script
>> EXECUTING FILE test_twill.script
AT LINE: test_twill.script:0
==> at http://localhost:8087
AT LINE: test_twill.script:1
--
1 of 1 files SUCCEEDED.

如果要自动化测试 Web 应用程序的非 JavaScript 部分,那么 twill 是一个非常方便的工具。twill 还有一些我没有提到的特性,比如处理变量、cookie、表单和 http 身份验证等。如果想了解高级的用例,请参阅 参考资料


使用 Selenium 进行功能测试

Selenium 是一个重量级的测试工具,它允许在浏览器中进行跨平台测试。编写跨平台 JavaScript 代码是 Web 开发人员必须忍受的苦差事。编写 Web 应用程序是很困难的,当您认为大功告成时,却发现一些难以觉察的 bug,它们仅在某些浏览器上才表现得明显。

不幸的是,单元测试不能捕捉这种 bug。事实上,这种 bug 通常让 Web 开发人员觉得测试并不可靠。他们认为测试是个苦差事,并且它们有时会延迟产品的交付,况且测试是很不可靠的。所以为什么要多此一举呢?

Selenium(以及其他浏览器测试工具)能够解决这个问题。您可以编写在每个浏览器中运行的功能测试,然后实现一个根据源代码的每次签入运行功能测试的持续集成系统。这样就能快速捕捉浏览器中的潜在 bug,然后进行修复。

Selenium 执行的最基础的工作是记录浏览器行为,然后将结果用于测试。看看图 1 中的示例,您会看到一个包含有 Base URL 的窗口。该窗口记录需要测试的 Web 站点的行为。在这个例子中,我测试的是一个 Google App Engine 站点:http://shell.appspot.com,它是一个用于演示的 Ajax Python 解释器。在记录会话之后,您可以用 Python 导出测试并使用 Selenium 运行它们。

图 1. Selenium IDE 窗口
Selenium IDE 的屏幕截图

为了运行测试,仅需将测试存储为 Python 代码(或其他语言的代码),接着下载并运行 Selenium RC 测试服务器,然后就可以运行测试了。清单 4 是一个测试例子。

清单 4. 示例 Selenium 测试
from selenium import selenium
import unittest, time, re

class NewTest(unittest.TestCase):
    def setUp(self):
        self.verificationErrors = []
        self.selenium = selenium("localhost",
            4444, "*chrome", "http://shell.appspot.com")
        self.selenium.start()

    def test_new(self):
        sel = self.selenium
        sel.open("/")
        sel.click("link=source")
        sel.wait_for_page_to_load("30000")

    def tearDown(self):
        self.selenium.stop()
        self.assertEqual([], self.verificationErrors)

if __name__ == "__main__":
    unittest.main()

您可以启动 Selenium RC,它在多个浏览器上充当测试的代理,然后运行功能测试。清单 5 给出了 Selenium RC 的输出结果。

清单 5. 示例 Selenium RC 输出
# java -jar selenium-server.jar
01:18:47.909 INFO - Java: Apple Inc. 1.5.0_16-133
01:18:47.910 INFO - OS: Mac OS X 10.5.6 i386
01:18:47.915 INFO - v1.0-beta-1 [2201], [1994]
01:18:48.044 INFO - Version Jetty/5.1.x
01:18:48.045 INFO - Started HttpContext[/,/]
01:18:48.047 INFO - Started HttpContext[/selenium-server]
01:18:48.047 INFO - Started HttpContext[/selenium-server/driver]
01:18:48.055 INFO - Started SocketListener on 0.0.0.0:4444
[output suppressed for space]

我希望您阅读完整的 Selenium RC FAQ,以理解它如何与多个浏览器进行交互(参见 参考资料)。如您所见,使用 Selenium 自动化跨平台功能测试非常容易,并且支持很多语言,包括 HTML、Java™ 代码、C#、Perl、PHP、Python 和 Ruby。


Windmill

Windmill 是一个类似于 Selenium 的 Web 测试框架,但也有一些不同之处。一个主要的区别是 Windmill 是用 Python 和 JavaScript 编写的,并且是在 Chandler 项目下开发的。这个开源项目是 Microsoft® Outlook 的有力竞争者。

要开始使用 Windmill,仅需运行命令:sudo easy_install windmill。这将安装 windmill 测试框架。接下来,如果输入 windmill firefox,将打开 Windmill IDE(见图 2)。然后会打开测试页面,如图 3 所示。在图 2 中您可以看到,IDE 记录行为的方式与 Selenium 很相似。然后保存该测试文件,它类似于清单 6 中的输出。

图 2. Windmill IDE 窗口
Windmill IDE 的屏幕截图
图 3. Windmill 教程
Windmill 教程页面截图
清单 6. 示例测试文件输出
# Generated by the windmill services transformer
from windmill.authoring import WindmillTestClient
def test_recordingSuite0():
	client = WindmillTestClient(__name__)
	client.click(id=u'recordedClickId')
	client.click(id=u'textFieldOne')
	client.type(text=u'foo bar', id=u'textFieldOne')
	client.click(id=u'btnSub')

这里有一个选项可以将测试保存为 JSON 或 Python,在本例中我保存为 Python。接下来,仅需从命令行的测试选项运行测试文件,就能够实际运行测试。清单 7 显示了运行测试的代码。

清单 7. 运行测试
# windmill firefox test=windmill_test.py
http://tutorial.getwindmill.com/
Started ['/Applications/Firefox.app/Contents/MacOS/firefox-bin',
'-profile', '/var/folders/1K/
1KgyCzqJHButzT6vq8vwHU+++TI/-Tmp-/tmp_ovtnN.mozrunner',
'http://tutorial.getwindmill.com/windmill-serv/start.html']
Server running...

您可以对这个例子稍作修改,就可用于 Google App Engine 应用程序或其他 Web 应用程序。Windmill 还提供出色的文档,解释如何执行高级任务,比如使用插件扩展 Windmill。


结束语

功能测试对 Web 开发过程十分重要。如果没有功能测试,Web 开发就像猜谜游戏一样,容易出现错误的部署和重构。

那么,是不是所有 Web 开发人员都必须执行功能测试呢?我认为是这样的,所有 Web 应用程序都应该接受测试,尤其是在云环境中使用的应用程序。不对 Web 应用程序进行功能测试是很危险的,并且用 Selenium、Windmill 和 twill 进行最低级别的测试是非常容易的。在此引用 twill 的作者 Titus Brown 的话结束本文 “如果没有测试代码,您怎么知道它能正常工作呢?”。


下载

描述名字大小
本文的示例代码functional_testing_code.zip7KB

参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development, Open source
ArticleID=387900
ArticleTitle=使用开源工具测试 Web 应用程序
publish-date=05072009