测试技术与开源项目的实践探索
一、参考测试框架中的失效测试
在测试领域,参考测试框架有了新的能力——失效测试。当文档的一部分发生变化而其余部分保持完整时,发生变化的部分就被称为“失效”,因为渲染引擎必须重新绘制它。所有的失效测试都是异步测试,这样能让我们完全控制何时对画布进行快照。
为了测试失效情况,我们从渲染引擎捕获一个信号,以此来确定何时可以修改页面使之前的渲染失效。一旦使之前的渲染失效,我们就移除 “reftest - wait” 值,允许进行快照拍摄。
一个简单的失效测试示例是,用一个不透明形状覆盖文档的一部分,然后移除该形状,使被覆盖的背景重新绘制。我们将这样的测试与没有覆盖形状的页面静态渲染进行比较。
以下是参考文件和测试文件的代码示例:
参考文件(Example 19 - 3) :
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN>
<html>
<head>
<style>
html, body {margin: 0px;}
#textdiv {height: 100px; width: 100px; border: solid green;}
</style>
</head>
<body>
<div id="textdiv">The quick brown fox jumped over the lazy dog and it bit
him</div>
</body>
</html>
测试文件(Example 19 - 4) :
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN>
<html class="reftest-wait">
<head>
<style>
html, body {margin: 0px;}
#textdiv {height: 100px; width: 100px; border: solid green;}
#block {position: fixed; top: 40px; left: 40px; width: 100px;
height: 100px; background: red;}
#textdiv + div.disappear {display: none;}
</style>
<script>
function doTest(){
document.getElementById("block").setAttribute("class", "disappear");
document.documentElement.removeAttribute("class");
}
document.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</head>
<body>
<div id="textdiv-id001">The quick brown fox jumped over the lazy dog and it bit
him</div>
<div id="block"></div>
</body>
</html>
当移除红色块后,句子被简单的绿色边框包围,与参考文件相匹配。
二、构建社区与测试框架的发展
在 Mozilla 项目中,我们所做的一切都鼓励全球对实现开放网络感兴趣的社区参与。这对我们所有的测试框架都有实际意义,我们努力使每个测试框架尽可能简单,便于运行、理解和创建测试。
这对 Mozilla 测试社区有具体的好处。当我们的错误分类团队发现网页问题时,他们可以将问题缩小到最小测试用例,这些最小测试用例可以轻松添加到参考测试框架中。开发者也可以轻松编写测试,以确定他们的修复或新功能是否按设计工作。
为了使回归测试从被动变为主动,我们进一步开展了实时网站比较项目。该项目的主要动机之一是了解新一代 HTML 5 解析器对网站的影响。这个实时比较引擎建立在参考测试框架之上。
我们还计划邀请网页开发者提交他们网站部分的测试,例如复杂导航系统的测试标记或包含导航代码的页面链接。如果测试标记及其之前的渲染在两个 Firefox 里程碑版本之间发生变化,我们将发出通知。
此外,我们将参考测试提交给各种 W3C 小组,以促进 CSS 和 SVG 等技术的互操作性测试套件的发展。我们还在其他网页浏览器上运行自己的参考测试,不断拓展回归框架的能力,使其对网页开发者有用,并成为测试未来网络技术的机制。
三、Clam Anti - Virus 项目概述
Clam Anti - Virus(ClamAV)是一个用于 Unix 的开源杀毒工具包,用 C 语言编写,遵循 GNU GPLv2 许可。该项目始于 2002 年,五年后被 Sourcefire 收购,现已成为开源安全领域的关键参与者。
ClamAV 由国际开发团队维护,提供杀毒引擎库(libclamav)以及一系列相关工具,包括命令行扫描器(clamscan)和多线程扫描守护进程(clamd)。扫描器与包含超过 580,000 条条目的病毒签名数据库相结合。
其主要目标是与邮件服务器集成进行电子邮件扫描,这使其成为关键任务应用程序,扫描必须稳定可靠,以免影响合法邮件的传递。此外,扫描器还可用于多种其他用途,目前有超过 100 个第三方应用程序扩展了 ClamAV 的功能,提供各种形式的实时扫描、HTTP 流量检查或与 FTP 等服务的集成。
四、ClamAV 的测试方法
ClamAV 项目使用多种黑盒和白盒测试方法,以尽可能消除错误,提升用户体验。
(一)黑盒与白盒测试
- 黑盒测试 :将软件视为一个神秘对象,其内部结构和设计未知。它接收输入数据,处理后输出结果。当程序能够处理数据并给出预期结果时,单个测试被认为是成功的。黑盒测试基于软件规范。
- 白盒测试 :需要了解软件的内部实现,专注于测试程序中的特定路径。测试用例需要程序员精心选择,覆盖所有重要的代码单元。
虽然黑盒和白盒测试方法互补,但都有局限性,实际中很难完全测试程序。因此,需要创造性地设计有效的测试用例,在软件到达用户之前检测问题。
(二)静态分析
静态分析是一种白盒测试方法,无需执行代码。其目的是查找常见的编程错误,确保源代码符合所有重要要求和标准。分析可以手动或自动进行,由于手动代码检查非常繁琐,开发者通常使用专业的自动化代码分析工具,基于语法、语义和数据流分析等技术进行检查。
- GCC :是常用的静态分析工具之一。在 ClamAV 项目中,GCC 在编译阶段进行语法和语义检查。语法错误会导致编译失败,程序员必须修复才能编译应用程序。语义分析在语法检查之后进行,关注程序内部设计的正确性,包括作用域检查和类型检查等。GCC 还会进行数据流分析等其他检查,提供许多选项来微调错误检测。重要的是仔细分析警告并尽可能修复它们,无警告的代码更易于维护且不易出错。
- Clang Static Analyzer :是 Low Level Virtual Machine(LLVM)项目的一部分,虽然仍在大力开发中,但已能成功检测空指针和未定义指针解引用、除零错误、无效函数调用、未初始化参数等问题。其优势在于输出格式,为源代码中检测到的每个错误创建 HTML 报告,包含行号、彩色语法和完整的问题描述,开发者可以轻松找到错误的根源。
- Splint :在编译器配备高级代码分析器之前,程序员主要依赖外部工具,如 Lint。现在推荐的是 Splint,它除了进行传统的语义检查外,还能检测与安全相关的问题,如空指针解引用、内存管理错误、缓冲区溢出等。但 Splint 非常敏感,可能会报告大量可能的问题,并且在解析更复杂的文件时可能会有问题,因此通常需要单独检查要审查的代码部分。
需要注意的是,所有静态分析工具都不完美,可能会产生虚假报告或未检测到某些问题。虚假警告通常可以通过特殊选项或注释受影响的代码行来抑制。
(三)内存检查
内存管理错误是常见的软件错误,在大型项目中几乎难以避免。常见的错误包括内存泄漏、使用未声明或已释放的内存、越界写入或双重释放等。内存相关问题的症状可能各不相同,基本情况下会导致程序崩溃(由段错误引起)且可重复,但也可能难以重现且不确定。
幸运的是,有一些高级内存调试工具可以节省大量时间,ClamAV 项目常用的有 Valgrind、Electric Fence 和 DUMA、Mudflap。
- Valgrind :功能强大且易于使用,其主要优点是无需修改要测试的应用程序,直接处理二进制文件,支持任何语言编写的程序。它不仅是内存调试器,还是一个完整的套件,提供缓存和堆分析或同步问题检测工具。原始版本仅支持特定硬件平台上的 Linux,但有非官方端口可用于其他系统。由于它模拟 CPU,执行速度会显著减慢,最坏情况下可能慢达 50 倍,因此有一台快速的机器会很有帮助。
以下是 Valgrind 报告 ClamAV 0.92 中压缩可执行文件解包器内存损坏的示例:
==18030== Invalid write of size 1
==18030== at 0x4E6D92A: unmew (packlibs.c:300)
==18030== by 0x4E6F5DA: unmew11 (mew.c:799)
==18030== by 0x4E61FE0: cli_scanpe (pe.c:1155)
==18030== by 0x4E47F6A: cli_magic_scandesc (scanners.c:2234)
==18030== by 0x4E498F0: cl_scandesc (scanners.c:2264)
==18030== by 0x405737: checkfile (manager.c:651)
==18030== by 0x40675A: scanfile (manager.c:1093)
==18030== by 0x40733D: scanmanager (manager.c:371)
==18030== by 0x404EA5: main (clamscan.c:213)
==18030== Address 0x67594f0 is 0 bytes after a block of size 12,288 alloc'd
==18030== at 0x4C216F4: calloc (vg_replace_malloc.c:397)
==18030== by 0x4E42CD9: cli_calloc (others.c:330)
==18030== by 0x4E61DF5: cli_scanpe (pe.c:1123)
综上所述,无论是参考测试框架的失效测试,还是 ClamAV 项目的多种测试方法,都体现了测试在软件开发和维护中的重要性,通过不断优化测试方法和工具,可以提高软件的质量和稳定性。
测试技术与开源项目的实践探索
五、测试方法总结与对比
为了更清晰地了解 ClamAV 项目中使用的各种测试方法,下面通过表格的形式对它们进行总结和对比。
| 测试方法 | 类型 | 特点 | 优势 | 局限性 |
|---|---|---|---|---|
| 黑盒测试 | 基于软件规范 | 将软件视为黑盒,关注输入输出结果 | 不依赖内部实现,可从用户角度测试 | 难以覆盖所有情况,不能发现内部逻辑错误 |
| 白盒测试 | 基于内部实现 | 了解软件内部结构,测试特定路径 | 能深入测试代码逻辑,发现潜在问题 | 需要专业知识,测试用例设计复杂 |
| 静态分析(GCC) | 白盒测试 | 编译阶段进行语法和语义检查 | 能及时发现基本编程错误,优化代码 | 依赖编译器,可能无法发现运行时错误 |
| 静态分析(Clang Static Analyzer) | 白盒测试 | 检测多种编程错误,输出 HTML 报告 | 详细定位错误,便于修复 | 仍在开发中,可能存在未完善之处 |
| 静态分析(Splint) | 白盒测试 | 检测安全相关问题 | 增强代码安全性 | 敏感易产生误报,解析复杂文件有困难 |
| 内存检查(Valgrind) | 动态分析 | 无需修改应用程序,检测内存问题 | 功能强大,支持多种语言 | 执行速度慢 |
从这个表格中可以看出,不同的测试方法各有优劣,在实际应用中需要根据具体情况选择合适的测试方法,或者结合多种方法进行全面测试。
六、测试流程与实践建议
在实际的项目开发中,为了确保软件的质量,需要建立一套完善的测试流程。以下是一个基于上述测试方法的测试流程示例:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B(需求分析):::process
B --> C(设计测试用例):::process
C --> D{选择测试方法}:::decision
D -->|黑盒测试| E(执行黑盒测试):::process
D -->|白盒测试| F(执行白盒测试):::process
D -->|静态分析| G(执行静态分析):::process
D -->|内存检查| H(执行内存检查):::process
E --> I(分析测试结果):::process
F --> I
G --> I
H --> I
I --> J{是否通过测试}:::decision
J -->|是| K(发布软件):::process
J -->|否| L(修复问题):::process
L --> C
K --> M([结束]):::startend
这个流程图展示了一个完整的测试流程,从需求分析开始,设计测试用例,选择合适的测试方法进行测试,分析测试结果,根据结果决定是否通过测试。如果未通过测试,则需要修复问题并重新进行测试。
在实践中,还可以给出以下建议:
1.
早期介入
:测试应该在项目的早期阶段就介入,从需求分析开始就参与进来,这样可以更好地理解项目的目标和要求,设计出更有效的测试用例。
2.
多样化测试
:不要依赖单一的测试方法,结合多种测试方法可以更全面地发现问题。例如,在开发过程中先进行静态分析,发现基本的编程错误,然后进行黑盒和白盒测试,验证功能和逻辑的正确性,最后进行内存检查,确保内存管理的安全性。
3.
持续测试
:测试不是一次性的工作,应该贯穿整个项目的生命周期。在每次代码变更后都进行测试,及时发现新引入的问题。
4.
自动化测试
:对于一些重复性的测试任务,可以考虑使用自动化测试工具,提高测试效率和准确性。
七、未来展望
随着技术的不断发展,测试领域也在不断创新。对于像 Mozilla 项目和 ClamAV 项目这样致力于推动开源软件发展的项目来说,未来还有很多可以探索的方向。
在参考测试框架方面,实时网站比较项目有着很大的潜力。通过不断优化实时比较引擎,可以更准确地评估 HTML 5 解析器等新技术对网站的影响。同时,邀请更多的网页开发者参与测试,可以收集到更广泛的测试用例,进一步完善测试套件。
对于 ClamAV 项目,随着病毒技术的不断演变,需要不断更新病毒签名数据库,提高检测的准确性和效率。同时,也可以探索新的测试方法和工具,以应对日益复杂的安全挑战。
此外,随着人工智能和机器学习技术的发展,可以考虑将这些技术应用到测试领域。例如,利用机器学习算法自动生成测试用例,或者通过人工智能分析测试结果,预测潜在的问题。
总之,测试技术在软件开发和维护中起着至关重要的作用。通过不断探索和创新,我们可以提高软件的质量和安全性,为用户提供更好的体验。无论是 Mozilla 项目还是 ClamAV 项目,都在为实现这一目标而努力,未来也将继续在测试领域取得更多的成果。
超级会员免费看

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



