布局引擎视觉测试 (reftest)

布局引擎视觉测试 (reftest) L. David Baron <dbaron@dbaron.org>,Mozilla 公司 2006 年 7 月 19 日

此代码旨在运行 Mozilla 布局引擎的测试。这些测试由一个 HTML(或其他格式)文件以及相同格式的参考文件组成。测试基于清单文件运行,对于每个测试,都会报告 PASS 或 FAIL,如果结果(PASS 或 FAIL)与清单中记录的预期结果不符,则会报告 UNEXPECTED。

会捕获两个测试显示的图像,大多数测试类型都涉及比较这些图像(例如,测试类型 == 或 !=)以确定测试是否通过。测试捕获是在 800 像素宽和 1000 像素高的视口中进行的,因此该区域之外的任何内容都将被忽略(显示的任何滚动条除外)。但是,理想情况下,测试应编写成适合 600x600 的大小,因为我们将来可能希望切换到 600x600 以匹配 http://lists.w3.org/Archives/Public/www-style/2012Sep/0562.html

为什么采用这种方式?

编写 HTML 测试,其中参考渲染也在 HTML 中,比简单地编写一些可以通过将旧版本渲染与新版本渲染进行比较(可能使用旧版本存储的参考图像)进行回归测试的 HTML 片段更难。但是,跨时间进行比较有很大的缺点。

  • 跨时间进行比较要么需要对每个测试运行两次,要么需要适合平台和配置的存储参考图像(通常将测试限制在非常特定的配置中)。

  • 跨时间进行比较可能会由于预期变化而失败,例如,HTML 默认样式表的更改、表单控件外观的更改或默认首选项(如默认字体大小或默认颜色)的更改。

使用明确选择通过标准的测试,允许随时运行测试以查看它们是否仍然通过。

清单格式

测试清单格式是一个纯文本文件。以 "#" 开头的行是注释。可以使用空格后跟 "#" 和注释来注释行。每行非空行(删除注释后)必须是以下之一

包含另一个清单

<skip-type>* include <relative_path>

<skip-type> 是 skip 或 skip-if 项之一(请参阅下面 <failure-type> 中的定义)。如果任何 skip 类型评估为真(即它们是普通的 skip 或它们是 skip-if 且条件评估为真),则跳过 include 语句。否则,指定清单中的 reftests 将包含在运行的 reftests 集中。

测试项

[ <failure-type> | <preference> ]* [<http>] <type> <url> <url_ref>

