Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(925)

Side by Side Diff: docs/testing/layout_test_writing.md

Issue 2492733003: New documentation on writing LayoutTests. (Closed)
Patch Set: Documented test types and legacy reftests. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | docs/testing/layout_tests.md » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Writing Layout Tests
qyearsley 2016/11/15 18:40:56 Is this file just called layout_test_writing.md so
pwnall 2016/11/16 01:50:39 Done. You guessed my intention correctly :) I thou
2
3 _Layout tests_ is a bit of a misnomer. This term is
4 [a part of our WebKit heritage](https://webkit.org/blog/1452/layout-tests-theory /),
5 and we use it to refer to every test that is written as a Web page (HTML, SVG,
qyearsley 2016/11/15 18:40:56 I notice that Web is capitalized in a few places h
pwnall 2016/11/16 01:50:39 Web is capitalized on Wikipedia and NY Times. This
foolip 2016/11/16 11:59:53 https://www.chromium.org/blink uses lowercase "web
qyearsley 2016/11/16 18:35:45 For some reason I never realized that it was somet
6 or XHTML) and lives in
7 [third_party/WebKit/LayoutTests/](../../third_party/WebKit/LayoutTests).
8
9 [TOC]
10
11 ## Overview
12
13 Layout tests should be used to accomplish one of the following goals:
14
15 1. The entire surface of Blink that is exposed to the Web should be covered by
16 tests that we contribute to the
17 [Web Platform Tests Project](https://github.com/w3c/web-platform-tests)
18 (WPT). This helps us avoid regressions, and gives us confidence that we match
19 other browsers' behavior.
20 2. When a Blink feature cannot be tested using the Web Platform, and cannot be
21 easily covered by
22 [C++ unit tests](https://cs.chromium.org/chromium/src/third_party/WebKit/Sour ce/web/tests/?q=webframetest&sq=package:chromium&type=cs),
23 the feature must be covered by layout tests, to avoid unexpected regressions.
24 These tests will use Blink-specific testing APIs that are only available in
25 [content_shell](./layout_tests_in_content_shell.md).
26
27 ### Test Types
28
29 There are three broad types of layout tests, listed in the order of preference.
30
31 * *JavaScript Tests* are the layout test implementation of
32 [xUnit tests](https://en.wikipedia.org/wiki/XUnit). These tests contain
33 assertions written in JavaScript, and pass if the assertions evaluate to
34 true.
qyearsley 2016/11/15 18:40:56 Could note here that there are two different JS li
pwnall 2016/11/16 01:50:39 I'd rather not. js-test.js is part of our WebKit l
foolip 2016/11/16 11:59:53 This section doesn't mention specifics, but below
qyearsley 2016/11/16 18:35:44 Yep, sounds good to me.
35 * *Reference Tests* render a test page and a reference page, and pass if the two
36 renderings are identical, according to a pixel-by-pixel comparison. These
37 tests are less robust, harder to debug, and significantly slower than
38 JavaScript tests, and are only used when JavaScript tests are insufficient,
39 such as when testing layout code.
40 * *Pixel Tests* render a test page and compare the result against a pre-rendered
41 image in the repository. Pixel tests are less robust than JavaScript tests and
42 reference tests, because the rendering of a page is influenced by many factors
43 such as the host computer's graphics card and driver, the platform's text
44 rendering system, and various user-configurable operating system settings.
45 For this reason, it is not uncommon for a pixel test to have a different
46 reference image for each platform that Blink is tested on. Pixel tests are
47 least preferred, because the reference images are
48 [quite cumbersome to manage](./layout_test_expectations.md).
49
50 ## General Principles
51
52 The principles below are adapted from
53 [Test the Web Forward's Test Format Guidelines](http://testthewebforward.org/doc s/test-format-guidelines.html)
54 and
55 [WebKit's Wiki page on Writing good test cases](https://trac.webkit.org/wiki/Wri ting%20Layout%20Tests%20for%20DumpRenderTree).
56
57 * Tests should be as **short** as possible. The page should only include
58 elements that are necessary and relevant to what is being tested.
59
60 * Tests should be as **fast** as possible. Blink has several thousand layout
61 tests that are run in parallel, and avoiding unnecessary delays is crucial to
62 keeping our Commit Queue in good shape.
63 * Avoid [window.setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/W indowTimers/setTimeout),
64 as it wastes testing time and can introduce flakiness. Instead, use specific
65 event handlers, such as
66 [window.onload](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEvent Handlers/onload).
67
68 * Tests should be **self-describing**, so that a project member can recognize
69 whether a test passes or fails without having to read the specification of the
70 feature being tested. `testharness.js` makes a test self-describing when used
71 correctly, but tests that degrade to manual tests
72 [must be carefully designed](http://testthewebforward.org/docs/test-style-guid elines.html)
73 to be self-describing.
74
75 * Tests should use the **minimal** set of platform features needed to express
76 the test scenario efficiently. Avoid depending on edge case behavior of
qyearsley 2016/11/15 18:40:56 Nit: "efficiently" may be unnecessary here.
pwnall 2016/11/16 01:50:39 I put it in there because I wanted to say that it'
foolip 2016/11/16 11:59:53 Makes sense to me. If you're waiting for many cond
qyearsley 2016/11/16 18:35:44 Sounds good. This is nitpicky, but I'm still not s
pwnall 2016/11/22 20:32:54 Done. I like concisely. Thank you! FWIW, "efficie
77 features that aren't explicitly covered by the test. For example, except where
78 testing parsing, tests should contain no parse errors.
79
80 * Tests should be as **cross-platform** as reasonably possible. Avoid
81 assumptions about device type, screen resolution, etc. Unavoidable assumptions
82 should be documented.
83 * When possible, tests should only use Web platform features, as specified
84 in the relevant standards.
85 * Tests should be written under the assumption that they will be upstreamed
86 to the WPT project. For example, tests should follow the
87 [WPT guidelines](http://testthewebforward.org/docs/writing-tests.html).
88 * Tests that use Blink-specific testing APIs should feature-test for the
89 presence of the testing APIs and degrade to
90 [manual tests](http://testthewebforward.org/docs/manual-test.html)
91 when the testing APIs are not present.
92
93 * Tests must be **self-contained** and not depend on external network resources.
94 Unless used by multiple test files, CSS and JavaScript should be inlined using
95 `<style>` and `<script>` tags. Content shared by multiple tests should be
96 placed in a `resources/` directory near the tests that share it. See below for
97 using multiple origins in a test.
98
99 * Test **file names** should describe what is being tested.
100
101 * Tests must stick to pure ASCII or use the UTF-8 **character encoding**, which
102 should be declared by `<meta charset=utf-8>`. This does not apply when
103 specifically testing encodings.
104
105 * Tests must aim to have a **coding style** that is consistent with
106 [Google's JavaScript Style Guide](https://google.github.io/styleguide/javascri ptguide.xml),
107 with the following exceptions.
108 * Rules related to Google Closure and JSDoc do not apply.
109 * Modern Web Platform and JavaScript features should be preferred to legacy
110 constructs that target old browsers. For example, prefer `const` and `let`
111 to `var`, and prefer `class` over other OOP constructs.
112 * Concerns regarding buggy behavior in legacy browsers do not apply. For
113 example, the garbage collection cycle note in the _Closures_ section does
114 not apply.
qyearsley 2016/11/15 18:40:56 Also note there's a doc about layout test style gu
pwnall 2016/11/16 01:50:39 Thank you for the link! I either completely forgot
115
116 ## JavaScript Tests
117
118 Whenever possible, the testing criteria should be expressed in JavaScript. The
119 alternatives, which will be described in future sections, result in slower and
120 less robust tests.
121
122 All new JavaScript tests should be written using the
123 [testharness.js](https://github.com/w3c/testharness.js/) testing framework. This
124 framework is used by the tests in the
125 [web-platform-tests](https://github.com/w3c/web-platform-tests) repository,
126 which is shared with all the other browser vendors, so `testharness.js` tests
127 are more accessible to browser developers.
128
129 As a shared framework, `testharness.js` enjoys high-quality documentation, such
130 as [a tutorial](http://testthewebforward.org/docs/testharness-tutorial.html) and
131 [API documentation](https://github.com/w3c/testharness.js/blob/master/docs/api.m d).
132 Layout tests should follow the recommendations of the above documents.
133 Furthermore, layout tests should include relevant
134 [metadata](http://testthewebforward.org/docs/css-metadata.html). The
135 specification URL (in `<link rel="help">`) is almost always relevant, and is
136 incredibly helpful to a developer who needs to understand the test quickly.
137
138 Below is a skeleton for a JavaScript test. Note that, in order to follow the
139 minimality guideline, the test omits the tags `<html>`, `<head>` and `<body>`,
140 as they can be inferred by the HTML5 parser.
141
142 ```html
143 <!DOCTYPE html>
144 <meta charset="utf-8">
145 <title>JavaScript: the true literal</title>
146 <link rel="help"
147 href="http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-defini tions-boolean-value">
148 <script src="/resources/testharness.js"></script>
149 <script src="/resources/testharnessreport.js"></script>
150 <script>
151
152 // Synchronous test example.
153 test(t => {
154 const truthy = true;
155 assert_true(truthy, 'true should be truthy');
156 }, 'The literal true in a synchronous test case');
157
158 // Asynchronous test example.
159 async_test(t => {
160 setTimeout(t.step_func(() => {
161 const truthy = true;
162 assert_true(truthy, 'true should be truthy');
163 }), 0);
164 t.done();
165 }, 'The literal true in a setTimeout callback');
166
167 // Promise test example.
168 promise_test(t => {
169 return new Promise((resolve, reject) => {
170 resolve(true);
171 }).then(truthy => {
172 assert_true(truthy, 'true should be truthy');
173 });
174 }, 'The literal true in a Promise');
175
176 </script>
177 ```
178
179 ### Relying on Blink-Specific Testing APIs
180
181 Tests that cannot be expressed using the Web Platform APIs rely on
182 Blink-specific testing APIs. These APIs are only available in
183 [content_shell](./layout_tests_in_content_shell.md).
184
185 ### Manual Tests
186
187 Whenever possible, tests that rely on Blink-specific testing APIs should also be
188 usable as [manual tests](http://testthewebforward.org/docs/manual-test.html).
189 This makes it easy to debug the test, and to check whether our behavior matches
190 other browsers.
191
192 Manual tests should minimize the chance of user error. This implies keeping the
193 manual steps to a minimum, and having simple and clear instructions that
194 describe all the configuration changes and user gestures that match the effect
195 of the Blink-specific APIs used by the test.
196
197 Below is an example of a fairly minimal test that uses a Blink-Specific API
198 (`window.eventSender`), and gracefully degrades to a manual test.
199
200 ```html
201 <!DOCTYPE html>
202 <meta charset="utf-8" />
203 <title>DOM Events: Event.isTrusted for UI events</title>
204 <link rel="help"
205 href="https://dom.spec.whatwg.org/#dom-event-istrusted" />
206 <link rel="help"
207 href="https://dom.spec.whatwg.org/#constructing-events" />
208 <meta name="assert" content="Event.isTrusted value under certain situations" />
qyearsley 2016/11/15 18:40:56 I think there's no need to use /> to close meta an
jeffcarp 2016/11/15 19:08:17 Just to back this up, the Chromium style says not
pwnall 2016/11/16 01:50:39 Thanks for pointing me to that! I added a link to
pwnall 2016/11/16 01:50:39 Done. Thanks so much for catching this! Having exa
209 <script src="../../resources/testharness.js"></script>
210 <script src="../../resources/testharnessreport.js"></script>
211
212 <p>Please click on the button below.</p>
213 <button id="click-me" type="button">Click Me!</button>
214
215 <script>
216
217 setup({ explicit_timeout: true });
218
219 promise_test(() => {
220 return new Promise((resolve, reject) => {
221 const button = document.getElementById('click-me');
222 button.addEventListener('click', (event) => {
223 clickEvent = event;
224 resolve(event);
225 });
226
227 if (window.eventSender) {
228 eventSender.mouseMoveTo(button.offsetLeft, button.offsetTop);
229 eventSender.mouseDown();
230 eventSender.mouseUp();
231 }
232 }).then((clickEvent) => {
233 assert_equals(true, clickEvent.isTrusted,
234 'User interaction events should have isTrusted set to true');
235 });
236
237 }, 'Click generated by user interaction');
238
239 </script>
240 ```
241
242 The test exhibits the following desirable features:
243
244 * It has a second specification URL (`<link rel="help">`), because the paragraph
245 that documents the tested feature (referenced by the primary URL) is not very
246 informative on its own.
247 * It links to the
248 [WHATWG Living Standard](https://wiki.whatwg.org/wiki/FAQ#What_does_.22Living_ Standard.22_mean.3F),
249 rather than to a frozen version of the specification.
250 * It uses relative paths to point to
251 [/references/testharness.js](../../third_party/WebKit/LayoutTests/references/t estharness.js)
252 and
253 [/references/testharnessreport.js](../../third_party/WebKit/LayoutTests/refere nces/testharnessreport.js),
254 so a developer can iterate on the test simply by opening its file in a
255 browser, without having to start a HTTP server. This is only relevant for
256 tests that work from `file://` origins, and tests that require a HTTP server
257 should use absolute paths.
258 * It documents its assertions clearly.
259 * The `<meta name="assert">` describes the purpose of the entire file.
260 * The `assert_equals` string describes the expected behavior, not the error.
261 * Each test case describes the circumstance that it tests.
262 * It contains clear instructions for manually triggering the test conditions.
263 The test starts with a paragraph (`<p>`) that tells the tester exactly what to
264 do, and the `<button>` that needs to be clicked is clearly labeled.
265 * It disables the timeout mechanism built into `testharness.js` by calling
266 `setup({ explicit_timeout: true });`
267 * It checks for the presence of the Blink-specific testing APIs
268 (`window.eventSender`) before invoking them. The test does not automatically
269 fail when the APIs are not present.
270 * It uses [Promises](https://developer.mozilla.org/docs/Web/JavaScript/Reference /Global_Objects/Promise)
271 to separate the test setup from the assertions. This is particularly helpful
272 for manual tests that depend on a sequence of events to occur, as Promises
273 offer a composable way to express waiting for asynchronous events that avoids
274 [callback hell](http://stackabuse.com/avoiding-callback-hell-in-node-js/).
275
276 Notice that the test is pretty heavy compared to a minimal JavaScript test that
277 does not rely on testing APIs. Only use Blink-specific testing APIs when the
278 desired testing conditions cannot be set up using Web Platform APIs.
279
280 #### Using Blink-Specific Testing APIs
281
282 A downside of Blink-specific APIs is that they are not as well documented as the
283 Web Platform features. Learning to use a Blink-specific feature requires finding
284 other tests that use it, or reading its source code.
285
286 For example, the most popular Blink-specific API is `testRunner`, which is
287 implemented in
288 [components/test_runner/test_runner.h](../../components/test_runner/test_runner. h)
289 and
290 [components/test_runner/test_runner.cpp](../../components/test_runner/test_runne r.cpp).
291 By skimming the `TestRunnerBindings::Install` method, we learn that the
292 testRunner API is presented by the `window.testRunner` and
293 `window.layoutTestsController` objects, which are synonyms. Reading the
294 `TestRunnerBindings::GetObjectTemplateBuilder` method tells us what properties
295 are available on the `window.testRunner` object.
296
297 *** aside
298 `window.testRunner` is the preferred way to access the `testRunner` APIs.
299 `window.layoutTestsController` is still supported because it is used by
300 3rd-party tests.
301 ***
302
303 *** note
304 `testRunner` is the most popular testing API because it is also used indirectly
305 by tests that stick to Web Platform APIs. The `testharnessreport.js` file in
306 `testharness.js` is specifically designated to hold glue code that connects
307 `testharness.js` to the testing environment. Our implementation is in
308 [third_party/WebKit/LayoutTests/resources/testharnessreport.js](../../third_part y/WebKit/LayoutTests/references/testharnessreport.js),
309 and uses the `testRunner` API.
310 ***
311
312 See the [components/test_runner/](../../components/test_runner/) directory and
313 [WebKit's LayoutTests guide](https://trac.webkit.org/wiki/Writing%20Layout%20Tes ts%20for%20DumpRenderTree)
314 for other useful APIs. For example, `window.eventSender`
315 ([components/test_runner/event_sender.h](../../components/test_runner/event_send er.h)
316 and
317 [components/test_runner/event_sender.cpp](../../components/test_runner/event_sen der.cpp))
318 has methods that simulate events input such as keyboard / mouse input and
319 drag-and-drop.
320
321 Here is a UML diagram of how the `testRunner` bindings fit into Chromium.
322
323 [![UML of testRunner bindings configuring platform implementation](https://docs. google.com/drawings/u/1/d/1KNRNjlxK0Q3Tp8rKxuuM5mpWf4OJQZmvm9_kpwu_Wwg/export/sv g?id=1KNRNjlxK0Q3Tp8rKxuuM5mpWf4OJQZmvm9_kpwu_Wwg&pageid=p)](https://docs.google .com/drawings/d/1KNRNjlxK0Q3Tp8rKxuuM5mpWf4OJQZmvm9_kpwu_Wwg/edit)
324
325 ### Text Test Expectations
326
qyearsley 2016/11/15 18:40:56 I've been referring to all -expected.* files as "b
pwnall 2016/11/16 01:50:39 Done. Thank you very much for bringing this up! Co
qyearsley 2016/11/16 18:35:44 Yeah, I think that the current state of affairs is
327 By default, all the test cases in a file that uses `testharness.js` are expected
328 to pass. However, in some cases, we prefer to add failing test cases to the
329 repository, so that we can be notified when the failure modes change (e.g., we
330 want to know if a test starts crashing rather than returning incorrect output).
331 In these situations, a test file will be accompanied by an `-expected.txt` file,
332 which documents the test's expected output.
333
334 The `-expected.txt` files are generated automatically when appropriate by
335 `run-webkit-tests`, which is described [here](./layout_tests.md), and by the
336 [rebaselining tools](./layout_test_expectations.md).
337
338 `-expected.txt` files should be very rare. In general, layout tests should
339 use JavaScript to document Blink's current behavior, rather than using
340 JavaScript to document desired behavior and a text file to document current
341 behavior.
qyearsley 2016/11/15 18:40:56 Although, web platform tests test conformance to a
pwnall 2016/11/16 01:50:39 I think this is an exception. WPT tests are import
foolip 2016/11/16 11:59:53 I think it is still worth pointing out somehow. As
pwnall 2016/11/22 20:32:54 Done.
342
343 ### js-test tests
qyearsley 2016/11/15 18:40:56 Possible alternate section title: "JavaScript Te
pwnall 2016/11/16 01:50:39 I changed the section heading. Thank you for highl
344
345 *** promo
qyearsley 2016/11/15 18:40:56 What is "promo" here?
pwnall 2016/11/16 01:50:39 It's a gittiles-specific thing. https://gerrit.goo
qyearsley 2016/11/16 18:35:44 Ah, thanks
346 For historical reasons, older tests are written using the `js-test` harness.
347 This harness is **deprecated**, and should not be used for new tests.
348 ***
349
350 If you need to understand old tests, the best `js-test` documentation is its
351 implementation at
352 [third_party/WebKit/LayoutTests/resources/js-test.js](../../third_party/WebKit/L ayoutTests/resources/js-test.js).
353
354 `js-test` tests lean heavily on the Blink-specific `testRunner` testing API.
355 In a nutshell, the tests call `testRunner.dumpAsText()` to signal that the page
356 content should be dumped and compared against an `-expected.txt` file. As a
357 consequence, `js-test` tests are always accompanied by an `-expected.txt`.
358 Asynchronous tests also use `testRunner.waitUntilDone()` and
359 `testRunner.notifyDone()` to tell the testing tools when they are complete.
360
361 ### Tests that use an HTTP Server
362
363 By default, tests are loaded as if via `file:` URLs. Some web platform features
364 require tests served via HTTP or HTTPS, for example absolute paths (`src=/foo`)
365 or features restricted to secure protocols.
366
367 HTTP tests are those tests that are under `LayoutTests/http/tests` (or virtual
368 variants). Use a locally running HTTP server (Apache) to run them. Tests are
369 served off of ports 8000 and 8080 for HTTP, and 8443 for HTTPS. If you run the
370 tests using `run-webkit-tests`, the server will be started automatically. To run
371 the server manually to reproduce or debug a failure:
372
373 ```bash
374 cd src/third_party/WebKit/Tools/Scripts
375 run-blink-httpd start
376 ```
377
378 The layout tests will be served from `http://127.0.0.1:8000`. For example, to
379 run the test `http/tests/serviceworker/chromium/service-worker-allowed.html`,
380 navigate to
381 `http://127.0.0.1:8000/serviceworker/chromium/service-worker-allowed.html`. Some
382 tests will behave differently if you go to 127.0.0.1 instead of localhost, so
383 use 127.0.0.1.
384
385 To kill the server, run `run-blink-httpd --server stop`, or just use `taskkill`
386 or the Task Manager on Windows, and `killall` or Activity Monitor on MacOS.
387
388 The test server sets up an alias to `LayoutTests/resources` directory. In HTTP
389 tests, you can access the testing framework at e.g.
390 `src="/js-test-resources/js-test.js"`.
391
392 TODO: Document [wptserve](http://wptserve.readthedocs.io/) when we are in a
393 position to use it to run layout tests.
394
395 ## Reference Tests
396
397 TODO: Check that we match the Web Platform's
398 [reftests](http://testthewebforward.org/docs/reftests.html), link to their
399 document and summarize it.
400
401 ### Legacy Reference Tests
402
403 *** promo
404 WebKit-style reftests are deprecated. Please use the WPT style for all new
405 reference tests that you create.
406 ***
407
408 Blink also has inherited a sizable amount of
409 [reftests](https://trac.webkit.org/wiki/Writing%20Reftests) from WebKit. In
410 these tests, the reference page file name is based on the test page's file name
411 and an `-expected.html` suffix.
412
413 ## Pixel Tests
414
415 `testRunner` APIs such as `window.testRunner.dumpAsTextWithPixelResults()` and
416 `window.testRunner.dumpDragImage()` create an image expectation, turning the
417 test into a **pixel test**. These tests have associated `-expected.png` image
418 files.
419
420 Pixel tests should still follow the principles laid out above. Pixel tests pose
421 unique challenges to the desire to have *self-describing* and *cross-platform*
422 tests. The
423 [WPT test style guidelines](http://testthewebforward.org/docs/test-style-guideli nes.html)
424 contain useful guidance. The most relevant pieces of advice are below.
425
426 * use a green paragraph / page / square to indicate success
427 * use the red color or the word `FAIL` to highlight errors
428 * use the [Ahem font](https://www.w3.org/Style/CSS/Test/Fonts/Ahem/README) to
429 minimize the variance introduced by the platform's text rendering system
430
431 The following snippet includes the Ahem font in a layout test.
432
433 ```html
434 <style>
435 body {
436 font: 10px Ahem;
437 }
438 </style>
439 <script src="/resources/ahem.js"></script>
440 ```
441
442 ### Tests that need to paint, raster, or draw a frame of intermediate output
443
444 A layout test does not actually draw frames of output until the test exits. If
445 it is required to generate a painted frame, then use
446 `window.testRunner.displayAsyncThen`, which will run the machinery to put up a
447 frame, then call the passed callback. There is also a library at
448 `fast/repaint/resources/text-based-repaint.js` to help with writing paint
449 invalidation and repaint tests.
450
451 ## See Also
452
453 [Writing reliable layout tests](https://docs.google.com/document/d/1Yl4SnTLBWmY1 O99_BTtQvuoffP8YM9HZx2YPkEsaduQ/edit)
OLDNEW
« no previous file with comments | « no previous file | docs/testing/layout_tests.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698