软件测试技术:突变测试与参考测试的魅力
1. 突变测试的崛起
随着科技的不断进步,计算能力持续提升,这使得我们有能力承担突变测试所带来的巨大计算需求。现代的测试用例生成器能够较为轻松地自动实现高覆盖率,但生成的测试用例质量仍有待提高。不过,我们拥有多种动态和静态优化方法,这些方法让突变测试不仅效率可观,而且在改进测试套件方面效果显著。
种种迹象表明,突变测试在未来将变得更加普遍。如今,首批可扩展的突变测试工具已问世,大家可以亲自尝试,感受突变测试的魅力。
2. 参考测试:美丽的测试方式
自动化回归测试通常不被认为具有美感。因为若自动化测试成功,它应在人们的意识之外运行,系统会在每次构建后自动运行数千个测试,无需人工干预。自动化测试往往与成熟项目的维护阶段相关,显得不够吸引人。
然而,在测试网络技术时,我们需要在这些技术被开发者广泛采用之前就对其行为和技术进行测试。以 Mozilla 项目为例,我们正借助自动化回归系统,将回归测试从被动模式转变为更具前瞻性的预期式测试。
我们的目标是在互联网上建立并支持开放性、创新性和机会。为此,我们开发了一个平台,以符合我们理想中互联网愿景的方式提供开放的网络技术。其中,Firefox 浏览器是我们工作的杰出代表,此外还有 Thunderbird、Komodo、Miro 和 Songbird 等基于同一基础构建的产品。这些产品功能多样,但都依赖于 Gecko 网络渲染引擎。
在 Mozilla 平台中,用户界面元素使用基于 XML 的标记语言 XUL 进行编码。这种标记语言借助 JavaScript 实现元素交互,并使用与网站相同的级联样式表。XHTML 是 XML 版的 HTML,与 XUL 有一定关联,甚至可以用 XUL 编写网页。正因如此,标准网页和 Mozilla 平台应用的用户界面元素都由 Gecko 渲染引擎渲染。所以,Gecko 渲染引擎对支持开放网络至关重要,其任何变化都会对下游应用产生重大影响。
3. 参考测试的核心组件
参考测试作为我们的可视化测试框架,是利用简单性和可扩展性,通过回归框架进行预期式测试的典范。要将参考测试的经验应用到自己的测试基础设施中,需要了解以下三个核心组件:
-
优雅地解决问题
:以简洁有效的方式应对测试中的各种问题。
-
体现可扩展性
:能够适应不断变化的网络环境和技术需求。
-
建立社区
:促进开发者之间的交流与合作,共同提升测试质量。
4. 参考测试的结构
参考测试基于一个简单的理念:使用两段不同的网页代码生成相同的视觉渲染效果。若渲染结果存在差异,则测试失败。
例如,测试一个带有样式规则
<div style="font-weight:bolder">
的元素,应与参考文件中的
<div><b>
HTML 标记产生相同的加粗效果,如下表所示:
| 测试 | 参考 |
| — | — |
|
<div style="font-weight: bolder">This is bold</div>
|
<div><b>This is bold</b></div>
|
| This is bold | This is bold |
若要测试 CSS 样式和选择器,可使用 CSS 选择器控制测试的渲染,同时使用内联样式控制元素的渲染,如下表所示:
| 测试 | 参考 |
| — | — |
|
<html><head><style type="text/css">div.headline {font-weight: bolder}</style></head><body><div class="headline">This is bold</div></body></html>
|
<html><body><div style="font-weight: bolder">This is bold</div></body></html>
|
| This is bold | This is bold |
参考测试由清单文件控制,这些文件可以嵌套其他清单文件,方便在整个源代码树中嵌套测试。清单文件的格式如下:
== test1.html test1-ref.html
!= test2.xhtml test2-ref.xhtml
fails-if (MOZ_WIDGET_TOOLKIT=="windows") == test3.html test3-ref.html
每个测试项的格式为:
[<known-failure>] [<http>] <type> <test url> <reference url>
,其中类型、测试 URL 和参考 URL 是必需的参数。
==
表示渲染结果必须匹配测试才能通过,
!=
则表示渲染结果必须不同测试才能通过。可选参数
<known-failure>
可让我们根据不同情况预期测试失败和断言,
<http>
表示测试依赖特定的 HTTP 头或状态,需在 HTTP 服务器上运行。
测试框架读取清单文件,为相关测试文件及其参考文件生成一组画布元素。测试运行时,每个文件会加载到浏览器窗口的
<canvas>
元素中。当文档的
onload
事件触发时,会调用以下代码:
function DocumentLoaded()
{
... Some Housekeeping Stuff ...
if (gURICanvases[gCurrentURL]) {
gCurrentCanvas = gURICanvases[gCurrentURL];
} else if (gCurrentCanvas == null) {
InitCurrentCanvasWithSnapshot();
}
if (gState == 1) {
gCanvas1 = gCurrentCanvas;
} else {
gCanvas2 = gCurrentCanvas;
}
gCurrentCanvas = null;
resetZoom();
switch (gState) {
case 1:
// First document has been loaded.
// Proceed to load the second document.
StartCurrentURI(2);
break;
case 2:
// Both documents have been loaded. Compare the renderings and see
// if the comparison result matches the expected result specified
// in the manifest.
// number of different pixels
var differences;
// whether the two renderings match:
var equal;
if (gWindowUtils) {
differences = gWindowUtils.compareCanvases(gCanvas1, gCanvas2, {});
equal = (differences == 0);
} else {
differences = -1;
var k1 = gCanvas1.toDataURL();
var k2 = gCanvas2.toDataURL();
equal = (k1 == k2);
}
// And then we use the manifest token to determine how to interpret
// the result of the compareCanvases call....
...
若框架判断比较结果与清单文件不符,则测试失败。测试失败时,测试画布和参考画布会被序列化为数据 URL 记录在测试日志中,方便日志查看器通过叠加测试图像和参考图像,直观展示问题所在。
5. 参考测试的可扩展性
测试框架通常比被测试的应用程序寿命更长,因此可扩展性是其设计的关键属性。对于参考测试而言,可扩展性尤为重要,因为它需要不断适应不断变化的开放网络。早期简单的参考测试已无法满足如今复杂网页行为的测试需求,参考测试必须不断进化,以维护渲染引擎的全面测试套件。
5.1 异步测试
如今的网络不再是静态的,网页会动态修改 DOM,添加或删除元素和样式规则,浏览器需要实时适应这些变化。为了测试这种行为,“reftest - wait” 测试应运而生。在这类测试中,文档的
onload
事件触发时,渲染的画布不会立即发送到
compareCanvas
函数。测试作者通过 JavaScript 告知参考测试框架何时对文件进行快照以进行比较,这使得我们能够像许多网页一样利用标准的
onload
处理程序编写测试。
以下是一个异步参考测试的示例:
| 测试 | 参考 |
| — | — |
|
<!DOCTYPE HTML><html class="reftest - wait"><head><style>body::before { content:"Before"; border:inherit; }.cl::after { display:block; content:"After"; }</style><script>function fixupDOM() { document.body.setAttribute("style", "border:2px solid red;"); document.body.className = "cl"; document.documentElement.className = ""; }</script></head><body onload="fixupDOM()"></body></html>
|
<!DOCTYPE HTML><html><body style="border:2px solid red;"><span style="border:2px solid red;">Before</span><div>After</div></body></html>
|
在这个测试中,
<html>
元素的
class
属性值为 “reftest - wait” ,告知系统这是一个异步测试。参考测试子系统会监听该属性值的变化。
<body>
元素的
onload
事件会调用
fixupDOM
函数,该函数会修改
body
标签的样式,触发 CSS 系统生成内容。最后,
document.documentElement.className = ""
这行代码清除
<html>
标签的
class
属性,通知参考测试框架进行画布快照。若未清除该值,测试将超时并标记为失败。参考文件是一个静态 HTML 页面,包含与测试最终状态匹配的标记,由于是静态页面,无需设置 “reftest - wait” 标志。
5.2 打印测试
在当今数字化时代,虽然越来越多的内容实现了在线化,但打印功能对于现代浏览器仍然至关重要。打印涉及到不同的渲染方式,如页边距设置、分页和颜色模型等。随着网站复杂度的增加,网页可以使用 CSS 的
@media
规则包含特定的打印样式规则,这为页面渲染带来了新的可能性,也需要进行相应的测试。
“reftest - print” 类测试可用于测试各种打印配置。其语法与异步测试相似,但机制不同。以下是一个打印参考测试的示例:
| 测试 | 参考 |
| — | — |
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html class="reftest - print"><title>Height test</title><div style="top: 0; left: 0; right: 0; position: fixed; height: 100%; border - left: 2em blue solid;">The left border of this box must span the entire page content area. This box must be repeated on the second page.</div><p style="page - break - before: always;">...</html>
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html class="reftest - print"><title>Height test</title><style type="text/css">html, body { height: 100%; margin: 0; padding: 0;}</style><div style="height: 100%; border - left: 2em blue solid;">The left border of this box must span the entire page content area. This box must be repeated on the second page.</div><div style="height: 100%; border - left: 2em blue solid;">The left border of this box must span the entire page content area. This box must be repeated on the second page.</div></html>
|
“reftest - print” 类定义了特定的页面布局,强制页面按照 3 × 5 英寸索引卡的格式渲染。由于其目的是改变画布大小,因此测试和参考标记中都需要包含该类。与异步测试不同,无需移除 “reftest - print” 值。这个测试确保了根元素的总页面高度计算正确,通过设置高度为 100%,总高度取决于根元素的高度。如果计算正确,测试标记中的
<div>
元素将跨两页显示。
综上所述,突变测试和参考测试在软件测试领域都具有重要的价值。突变测试借助计算能力的提升和优化方法,未来有望得到更广泛的应用;参考测试则通过简单而有效的设计理念和良好的可扩展性,为网络技术的测试提供了强大的支持。无论是突变测试还是参考测试,都在不断发展和完善,以适应日益复杂的软件环境,保障软件的质量和稳定性。
6. 参考测试的社区建设
参考测试不仅仅是一种技术手段,更是一个社区驱动的项目。建立社区对于参考测试的发展和推广至关重要,它能够促进开发者之间的交流与合作,共同提升测试质量。以下是社区建设在参考测试中的一些体现:
-
知识共享
:社区成员可以分享自己在参考测试中的经验、技巧和最佳实践。通过论坛、博客、技术会议等渠道,大家可以互相学习,避免重复劳动,提高测试效率。
-
问题反馈
:社区为开发者提供了一个反馈问题的平台。当遇到测试中的困难或发现参考测试框架的缺陷时,开发者可以及时在社区中提出,以便得到其他成员的帮助和开发者的修复。
-
贡献代码
:社区鼓励开发者为参考测试框架贡献代码。无论是修复漏洞、添加新功能还是优化现有代码,社区成员的贡献都能够推动参考测试框架的不断发展和完善。
7. 参考测试的应用场景
参考测试在多个领域都有广泛的应用,以下是一些常见的应用场景:
-
浏览器兼容性测试
:随着不同浏览器和设备的不断涌现,确保网页在各种环境下的显示效果一致变得至关重要。参考测试可以通过比较不同浏览器或设备上的渲染结果,发现并解决兼容性问题。
-
网页更新测试
:当网页进行更新时,参考测试可以快速验证更新是否影响了页面的视觉效果。通过与之前的参考渲染进行比较,能够及时发现并修复因更新导致的显示问题。
-
新特性测试
:在开发新的网页特性时,参考测试可以帮助开发者验证新特性的正确性。通过设置相应的参考渲染,测试新特性是否按预期工作。
8. 参考测试的工作流程
参考测试的工作流程可以概括为以下几个步骤:
graph LR
A[编写测试代码和参考代码] --> B[配置清单文件]
B --> C[运行测试框架]
C --> D{比较渲染结果}
D -- 匹配 --> E[测试通过]
D -- 不匹配 --> F[测试失败]
F --> G[记录失败信息]
G --> H[分析问题并修复]
H --> A
- 编写测试代码和参考代码 :根据测试需求,编写相应的网页代码作为测试代码和参考代码。确保参考代码能够代表预期的渲染结果。
-
配置清单文件
:在清单文件中指定测试代码和参考代码的对应关系,以及测试的类型(如
==或!=)和其他可选参数。 - 运行测试框架 :启动参考测试框架,框架会根据清单文件加载测试代码和参考代码,并进行渲染。
- 比较渲染结果 :框架会比较测试代码和参考代码的渲染结果,判断是否符合清单文件中指定的条件。
- 处理测试结果 :如果渲染结果匹配,测试通过;如果不匹配,测试失败。测试失败时,框架会记录失败信息,方便后续分析和修复。
- 分析问题并修复 :根据测试失败的信息,分析问题的原因,并对代码进行修复。修复后,重新进行测试,直到测试通过。
9. 参考测试与其他测试方法的比较
参考测试与其他常见的测试方法相比,具有以下特点:
| 测试方法 | 优点 | 缺点 |
| — | — | — |
| 参考测试 | - 直观:通过比较视觉渲染结果,能够直接发现显示问题。
- 可扩展性强:能够适应不断变化的网络技术。
- 简单易用:基于简单的理念,容易理解和实现。 | - 依赖视觉效果:对于一些非视觉的功能测试效果不佳。
- 可能存在误判:由于视觉效果的判断可能存在主观性,可能会出现误判的情况。 |
| 单元测试 | - 粒度细:能够对代码的最小单元进行测试,发现问题的根源。
- 执行速度快:可以快速执行大量的测试用例。 | - 缺乏整体视角:只关注代码的局部功能,可能无法发现整体的显示问题。 |
| 集成测试 | - 验证组件间交互:能够测试不同组件之间的交互是否正常。 | - 复杂度高:随着组件数量的增加,测试的复杂度会显著提高。 |
10. 总结与展望
参考测试作为一种可视化的测试框架,以其简单性、可扩展性和社区驱动的特点,在软件测试领域发挥着重要的作用。它能够帮助开发者及时发现网页渲染中的问题,确保网页在各种环境下的显示效果一致。同时,参考测试的可扩展性使其能够适应不断变化的网络技术,为开放网络的发展提供了有力的支持。
未来,随着网络技术的不断发展,参考测试也将面临新的挑战和机遇。一方面,网页的复杂度将不断增加,参考测试需要进一步提升其性能和功能,以应对更复杂的测试需求。另一方面,人工智能和机器学习等技术的发展可能会为参考测试带来新的思路和方法,例如通过自动化的图像识别和分析技术,提高测试的准确性和效率。
总之,参考测试在软件测试领域具有广阔的发展前景。通过不断地改进和创新,参考测试将继续为保障软件质量和推动开放网络的发展做出贡献。同时,开发者也应该积极参与到参考测试的社区建设中,共同推动参考测试技术的进步。
超级会员免费看
32

被折叠的 条评论
为什么被折叠?