其中

  1. <failure-type>(可选)是以下之一

    fails

    如果两个渲染的图像不满足 <type> 中指定的条件,则测试通过。

    fails-if(condition)

    如果满足条件,则如果两个渲染的图像不满足 <type> 的条件,则测试通过。如果不满足条件,则如果满足 <type> 的条件,则测试通过。

    needs-focus

    如果 reftest 窗口未获得焦点,则测试失败或超时。

    random

    测试结果是随机的,因此不应在输出中考虑。

    random-if(condition)

    如果满足给定条件,则测试结果是随机的。

    silentfail

    此测试可能会静默失败,如果发生这种情况,则应将其计为测试通过。这对于静默失败是预期行为的情况很有用(例如,在 JavaScript 中的内存不足情况下,我们静默并立即停止运行脚本,希望回收足够的内存以保持浏览器的正常运行)。

    silentfail-if(condition)

    如果满足条件,则此测试可能会静默失败。

    skip

    此测试不应运行。当测试以灾难性的方式失败时(例如,导致浏览器崩溃或挂起)这很有用。使用 skip 比简单地注释掉测试更可取,因为我们希望在测试运行结束时报告测试失败。

    skip-if(condition)

    如果满足条件,则不运行测试。例如,如果测试仅在特定平台上崩溃(即允许我们在其他平台上获得测试覆盖率),这很有用。

    slow

    测试可能需要很长时间才能运行,因此如果启用了慢速测试或未禁用慢速测试,则运行它(测试清单解释器可以选择默认是否运行此类测试)。

    slow-if(condition)

    如果满足条件,则测试将被视为已指定 slow。这对于仅在特定平台上速度慢的测试很有用(例如,一个测试可能会在 32 位系统上执行内存不足行为,但在 64 位系统上速度会异常慢)。

    fuzzy(minDiff-maxDiff,minPixelCount-maxPixelCount)

    如果像素值差异在 minDiffmaxDiff(含)之间,并且不同像素的总数在 minPixelCountmaxPixelCount(含)之间,则允许测试通过。它也可以与 != 一起使用,以确保差异超出指定的区间。请注意,使用 != 测试时,范围的最小边界必须为零。

    模糊测试通常用于两种不同类型的用例。主要用例是预期相等的测试,但实际上以微小的方式失败(例如,抗锯齿差异),我们希望确保测试不会进一步退化,因此我们不想将测试标记为失败。对于这些情况,测试注释应尽可能紧密:如果行为完全确定,则表示类似 fuzzy(1-1,8-8) 的范围,并且如果可能,范围不应包含 0。在测试仅有时失败的情况下,不幸的是,这需要在两个范围中都使用 0,这意味着如果问题已解决,我们将不会收到意外通过的报告(允许我们删除 fuzzy() 注释并期望测试从那时起通过)。

    使用模糊测试的第二个用例是应该允许一定程度的可变性的测试(即规范允许可变性,因此我们无法断言所有像素都相同)。通常应避免此类测试(例如,通过使用另一个元素覆盖可以变化的像素),但在需要时,fuzzy() 注释中的范围通常应包含 0。

    fuzzy-if(condition,minDiff-maxDiff,minPixelCount-maxPixelCount)

    如果满足条件,则测试将被视为已指定 fuzzy。如果在特定平台上存在差异,这很有用。请参阅上面的 fuzzy()

    require-or(cond1&&cond2&&...,fallback)

    要求在运行测试之前执行某些特定设置或使环境条件(例如设置调试模式)为真。如果任何条件未知、未实现或失败,则恢复为备用故障类型。例如:require-or(debugMode,skip)

    asserts(count)

    加载测试和参考已知会断言恰好 count 次。注意:带有非零计数或 maxCount 的 asserts() 注释会抑制对带有注释的测试使用缓存的画布。但是,如果相同测试的后续出现未加注释,则它们将使用缓存的画布(可能是来自断言的加载)。这允许对相同测试或参考的重复使用进行正确的注释(这在使用位于可以独立测试的不同子目录中时可能特别有用),但不会强制它们这样做,也不会强制在公共参考被测试断言时抑制缓存。

    asserts-if(condition,count)

    与上面相同,但仅当条件为真时才执行。

    asserts(minCount-maxCount)

    加载测试和参考已知会在 minCount 和 maxCount 次之间(包含)断言。注意:有关画布缓存,请参见上文。

    asserts-if(condition,minCount-maxCount)

    与上面相同,但仅当条件为真时才执行。

    noautofuzz

    禁用特定平台配置的 reftest 框架中硬编码的自动模糊行为。自动模糊旨在补偿固有的不确定性,这种不确定性会导致在给定平台上的许多/所有测试中出现间歇性的模糊结果(带有少量模糊)。在测试中指定“noautofuzz”将禁用该测试的自动模糊,并需要完全匹配。

    条件是其中不包含空格的 JavaScript 表达式。它们在沙盒中进行评估,沙盒中定义了一组有限的变量。有关详细信息,请参阅 layout/tools/reftest.js 中的 BuildConditionSandbox 函数。

    使用条件的示例

    fails-if(winWidget) == test reference
    asserts-if(cocoaWidget,2) load crashtest
    
  2. <preference>(可选)是以下格式的字符串

    pref(<name>,<value>)

    test-pref(<name>,<value>)

    ref-pref(<name>,<value>)

    其中 <name> 是首选项设置的名称,如 about:config 中所示,而 <value> 是应将此首选项设置为的值。<value> 可以是布尔值(true/false)、整数或带引号的字符串不包含空格,具体取决于首选项的类型。

    在渲染测试和/或参考画布之前,首选项将设置为指定的值(pref() 应用于两者,test-pref() 仅应用于测试,ref-pref() 仅应用于参考),并且之后将恢复,以便后续测试不受影响。请注意,此功能仅适用于“实时”首选项,这些首选项会立即生效,而无需重新启动浏览器。

  3. <http>(如果存在)是以下字符串之一(不带引号)“HTTP”或“HTTP(..)”或“HTTP(../..)”或“HTTP(../../..)”,依此类推,表示应通过 HTTP 服务器运行测试,因为它需要某些 HTTP 标头或特定的 HTTP 状态。(如果您的测试不需要此功能,请不要使用它,因为它会不必要地减慢测试速度。)

    使用“HTTP”时,HTTP 测试具有以下限制:HTTP 测试访问的任何资源都必须使用相对 URL 访问,并且测试和资源必须位于包含描述测试的 reftest 清单的目录中(或其子目录中)。变体“HTTP(..)”等可用于放宽此限制,允许访问父目录等中的资源。

    要修改名为 FOO 的资源的 HTTP 状态或标头,请创建一个名为 FOO^headers^ 的同级文件,其内容如下

    [<http-status>]

    <http-header>*

    <http-status>

    格式为“HTTP ###[ <description>]”的行,其中 ### 表示所需的 HTTP 状态,<description> 表示所需的 HTTP 状态描述(如果有)。如果省略此行,则默认为“HTTP 200 OK”。

    <http-header>

    标准 HTTP 标头行格式的行,即“Field-Name: field-value”。您不能重复使用 Field-Name,并且必须将这些标头合并在一起,并且每个标头必须在单行上指定,否则格式与 HTTP 本身完全匹配。

    HTTP 测试还可以包含 SJS 文件。SJS 文件提供与 CGI 脚本类似的功能,因为它们生成的响应可以取决于传入请求的属性。目前,这些属性仅限于方法类型和标头,但最终在计算生成的响应时,也应该可以检查请求正文中的数据。SJS 文件是一个扩展名为 .sjs 的 JavaScript 文件,它定义了一个全局 handleRequest 函数(每次在 reftests 中加载该文件时都会调用),格式如下

    function handleRequest(request, response)
    {
      response.setStatusLine(request.httpVersion, 200, "OK");
    
      // You *probably* want this, or else you'll get bitten if you run
      // reftest multiple times with the same profile.
      response.setHeader("Cache-Control", "no-cache");
    
      response.write("any ASCII data you want");
    
      var outputStream = response.bodyOutputStream;
      // ...anything else you want to do, synchronously...
    }
    

    有关在 handleRequest 中的请求/响应上可用的哪些函数和属性的详细信息,请参阅 netwerk/test/httpserver/nsIHttpServer.idl 中的 nsIHttpRe(quest|sponse) 定义。

    HTTP 测试还可以使用 example.org URI 来测试跨站点行为。“example.org/filename”将访问与当前 reftest 相同目录中的 filename。(Android 目前未实现。)

  4. <type> 是以下之一

    ==

    如果两个渲染的图像相同,则测试通过。

    !=

    如果两个渲染的图像不同,则测试通过。

    load

    如果页面加载,则测试无条件通过。必须省略 url_ref,并且测试不能标记为失败或随机。(用于测试崩溃、挂起、断言和泄漏。)

    script

    加载的页面在通过以下 API 可访问的 JavaScript 数据结构中记录测试的通过或失败状态。

    getTestCases() 返回一个测试结果对象数组,表示页面执行的测试的结果。

    每个测试结果对象都有两种方法

    testPassed() 如果测试结果对象通过,则返回 true,否则返回 false。

    testDescription() 返回描述测试结果的字符串。

    url_ref 必须省略。测试可以标记为失败或随机。(用于测试 JavaScript 引擎。)

    print

    如果两个渲染的打印输出(作为 PDF)通过应用以下比较相同,则测试通过

    • 两个打印输出生成的页面数必须匹配。

    • 两个打印输出的文本内容必须匹配(光栅化文本与真实文本不匹配)。

    您可以通过在文档元素上设置 reftest-print-range 属性来指定打印范围。示例

    <html reftest-print-range="2-3">
    ...
    

    以下示例将导致单页打印

    <html reftest-print-range="2-2">
    ...
    

    您还可以仅打印选定的元素

    <html reftest-print-range="selection">
    ...
    

    确保在测试中包含实际选择某些内容的代码。

    对比较集的未来添加可能包括

    • 匹配纸张尺寸

    • 验证打印的页眉和页脚

    • 测试元素的(模糊)位置

    • 测试特定与打印相关的 CSS 属性

    print==/!= reftests 之间的主要区别在于,print 使我们能够通过解析输出 PDF 来比较打印结果的结构,而不是截取屏幕截图并比较像素值。这使我们能够测试常见的与打印相关的问题,例如文本在不应该时被光栅化。这种行为上的差异也是为什么它是自己的 reftest 运算符,而不是 ==/!= 的一种类型。将这些打印 reftests 列为 ==/!= 可能会有些误导,因为它们实际上并没有检查像素匹配。

    如果您正在寻找在分页模式下测试布局,请参阅有关分页测试的章节。

  5. <url> 是测试页面的相对文件路径或绝对 URL

  6. <url_ref> 是参考页面的相对文件路径或绝对 URL

