30、测试技术与开源项目的实践探索

测试技术与开源项目的实践探索

一、参考测试框架中的失效测试

在测试领域,参考测试框架有了新的能力——失效测试。当文档的一部分发生变化而其余部分保持完整时,发生变化的部分就被称为“失效”,因为渲染引擎必须重新绘制它。所有的失效测试都是异步测试,这样能让我们完全控制何时对画布进行快照。

为了测试失效情况,我们从渲染引擎捕获一个信号,以此来确定何时可以修改页面使之前的渲染失效。一旦使之前的渲染失效,我们就移除 “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 项目,都在为实现这一目标而努力,未来也将继续在测试领域取得更多的成果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值