| # Reftests |
| |
| Reftests are one of the primary tools for testing things relating to |
| rendering; they are made up of the test and one or more other pages |
| ("references") with assertions as to whether they render identically |
| or not. This page describes their aspects exhaustively; [the tutorial |
| on writing a reftest](reftest-tutorial) offers a more limited but |
| grounded guide to the process. |
| |
| ## How to Run Reftests |
| |
| Reftests can be run manually simply by opening the test and the |
| reference file in multiple windows or tabs and flipping between the |
| two. In automation the comparison is done in an automated fashion, |
| which can lead to differences hard for the human eye to notice to |
| cause the test to fail. |
| |
| ## Components of a Reftest |
| |
| In the simplest case, a reftest consists of a pair of files called the |
| *test* and the *reference*. |
| |
| The *test* file is the one that makes use of the technology being |
| tested. It also contains a `link` element with `rel="match"` or |
| `rel="mismatch"` and `href` attribute pointing to the *reference* |
| file, e.g. `<link rel=match href=references/green-box-ref.html>`. A |
| `match` test only passes if the two files render pixel-for-pixel |
| identically within a 800x600 window *including* scroll-bars if |
| present; a `mismatch` test only passes if they *don't* render |
| identically. |
| |
| The *reference* file is typically written to be as simple as possible, |
| and does not use the technology under test. It is desirable that the |
| reference be rendered correctly even in UAs with relatively poor |
| support for CSS and no support for the technology under test. |
| |
| ## Writing a Good Reftest |
| |
| In general the files used in a reftest should follow |
| the [general guidelines][] and |
| the [rendering test guidelines][rendering]. They should also be |
| self-describing, to allow a human to determine whether the the |
| rendering is as expected. |
| |
| References can be shared between tests; this is strongly encouraged as |
| it makes it easier to tell at a glance whether a test passes (through |
| familiarity) and enables some optimizations in automated test |
| runners. Shared references are typically placed in `references` |
| directories, either alongside the tests they are expected to be useful |
| for or at the top level if expected to be generally applicable (e.g., |
| many layout tests can be written such that the correct rendering is a |
| 100x100 green square!). For references that are applicable only to a |
| single test, it is recommended to use the test name with a suffix of |
| `-ref` as their filename; e.g., `test.html` would have `test-ref.html` |
| as a reference. |
| |
| ## Multiple References |
| |
| Sometimes, a test's pass condition cannot be captured in a single |
| reference. |
| |
| If a test has multiple links, then the test passes if: |
| |
| * If there are any match references, at least one must match, and |
| * If there are any mismatch references, all must mismatch. |
| |
| If you need multiple matches to succeed, these can be turned into |
| multiple tests (for example, by just having a reference be a test |
| itself!). If this seems like an unreasonable restriction, please file |
| a bug and let us know! |
| |
| ## Controlling When Comparison Occurs |
| |
| By default, reftest screenshots are taken after the following |
| conditions are met: |
| |
| * The `load` event has fired |
| * Web fonts (if any) are loaded |
| * Pending paints have completed |
| |
| In some cases it is necessary to delay the screenshot later than this, |
| for example because some DOM manipulation is required to set up the |
| desired test conditions. To enable this, the test may have a |
| `class="reftest-wait"` attribute specified on the root element. In |
| this case the harness will run the following sequence of steps: |
| |
| * Wait for the `load` event to fire and fonts to load. |
| * Wait for pending paints to complete. |
| * Fire an event named `TestRendered` at the root element, with the |
| `bubbles` attribute set to true. |
| * Wait for the `reftest-wait` class to be removed from the root |
| element. |
| * Wait for pending paints to complete. |
| * Screenshot the viewport. |
| |
| The `TestRendered` event provides a hook for tests to make |
| modifications to the test document that are not batched into the |
| initial layout/paint. |
| |
| ## Fuzzy Matching |
| |
| In some situations a test may have subtle differences in rendering |
| compared to the reference due to, e.g., anti-aliasing. To allow for |
| these small differences, we allow tests to specify a fuzziness |
| characterised by two parameters, both of which must be specified: |
| |
| * A maximum difference in the per-channel color value for any pixel. |
| * A number of total pixels that may be different. |
| |
| The maximum difference in the per pixel color value is formally |
| defined as follows: let <code>T<sub>x,y,c</sub></code> be the value of |
| colour channel `c` at pixel coordinates `x`, `y` in the test image and |
| <code>R<sub>x,y,c</sub></code> be the corresponding value in the |
| reference image, and let <code>width</code> and <code>height</code> be |
| the dimensions of the image in pixels. Then <code>maxDifference = |
| max<sub>x=[0,width) y=[0,height), c={r,g,b}</sub>(|T<sub>x,y,c</sub> - |
| R<sub>x,y,c</sub>|)</code>. |
| |
| To specify the fuzziness in the test file one may add a `<meta |
| name=fuzzy>` element (or, in the case of more complex tests, to any |
| page containing the `<link rel=[mis]match>` elements). In the simplest |
| case this has a `content` attribute containing the parameters above, |
| separated by a semicolon e.g. |
| |
| ``` |
| <meta name=fuzzy content="maxDifference=15;totalPixels=300"> |
| ``` |
| |
| would allow for a difference of exactly 15 / 255 on any color channel |
| and 300 exactly pixels total difference. The argument names are optional |
| and may be elided; the above is the same as: |
| |
| ``` |
| <meta name=fuzzy content="15;300"> |
| ``` |
| |
| The values may also be given as ranges e.g. |
| |
| ``` |
| <meta name=fuzzy content="maxDifference=10-15;totalPixels=200-300"> |
| ``` |
| |
| or |
| |
| ``` |
| <meta name=fuzzy content="10-15;200-300"> |
| ``` |
| |
| In this case the maximum pixel difference must be in the range |
| `10-15` and the total number of different pixels must be in the range |
| `200-300`. These range checks are inclusive. |
| |
| In cases where a single test has multiple possible refs and the |
| fuzziness is not the same for all refs, a ref may be specified by |
| prefixing the `content` value with the relative url for the ref e.g. |
| |
| ``` |
| <meta name=fuzzy content="option1-ref.html:10-15;200-300"> |
| ``` |
| |
| One meta element is required per reference requiring a unique |
| fuzziness value, but any unprefixed value will automatically be |
| applied to any ref that doesn't have a more specific value. |
| |
| ### Debugging fuzzy reftests |
| |
| When debugging a fuzzy reftest via `wpt run`, it can be useful to know what the |
| allowed and detected differences were. Many of the output logger options will |
| provide this information. For example, by passing `--log-mach=-` for a run of a |
| hypothetical failing test, one might get: |
| |
| ``` |
| 0:08.15 TEST_START: /foo/bar.html |
| 0:09.70 INFO Found 250 pixels different, maximum difference per channel 6 on page 1 |
| 0:09.70 INFO Allowed 0-100 pixels different, maximum difference per channel 0-0 |
| 0:09.70 TEST_END: FAIL, expected PASS - /foo/bar.html ['f83385ed9c9bea168108b8c448366678c7941627'] |
| ``` |
| |
| For other logging flags, see the output of `wpt run --help`. |
| |
| ## Limitations |
| |
| In some cases, a test cannot be a reftest. For example, there is no |
| way to create a reference for underlining, since the position and |
| thickness of the underline depends on the UA, the font, and/or the |
| platform. However, once it's established that underlining an inline |
| element works, it's possible to construct a reftest for underlining |
| a block element, by constructing a reference using underlines on a |
| ```<span>``` that wraps all the content inside the block. |
| |
| [general guidelines]: general-guidelines |
| [rendering]: rendering |