<url><url_ref> 之间的唯一区别在于,测试结果仅使用 <url> 报告。

URL 前缀的规范

url-prefix <string>

<string> 将附加到清单中所有后续测试项的相对 <url><url_ref>

<string> 在包含另一个清单时不会附加到相对路径,例如 include <relative_path>.

<string> 不会附加到与模式 /^\w+:/ 匹配的任何 <url><url_ref>。这将防止前缀应用于包含协议(如 data:about:http:)的任何绝对 URL。

虽然 url-prefix 的典型用法预计是清单的第一行,但在清单中的任何位置使用它都是合法的。url-prefix 的后续使用会覆盖任何现有的值。

默认值的规范

defaults [<failure-type> | <preference> | <http>]

其中 <failure-type><preference><http> 在上面定义。

默认设置将用于清单中所有后续测试项。任何特定于测试的设置都将覆盖默认设置,就像一行中的后面项目覆盖前面的项目一样。

不带设置的 defaults 行将重置默认值为为空。

与 url-prefix 一样,defaults 通常会在清单文件的开头使用,以便将其应用于所有测试项,但在清单中的任何位置使用 defaults 都是合法的。后续的 defaults 将重置任何先前的默认设置,并将其覆盖为新的设置。

在 include 行之前设置非跳过默认值是无效的,就像在 include 行本身直接指定非跳过设置是无效的一样。如果清单需要同时使用 defaults 和 include,则 include 应该出现在 defaults 之前。如果需要在清单中稍后指定 include,则可以在 include 之前使用一个空白的 defaults 行来重置默认值。

