【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

Tellurium 自动化测试框架介绍

  • 2010-11-04
  • 本文字数:4979 字

    阅读完需:约 16 分钟

简介

Tellurium 自动化测试框架是由方剑在 2007 年 6 月创建的用于测试 Web 应用的框架,并在 2008 年 6 月移步到 Google Code 成为一个开源项目。它会定期发布版本,当前版本号是0.7.0。项目的核心已经历时两年,并繁衍出了多个子项目,包括:UDL、Core、Engine、Widget 扩展、Maven Archetype、Trump、Tellurium IDE、TelluriumWorks 以及参考项目。

这个框架是从 Selenium 框架发展而来,但又具有不同的测试理念。大多数 Web 测试框架,比如 Selenium,主要致力于单独的 UI 元素。而 Tellurium 恰好相反,它把多个 UI 元素看作一个 Widget 整体,并将其称作 UI module。

拿 Google 搜索的 UI 做个例子,这个界面用 Tellurium 表示成如下这样:

复制代码
ui.Container(uid: "GoogleSearchModule", clocator: [tag: "td"]){  
InputBox(uid: "Input", clocator: [title: "Google Search"])  
SubmitButton(uid: "Search", clocator: [name: "btnG", value: "Google
Search"])  
SubmitButton(uid: "ImFeelingLucky", clocator: [value: "I'm Feeling
Lucky"])
}

正如你在例子中看到的,UI module 是嵌套的 UI 元素、tag 以及 attribute 的集合。Tellurium 在采用了 UI module 之后,更具表述性,对变化的响应也更加智能化。同时它也可以很容易地表示动态 Web 内容,并易于维护。

这个框架由以下组件组成:

  1. Trump——一个 Firefox 插件,全称是 Tellurium UI Module Plugin,它可以在用户选择待测 Web 页面上的 UI 元素后,自动生成 UI module。
  2. Tellurium IDE_——_ 另外一个 Firefox 插件,可以记录用户操作,并生成 Tellurium 测试脚本,包括 UI module 的定义、用户的动作以及断言。测试脚本是用 Groovy 写成的。
  3. TelluriumWorks——一个单独的 Java Swing 应用,用于编辑和运行 Tellurium 测试脚本。另外还在开发一个针对 IntelliJ IDEA 的 IDE 插件。
  4. JavaScript Widget Extensions——针对流行 JavaScript 框架的扩展,比如 Dojo 和 jQuery UI。这样用户就可以在项目中引用发布的 Tellurium jar 文件,并在 UI module 定义中,把 UI widget 当作一个普通的 Tellurium 对象。

特性

主要特性包括:

  1. UI module 清楚地表示了待测的 UI。在 Tellurium 的测试代码中,并没有直接使用定位器(locator)。而是使用 uid 对象来引用 UI 元素,从而更具表现力。比如:
复制代码
type "GoogleSearchModule.Input", "Tellurium test"
click "GoogleSearchModule.Search"
  1. 使用 UI 属性而不是固定的定位器来描述 UI。实际的定位器将会在运行时生成。如果属性改变了,新的运行时定位器也会由框架自动重新生成。Tellurium 从而可以按需自适应 UI 的变化。 Tellurium 0.7.0 中的 Santa 算法通过一次定位整个的 UI module,从而进一步提高测试的智能性。此外还使用了 UI module 部分匹配机制,在一定程度上适应属性的变化。
  2. 采用了 Tellurium UI 模板和 Tellurium UID 描述语言(UDL)来表示动态的 web 内容。
  3. 框架实行 UI module 和测试代码的分离,从而有利于重构。 比如,UI 和对应的测试方法定义在分离的 Groovy 类中。这样,测试代码就和 UI module 解耦了。

另外该框架还:

  • 使用抽象的 UI 对象来封装 Web UI 元素
  • 支持 Widget 以实现可重用性
  • 为 UI 定义、动作和测试提供一门 DSL
  • 支持组定位,从而一次定位一组 UI 组件
  • 包括 CSS 选择器支持,以改善在 IE 中的测试速度
  • 提供定位器缓存和命令集来提高测试速度
  • 支持数据驱动测试

对比 Selenium 和 Tellurium

Selenium Web 测试框架是最流行的开源自动化 web 测试框架之一。它是一款独创性的框架,提供了很多独一无二的特性和优势,比如:基于浏览器的测试、Selenium Grid 以及使用 Selenium IDE 来“录制和回放”用户的动作。

然后,Selenium 有点问题。拿下面这段测试代码举个例子:

复制代码
setUp("http://www.google.com/", "*chrome");
selenium.open("/");
selenium.type("q", "Selenium test");
selenium.click("//input[@value='Google Search' and @type='button']");

如果有人不是很熟悉 Google 的搜索页面,他能根据这段代码,说出页面的 UI 是什么样子的吗?定位器 q 在这里是什么意思呢?

万一因为 Web 的变化,XPath //input[@value=‘Google Search’ and @type=‘button’] 变成无效的了,怎么办?更有可能发生的是,这段代码需要逐行检查才能找出那几行需要更新的代码。

万一这段测试代码里面有几十上百个定位器怎么办?使用 Selenium IDE 生成测试代码,这可能在一开始比较容易,但归纳和重构起来就很困难了。

重构会是一个比从头生成新测试代码更乏味的过程。原因在于硬编码的定位器和使用的测试代码耦合太紧密了。因为测试代码没有结构化,维护代码就变得异常困难。

作为一个低层次 Web 测试驱动框架,Selenium 是一个很好的框架。然而,它需要投入更多的努力才能创建出智能的测试代码。

Tellurium 就是为解决 Selenium 中的大多数问题而诞生的。

Tellurium 同时被设计用来解决 Selenium 的其他弱点。比如,IE 性能一直是 Selenium 突出的问题。Tellurium 的解决方案是,使用 CSS 选择器来作为缺省的定位器。定位器由 UI module 自动生成,并改善了测试速度。

另外,在采用了 Tellurium UI module 缓存以及基于新的 Tellurium 引擎的命令集之后,测试速度得到进一步的提升。Tellurium 还支持对 Ajax 应用的测试:Tellurium 的 List 和 Table UI 对象被用来在运行时表示动态 Web 内容。而 option 对象则被用来在运行时表示同一 Web 元素的两个不同 UI。

与 Selenium 一样,Tellurium 可以用来测试任何基于 HTML DOM 结构的 Web 应用。

测试方法

Tellurium 采用一种新的方式,通过 UI module 的概念来进行自动化测试。使用对象封装 Web UI 的元素,因此不再需要手动生成和重构 UI 的定位器。UI module 是个简单的复合 UI 对象,由嵌套的基本 UI 对象组成。

这个框架可以在两种模式下运行。第一种模式是作为 Selenium 框架的 wrapper 来工作。也就是说,Tellurium core 基于 UI module 中的 UI 对象属性,生成运行时定位器。生成的运行时定位器然后通过 Tellurium 扩展传递给 Selenium core 来调用。

Tellurium 还在开发它自己的驱动引擎,即 Tellurium Engine,以更好更有效地支持 UI module。

  1. 首先,Tellurium Core 把 UI module 转换成 JSON 的表示形式。
  2. 然后在使用 UI module 时,JSON 表示的数据被第一次传递给 Tellurium Engine。
  3. 接着 Tellurium Engine 使用 Santa 算法,定位整个 UI module,并将其存在缓存中。
  4. 在接下来的调用中,会直接使用缓存的 UI module,而不需要重新定位了。
  5. 此外,Tellurium Core 把多条命令合并成一条批处理命令,叫做宏命令,然后在一次调用中把这条批处理发送给 Tellurium Engine。这样可以减少请求 / 响应带来的延迟。

下面这个例子,使用了该项目网站上的问题搜索 UI,来表述框架背后的思想。

我们从为问题搜索的 UI 定义 UI module 开始吧:

复制代码
ui.Form(uid: "issueSearch", clocator: [action: "list", method: "GET"]) {
Selector(uid: "issueType", clocator: [name: "can", id: "can", direct:
"true"])
TextBox(uid: "searchLabel", clocator: [tag: "span", text: "for"])
InputBox(uid: "searchBox", clocator: [type: "text", name: "q", id: "q"])
SubmitButton(uid: "searchButton", clocator: [value: "Search", direct:
"true"])
}

然后使用下面这个测试方法:

复制代码
public void searchIssue(String type, String issue){
select "issueSearch.issueType", type
keyType "issueSearch.searchBox", issue
click "issueSearch.searchButton"
waitForPageToLoad 30000
}

如果有一天,你需要把 Selector 修改成输入框,那我们只需要更新对应的 UI module:

复制代码
ui.Form(uid: "issueSearch", clocator: [action: "list", method: "GET"]) {
InputBox(uid: "issueType", clocator: [name: "can", direct: "true"])
TextBox(uid: "searchLabel", clocator: [tag: "span", text: "for"])
InputBox(uid: "searchBox", clocator: [type: "text", name: "q", id: "q"])
SubmitButton(uid: "searchButton", clocator: [value: "Search", direct: "true"])
}

然后修改命令:

复制代码
select "issueSearch.issueType", type

为:

复制代码
type "issueSearch.issueType", type

其余则保持不变。

如果有动态的 Web 内容,比如 Google Books 的网站,它包含了一个图书分类的列表,每个分类中包含一个图书列表。针对这样 UI 的 UI module 会出奇的简单:

复制代码
ui.Container(uid: "GoogleBooksList", clocator: [tag: "table", id: "hp_table"]) {
List(uid: "subcategory", clocator: [tag: "td", class: "sidebar"], separator:
"div") {
Container(uid: "{all}") {
TextBox(uid: "title", clocator: [tag: "div", class: "sub_cat_title"])
List(uid: "links", separator: "p") {
UrlLink(uid: "{all}", clocator: [:])
}
}
}}

Tellurium UID 描述语言为定义动态 Web 内容提供了更多的灵活性。我们来看个复杂点的例子。

复制代码
ui.StandardTable(uid: "GT", clocator: [id: "xyz"], ht: "tbody"){
TextBox(uid: "{header: first} as One", clocator: [tag: "th", text: "one"], self:
true)
TextBox(uid: "{header: 2} as Two", clocator: [tag: "th", text: "two"], self: true)
TextBox(uid: "{header: last} as Three", clocator: [tag: "th", text: "three"],
self: true)
TextBox(uid: "{row: 1, column -> One} as A", clocator: [tag: "div", class: "abc"])
Container(uid: "{row: 1, column -> Two} as B"){
InputBox(uid: "Input", clocator: [tag: "input", class: "123"])
Container(uid: "Some", clocator: [tag: "div", class: "someclass"]){
Span(uid: "Span", clocator: [tag: "span", class: "x"])
UrlLink(uid: "Link", clocator: [:])
}
}
TextBox(uid: "{row: 1, column -> Three} as Hello", clocator: [tag: "td"], self:
true)
}

在这个例子中,我们是使用元数据“first”、数字和“last”来指定 header 的位置。元数据“{row: 1, column -> One} as A”意味着我们例子中的 UI 元素——一个 TextBox,处于第一行,并和 header“One”处在同一列。测试代码很干净,比如:

复制代码
getText "GT.A"
keyType "GT.B.Input", input
click "GT.B.Some.Link"
waitForPageToLoad 30000

未来计划

Tellurium 是一个年轻而且创新的项目,它具有许多来自开发团队和用户社区的新颖思想。Tellurium 希望在以下领域继续发展:

  1. Tellurium 0.7.0 已经实现了一个新的使用 jQuery 的测试驱动引擎。这个引擎的主要特性包括:UI module 组定位、UI module 缓存、命令集处理、用 jQuery 重新实现的 Selenium API 以及新的 Tellurium API。Tellurium 会继续开发这个新引擎直至完备。
  2. Tellurium IDE module 插件 0.8.0 RC1 刚刚发布,它包含了很多新的特性。录制和生成测试脚本的 Tellurium IDE 的 RC 版本也已发布。它们是 Tellurium 成功的关键,因此会得到持续的改进。除了 Trump 和 Tellurium IDE,Tellurium 还在计划改善 TelluriumWorks,让它可以编辑、完成语法检查,并运行 Tellurium DSL 测试脚本。
  3. Tellurium 作为云测试工具是另外一个非常重要的发展方向。项目团队正在计划重新考虑整个架构,使其可以更直接地并行执行测试。通过 P2P 技术,只需最少的管理,就让测试服务器在云的环境中具备自组织和自协调的能力,这是件极具挑战性的工作。

Tellurium 框架还希望发展的其他领域包括:

  • 创建可重用的 Dojo、ExtJS 和 jQuery UI Tellurium widget。这样可以让其他人只需要在自己的项目中包含对应的 jar 文件,就可以重用这些 widget。
  • 支持行为驱动测试。
  • Web 安全测试
  • 支持其他的语言,比如 Ruby

关于作者

方剑毕业于乔治亚理工学院,电子和计算机工程专业博士学位。他的工作是某 IT 公司的高级软件工程师,致力于设计和实现企业级应用软件。他是 Tellurium 自动化测试框架项目的创建者。

查看英文原文: Introducing the Tellurium Automated Testing Framework


感谢张龙对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2010-11-04 00:006389
用户头像

发布了 127 篇内容, 共 42.1 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
发现更多内容

论分布式数据库TiDB架构的“存”与“算”

TiDB 社区干货传送门

数据库架构设计

MySQL正常执行的SQL在TiDB中变慢了

TiDB 社区干货传送门

管理与运维 故障排查/诊断

基于tidbV6.0探索tiflash在多标签组合场景下的使用

TiDB 社区干货传送门

实践案例 6.x 实践

TiCDC系列分享 Open API与业务系统集成

TiDB 社区干货传送门

应用适配 6.x 实践

基于 TiDB v6.0 部署两地三中心

TiDB 社区干货传送门

实践案例 6.x 实践

TiDB 6.0: 统计信息优化改进

TiDB 社区干货传送门

管理与运维 新版本/特性解读 6.x 实践

TiDB v5.4.0 与 v6.0.0 的 sysbench 性能对比

TiDB 社区干货传送门

性能测评 6.x 实践

一次断电故障引起TiDB无法启动的问题带来的几点思考

TiDB 社区干货传送门

管理与运维 故障排查/诊断

TiDB与MySQL的模糊查询大小写

TiDB 社区干货传送门

开发语言

文件数据导入到TiDB的实践

TiDB 社区干货传送门

TiDB 6.0: 让 TSO 更高效

TiDB 社区干货传送门

实践案例 性能测评 新版本/特性解读 6.x 实践

TiKV 节点重启后业务恢复速度(leader 平衡速度)v6.0 vs v5.1.2对比测试

TiDB 社区干货传送门

版本测评 6.x 实践

一次SSD磁盘寿命耗尽导致的TiDB集群写入变慢问题处理

TiDB 社区干货传送门

故障排查/诊断

TiDB 6.0 Book Rush | TiDB 和 Python 的 CRUD 应用开发实践

TiDB 社区干货传送门

6.x 实践

6.0体验:TiKV 重启后 Leader 均衡加速

TiDB 社区干货传送门

管理与运维 新版本/特性解读 6.x 实践

tiflash 6.0 on K8s 扩容与新特性实践

TiDB 社区干货传送门

版本测评 安装 & 部署 新版本/特性解读 扩/缩容 6.x 实践

TiDB Sysbench 性能对比测试报告 - v5.1.4 对比 v6.0.0 DMR

TiDB 社区干货传送门

6.x 实践

TiDB 查询优化及调优系列(四)查询执行计划的调整及优化原理

TiDB 社区干货传送门

TiCDC系列分享-01-简述产生背景及使用概况

TiDB 社区干货传送门

迁移 安装 & 部署 扩/缩容 应用适配 大数据场景实践

TiDB Lightning在数据迁移中的应用与错误处理实践

TiDB 社区干货传送门

迁移 管理与运维 6.x 实践

TiDB 和 C# 的简单 CRUD 应用程序

TiDB 社区干货传送门

6.x 实践

TiDB 查询优化及调优系列(三)慢查询诊断监控及排查

TiDB 社区干货传送门

TiDB多活方案

TiDB 社区干货传送门

实践案例 集群管理 数据库架构选型 数据库架构设计

基于tidbV6.0探索索引优化思路

TiDB 社区干货传送门

实践案例 6.x 实践

TiDB库表设计和使用规范

TiDB 社区干货传送门

管理与运维

TiFlash 源码阅读(二)计算层概览

TiDB 社区干货传送门

关于HTAP与HSAP

TiDB 社区干货传送门

数据库架构设计

内存悲观锁原理浅析与实践

TiDB 社区干货传送门

版本测评 新版本/特性解读 6.x 实践 TiKV 底层架构

TiDB HTAP特性的应用场景简析

TiDB 社区干货传送门

数据库架构设计

TiCDC系列分享-02-剖析同步模型与基本架构

TiDB 社区干货传送门

迁移 备份 & 恢复 大数据场景实践 实时数仓场景实践 数据中台场景实践

TiDB中如何查看database级别的QPS

TiDB 社区干货传送门

监控

Tellurium自动化测试框架介绍_Java_Jian Fang_InfoQ精选文章