其他框架(例如不依赖于 XUL 的框架,甚至测试其他布局引擎的框架)可以使用此测试清单格式。

运行测试

要运行给定的 reftest,请使用类似以下内容

./mach reftest <path to individual test or directory>

例如,如果要运行与异步滚动相关的 reftests,请运行以下内容

./mach reftest ./layout/reftest/async-scrolling &> reftest.out

然后在 reftest.out 中搜索/grep“UNEXPECTED”。

提供了两个脚本来将 reftest.out 转换为 HTML。clean-reftest-output.pl 将 reftest.out 转换为简单的 HTML,删除日志中不相关的行。reftest-to-html.pl 将输出转换为 html,这使得更容易直观地检查故障。有关了解 reftest 结果的更多详细信息,请参阅调试故障

可测试区域

此框架能够测试布局引擎的许多方面。它特别适合于测试动态更改处理(通过将静态最终结果作为参考进行比较)和增量布局(将脚本中断的布局与未中断的布局进行比较)。但是,也可以为可以用等效性来描述的许多其他内容编写测试,例如

  • 可以通过将一组复杂的样式规则(使单词变为绿色)的结果与 <span style=”color:green”>word</span> 进行比较来测试 CSS 级联。

  • 可以通过将使用画布绘制的结果与具有所需颜色作为 CSS background-color 的块级元素进行比较来测试 <canvas> 合成运算符。

  • 可以通过将计数器输出的文本与包含写出文本的页面进行比较来测试 CSS 计数器

  • 可以通过将复杂情况与写出边距的情况或通过具有“高度”和透明背景的元素创建边距空间的情况进行比较来测试复杂的边距折叠

当无法通过等效性进行测试时,可以通过非等效性进行测试。例如,测试在包含两个以上单词或三个以上不同单词的情况下的对齐方式很困难。但是,很容易测试对齐文本至少与左对齐、居中对齐或右对齐文本显示不同。

编写测试

在为此框架编写测试时,重要的是测试只能依赖于已知正确且永久的行为。例如,测试不应依赖于默认字体大小、body 元素的默认边距、用于 HTML 的默认样式表、表单控件的默认外观或任何其他可以避免的内容。

通常,实现此目的的最佳方法是使测试和参考在尽可能多的方面相同。例如

良好的测试标记

<div style="color:green"><table><tr><td><span>green
</span></td></tr></table></div>

良好的参考标记

<div><table><tr><td><span style="color:green">green
</span></td></tr></table></div>

错误的参考标记

<!-- 3px matches the default cellspacing and cellpadding -->
<div style="color:green; padding: 3px">green
</div>

错误的测试标记

<!-- span doesn't change the positioning, so skip it -->
<div style="color:green"><table><tr><td>green
</td></tr></table></div>

异步测试:class=”reftest-wait”

通常,reftest 会在内容的 load 事件触发后立即获取给定标记渲染的快照。如果您的测试需要推迟获取快照的时间,它应该确保在 load 事件触发时根元素上存在一个类“reftest-wait”。执行此操作最简单的方法是将其放入标记中,例如

<html class="reftest-wait">

当您的测试准备就绪时,您应该从根元素中删除此类,例如使用以下代码

document.documentElement.className = "";

请注意,在布局测试中,通常只需使用以下方法触发布局即可

document.body.offsetWidth  // HTML example

如果可能,您应该使用此技术而不是使您的测试异步。

失效测试:MozReftestInvalidate 事件

当测试(或参考)使用 reftest-wait 时,reftest 通过 MozAfterPaint 跟踪失效并以与常规窗口重新绘制相同的方式更新测试图像。因此,可以通过设置初始内容,然后在删除 reftest-wait 之前动态修改它来测试与失效相关的错误。但是,务必正确掌握这些动态修改的时间,以避免测试意外通过,因为窗口的完整重新绘制已挂起。为了帮助解决这个问题,reftest 会在 reftest-wait 测试的文档根元素上触发一个 MozReftestInvalidate 事件,此时可以安全地进行应测试失效的更改。该事件冒泡到文档和窗口,因此您也可以在那里设置侦听器。例如,

function doTest() {
  document.body.style.border = "";
  document.documentElement.removeAttribute('class');
}
document.addEventListener("MozReftestInvalidate", doTest, false);

绘制测试:class=”reftest-no-paint”

如果某个元素不应绘制,请在执行失效测试时在其上设置类“reftest-no-paint”。在您的 MozReftestInvalidate 处理程序中导致重新绘制(例如,通过更改 body 的背景颜色)将准确地测试该元素是否被绘制。

显示列表测试:class=”reftest-[no-]display-list”

这些类的工作方式与 reftest-no-paint 类似,但检查元素是否创建了显示项。这些类可用于检查保留显示列表的行为,其中显示列表通过更改增量更新,而不是被丢弃并从头开始重建。

不透明图层测试:class=”reftest-opaque-layer”

如果某个元素应该被分配到一个不透明的 PaintedLayer,则在其上设置类“reftest-opaque-layer”。这会检查在测试的最后一次绘制期间图层是否不透明,无论您的测试是否为失效测试,它都适用。为了通过测试,元素必须具有主帧,并且该帧的显示项必须全部分配到单个绘制图层,而不能分配到其他图层,因此它不能用于创建堆叠上下文(活动或非活动)的元素。

图层化测试:reftest-assigned-layer=”图层名称”

如果两个元素应该被分配到同一个 PaintedLayer,则选择任何字符串值作为图层名称,并在两个元素上设置属性 reftest-assigned-layer=”yourname”。Reftest 将检查所有具有相同 reftest-assigned-layer 值的元素是否共享同一个图层。它还将测试具有不同 reftest-assigned-layer 值的元素是否被分配到不同的图层。与类“reftest-opaque-layer”相同的限制适用:所有元素必须具有主帧,并且该帧的显示项必须全部分配到同一个 PaintedLayer,而不能分配到其他图层。如果不满足这些要求,测试将失败。

截取整个窗口快照:class=”reftest-snapshot-all”

在 reftest-wait 测试中,要禁用失效测试并强制最终快照拍摄整个窗口,请在根元素上设置“reftest-snapshot-all”类。

避免触发刷新:class=”reftest-no-flush”

Reftest 框架通常通过在根元素上调用 getBoundingClientRect 来触发刷新。如果测试的根元素具有类“reftest-no-flush”,则不会执行此操作。

这对于测试合成器线程上的动画很有用,因为刷新会导致主线程样式更新。

缩放测试:reftest-zoom=”<float>”

当测试的根元素具有“reftest-zoom”属性时,在渲染测试时会应用该缩放因子。这对应于桌面“完全缩放”样式缩放。Reftest 文档的宽度将为 800 个设备像素,高度为 1000 个设备像素。Reftest 框架假设 CSS 像素尺寸为 800/zoom 和 1000/zoom。因此,为了获得最佳效果,请选择在计算每个设备像素的 appunit 数量时不需要四舍五入的缩放因子;即缩放因子应能整除 60,以便 60/zoom 为整数。

设置视口大小:reftest-scrollport-w/h=”<int>”

如果根元素上的“reftest-scrollport-w”和“reftest-scrollport-h”属性中的任何一个非零,则将滚动位置钳位视口大小设置为给定的 CSS 像素大小。这不会影响拍摄快照的大小。

设置分辨率:reftest-resolution=”<float>”

如果测试的根元素具有“reftest-resolution”属性,则页面将以指定的分辨率呈现(就像用户捏合缩放到了该比例一样)。请注意,reftest-async-zoom 和 reftest-resolution 之间的区别在于,reftest-async-zoom 仅在合成器中应用比例,而 reftest-resolution 会导致页面以该分辨率绘制。此属性可以与 meta 视口中 initial-scale 标记一起使用,在这种情况下,首先应用 initial-scale,然后 reftest-resolution 更改比例。

此属性需要 pref apz.allow_zooming=true 才能生效。

设置异步滚动模式:reftest-async-scroll 属性

如果在根元素上设置了“reftest-async-scroll”属性,我们将尝试为文档启用异步滚动和缩放。这在许多配置中不受支持。

设置显示端口尺寸:reftest-displayport-x/y/w/h=”<int>”

如果根元素上的“reftest-displayport-x”、“reftest-displayport-y”、“reftest-displayport-w”和“reftest-displayport-h”属性中的任何一个非零,则将显示端口尺寸设置为给定的 CSS 像素边界。这不会影响拍摄快照的大小。

当在根元素上设置了“reftest-async-scroll”属性时,文档中的所有元素都会检查“reftest-displayport-x/y/w/h”,并在这些属性存在时在其上设置显示端口。

测试异步滚动:reftest-async-scroll-x/y=”<int>”

当在根元素上设置了“reftest-async-scroll”属性时,对于任何“reftest-async-scroll-x”或“reftest-async-scroll-y”属性非零的元素,在测试结束时,将给定的偏移量(以 CSS 像素为单位)添加到异步滚动偏移量,然后拍摄快照。

测试异步缩放:reftest-async-zoom=”<float>”

当根元素上存在“reftest-async-zoom”属性时,在测试结束时,将给定的异步缩放添加到任何现有缩放之上,然后拍摄快照。内容不会以新的缩放级别重新渲染。这对应于移动样式的“捏合缩放”样式缩放。这在许多配置中不受支持,任何使用此功能的测试可能都需要在其上使用 pref(apz.allow_zooming,true)。

分页测试:class=”reftest-paged”

现在,错误 374050 的补丁已发布 (https://bugzilla.mozilla.org/show_bug.cgi?id=374050),可以创建在分页上下文中运行的 reftests。

使用的页面大小为 5 英寸宽和 3 英寸高(使用默认的半英寸边距)。这是为了允许测试包含较少的文本,并使整个测试适合屏幕。

有一个 layout/reftests/printing 目录用于分页 reftests;但是,此目录没有任何特殊之处。您可以将分页 reftests 放置在任何合适的位置。

任何分页测试的建议第一行是

<!DOCTYPE html><html class="reftest-paged">
<style>html{font-size:12pt}</style>

根元素上的 reftest-paged 类会触发 reftest 切换到页面模式。建议修复字体大小,尽管不是必需的,因为页面是固定尺寸(以英寸为单位)。如果不存在 reftest-wait 类,则在加载时切换到页面模式;否则,在触发 MozReftestInvalidate 事件后立即切换。

此模式的基础布局支持并不真正完整;它没有使用与实际打印预览/打印完全相同的代码路径。特别是,脚本和框架可能会导致问题;尽管尚未经过测试。也就是说,它应该足以测试与分页相关的布局问题。

进程崩溃测试:class=”reftest-expect-process-crash”

如果您正在运行一个测试,该测试会导致 Electrolysis 下的某个进程作为 reftest 的一部分崩溃,这会导致进程崩溃 minidump 文件留在配置文件目录中。运行 reftests 的测试基础设施会注意到这些 minidump 文件并从中转储信息,并且日志中的这些其他错误消息最终可能会错误地与 reftest 运行的其他错误相关联。它们也很令人困惑,因为测试运行输出中出现“PROCESS-CRASH”消息看起来像是一个真正的问题,而实际上这是预期的行为。

为了指示 reftest 框架某个测试预期进程会崩溃,请在测试完成后,让测试将“reftest-expect-process-crash”作为根元素的类之一。这将导致在运行测试期间生成的任何 minidump 文件被删除,并且它们不会在测试运行输出中导致任何错误消息。

跳过强制内容进程图层树更新:reftest-no-sync-layers 属性

通常,当多进程 reftest 测试结束时,我们强制内容进程在拍摄快照之前将图层树更新推送到合成器。在根元素上设置“reftest-no-sync-layers”属性会跳过此步骤,从而能够测试图层树更新是否正在正确生成。但是,测试必须在结束前手动等待 MozAfterPaint 事件。

SpecialPowers

某些测试可能需要合成用户输入事件或其他通常无法从典型脚本运行的功能。布局 reftests 在此类情况下可以访问SpecialPowers

测试作者可以使用SpecialPowers.getDOMWindowUtils(window)访问特权nsIDOMWindowUtils接口。该接口包含许多有趣的功能,包括事件合成。

调试故障

已创建 Reftest 分析器,以便更容易地调试 reftests。如果 reftest 失败,请将日志上传到 Reftest 分析器以查看预期结果与 reftest 的实际结果之间的差异。Reftest 分析器可以在以下网址找到

https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml