Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 1 | # Web Tests Tips |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 2 | |
| 3 | The recommendations here are intended to help you write new tests that go |
| 4 | through code review with a minimal number of round trips, remain useful as Blink |
| 5 | evolves, and serve as an asset (rather than a liability) for the team. |
| 6 | |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 7 | While reading existing web tests, please keep in mind that they represent |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 8 | snapshots taken over many years of an ever-evolving collective opinion of what |
| 9 | good Web pages and solid tests should look like. Thus, it should not come as a |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 10 | surprise that most existing web tests are not consistent with these |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 11 | recommendations, and are not even consistent with each other. |
| 12 | |
| 13 | *** note |
| 14 | This document intentionally uses _should_ a lot more than _must_, as defined in |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 15 | [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). Writing web tests is a |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 16 | careful act of balancing many concerns, and this humble document cannot possibly |
| 17 | capture the context that rests in the head of an experienced Blink engineer. |
| 18 | *** |
| 19 | |
| 20 | ## General Principles |
| 21 | |
| 22 | This section contains guidelines adopted from |
Philip Jägenstedt | 3a3d5b8 | 2018-05-31 15:25:35 | [diff] [blame] | 23 | [web-platform-tests documentation](https://web-platform-tests.org/writing-tests/general-guidelines.html) |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 24 | and |
| 25 | [WebKit's Wiki page on Writing good test cases](https://trac.webkit.org/wiki/Writing%20Layout%20Tests%20for%20DumpRenderTree), |
| 26 | with Blink-specific flavoring. |
| 27 | |
| 28 | ### Concise |
| 29 | |
| 30 | Tests should be **concise**, without compromising on the principles below. Every |
| 31 | element and piece of code on the page should be necessary and relevant to what |
| 32 | is being tested. For example, don't build a fully functional signup form if you |
| 33 | only need a text field or a button. |
| 34 | |
| 35 | Content needed to satisfy the principles below is considered necessary. For |
| 36 | example, it is acceptable and desirable to add elements that make the test |
| 37 | self-describing (see below), and to add code that makes the test more reliable |
| 38 | (see below). |
| 39 | |
| 40 | Content that makes test failures easier to debug is considered necessary (to |
| 41 | maintaining a good development speed), and is both acceptable and desirable. |
| 42 | |
| 43 | *** promo |
| 44 | Conciseness is particularly important for reference tests and pixel tests, as |
| 45 | the test pages are rendered in an 800x600px viewport. Having content outside the |
| 46 | viewport is undesirable because the outside content does not get compared, and |
| 47 | because the resulting scrollbars are platform-specific UI widgets, making the |
| 48 | test results less reliable. |
| 49 | *** |
| 50 | |
| 51 | ### Fast |
| 52 | |
| 53 | Tests should be as **fast** as possible, without compromising on the principles |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 54 | below. Blink has several thousand web tests that are run in parallel, and |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 55 | avoiding unnecessary delays is crucial to keeping our Commit Queue in good |
| 56 | shape. |
| 57 | |
| 58 | Avoid |
| 59 | [window.setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout), |
| 60 | as it wastes time on the testing infrastructure. Instead, use specific event |
| 61 | handlers, such as |
| 62 | [window.onload](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload), |
| 63 | to decide when to advance to the next step in a test. |
| 64 | |
| 65 | ### Reliable |
| 66 | |
| 67 | Tests should be **reliable** and yield consistent results for a given |
| 68 | implementation. Flaky tests slow down your fellow developers' debugging efforts |
| 69 | and the Commit Queue. |
| 70 | |
| 71 | `window.setTimeout` is again a primary offender here. Asides from wasting time |
| 72 | on a fast system, tests that rely on fixed timeouts can fail when on systems |
| 73 | that are slower than expected. |
| 74 | |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 75 | When adding or significantly modifying a web test, use the command below to |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 76 | assess its flakiness. While not foolproof, this approach gives you some |
| 77 | confidence, and giving up CPU cycles for mental energy is a pretty good trade. |
| 78 | |
| 79 | ```bash |
Kent Tamura | a045a7f | 2018-04-25 05:08:11 | [diff] [blame] | 80 | third_party/blink/tools/run_web_tests.py path/to/test.html --repeat-each=100 |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 81 | ``` |
| 82 | |
| 83 | The |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 84 | [PSA on writing reliable web tests](https://docs.google.com/document/d/1Yl4SnTLBWmY1O99_BTtQvuoffP8YM9HZx2YPkEsaduQ/edit). |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 85 | also has good guidelines for writing reliable tests. |
| 86 | |
| 87 | ### Self-Describing |
| 88 | |
| 89 | Tests should be **self-describing**, so that a project member can recognize |
| 90 | whether a test passes or fails without having to read the specification of the |
| 91 | feature being tested. |
| 92 | |
| 93 | `testharness.js` makes a test self-describing when used correctly. Other types |
| 94 | of tests, such as reference tests and |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 95 | [tests with manual fallback](./web_tests_with_manual_fallback.md), |
Philip Jägenstedt | 3a3d5b8 | 2018-05-31 15:25:35 | [diff] [blame] | 96 | [must be carefully designed](https://web-platform-tests.org/writing-tests/manual.html#requirements-for-a-manual-test) |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 97 | to be self-describing. |
| 98 | |
| 99 | ### Minimal |
| 100 | |
| 101 | Tests should require a **minimal** amount of cognitive effort to read and |
| 102 | maintain. |
| 103 | |
| 104 | Avoid depending on edge case behavior of features that aren't explicitly covered |
| 105 | by the test. For example, except where testing parsing, tests should contain |
| 106 | valid markup (no parsing errors). |
| 107 | |
| 108 | Tests should provide as much relevant information as possible when failing. |
| 109 | `testharness.js` tests should prefer |
Philip Jägenstedt | 3a3d5b8 | 2018-05-31 15:25:35 | [diff] [blame] | 110 | [rich assert_ functions](https://web-platform-tests.org/writing-tests/testharness-api.html#list-of-assertions) |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 111 | to combining `assert_true()` with a boolean operator. Using appropriate |
| 112 | `assert_` functions results in better diagnostic output when the assertion |
| 113 | fails. |
| 114 | |
| 115 | ### Cross-Platform |
| 116 | |
| 117 | Tests should be as **cross-platform** as reasonably possible. Avoid assumptions |
| 118 | about device type, screen resolution, etc. Unavoidable assumptions should be |
| 119 | documented. |
| 120 | |
| 121 | When possible, tests should only use Web platform features, as specified |
| 122 | in the relevant standards. When the Web platform's APIs are insufficient, |
| 123 | tests should prefer to use WPT extended testing APIs, such as |
| 124 | `wpt_automation`, over Blink-specific testing APIs. |
| 125 | |
| 126 | Test pages should use the HTML5 doctype (`<!doctype html>`) unless they |
| 127 | specifically cover |
| 128 | [quirks mode](https://developer.mozilla.org/docs/Quirks_Mode_and_Standards_Mode) |
| 129 | behavior. |
| 130 | |
| 131 | Tests should avoid using features that haven't been shipped by the |
| 132 | actively-developed major rendering engines (Blink, WebKit, Gecko, Edge). When |
| 133 | unsure, check [caniuse.com](http://caniuse.com/). By necessity, this |
| 134 | recommendation does not apply to the feature targeted by the test. |
| 135 | |
| 136 | *** note |
| 137 | It may be tempting have a test for a bleeding-edge feature X depend on feature |
| 138 | Y, which has only shipped in beta / development versions of various browsers. |
| 139 | The reasoning would be that all browsers that implement X will have implemented |
| 140 | Y. Please keep in mind that Chrome has un-shipped features that made it to the |
| 141 | Beta channel in the past. |
| 142 | *** |
| 143 | |
| 144 | *** aside |
| 145 | [ES2015](http://benmccormick.org/2015/09/14/es5-es6-es2016-es-next-whats-going-on-with-javascript-versioning/) |
| 146 | is shipped by all major browsers under active development (except for modules), |
| 147 | so using ES2015 features is acceptable. |
| 148 | |
| 149 | At the time of this writing, ES2016 is not fully shipped in all major browsers. |
| 150 | *** |
| 151 | |
| 152 | ### Self-Contained |
| 153 | |
| 154 | Tests must be **self-contained** and not depend on external network resources. |
| 155 | |
| 156 | Unless used by multiple test files, CSS and JavaScript should be inlined using |
| 157 | `<style>` and `<script>` tags. Content shared by multiple tests should be |
| 158 | placed in a `resources/` directory near the tests that share it. See below for |
| 159 | using multiple origins in a test. |
| 160 | |
| 161 | ### File Names |
| 162 | |
| 163 | Test **file names** should describe what is being tested. |
| 164 | |
| 165 | File names should use `snake-case`, but preserve the case of any embedded API |
| 166 | names. For example, prefer `document-createElement.html` to |
| 167 | `document-create-element.html`. |
| 168 | |
| 169 | ### Character Encoding |
| 170 | |
| 171 | Tests should use the UTF-8 **character encoding**, which should be declared by |
| 172 | `<meta charset=utf-8>`. A `<meta>` tag is not required (but is acceptable) for |
| 173 | tests that only contain ASCII characters. This guideline does not apply when |
| 174 | specifically testing encodings. |
| 175 | |
| 176 | The `<meta>` tag must be the first child of the document's `<head>` element. In |
| 177 | documents that do not have an explicit `<head>`, the `<meta>` tag must follow |
| 178 | the doctype. |
| 179 | |
| 180 | ## Coding Style |
| 181 | |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 182 | No coding style is enforced for web tests. This section highlights coding |
| 183 | style aspects that are not consistent across our web tests, and suggests some |
| 184 | defaults for unopinionated developers. When writing web tests for a new part |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 185 | of the codebase, you can minimize review latency by taking a look at existing |
| 186 | tests, and pay particular attention to these issues. Also beware of per-project |
| 187 | style guides, such as the |
| 188 | [ServiceWorker Tests Style guide](https://www.chromium.org/blink/serviceworker/testing). |
| 189 | |
| 190 | ### Baseline |
| 191 | |
| 192 | [Google's JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html) |
| 193 | and |
| 194 | [Google's HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.xml) |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 195 | are a reasonable baseline for coding style defaults, with the caveat that web |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 196 | tests do not use Google Closure or JSDoc. |
| 197 | |
| 198 | ### == vs === |
| 199 | |
| 200 | JavaScript's |
| 201 | [== operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Equality_()) |
| 202 | performs some |
| 203 | [type conversion](http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-equality-comparison). |
| 204 | on its arguments, which might be surprising to readers whose experience centers |
| 205 | around C++ or Java. The |
| 206 | [=== operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Identity_strict_equality_()) |
| 207 | is much more similar to `==` in C++. |
| 208 | |
| 209 | Using `===` everywhere is an easy default that saves you, your reviewer, and any |
| 210 | colleague that might have to debug test failures, from having to reason about |
| 211 | [special cases for ==](http://dorey.github.io/JavaScript-Equality-Table/). At |
| 212 | the same time, some developers consider `===` to add unnecessary noise when `==` |
| 213 | would suffice. While `===` should be universally accepted, be flexible if your |
| 214 | reviewer expresses a strong preference for `==`. |
| 215 | |
| 216 | ### Let and Const vs Var |
| 217 | |
| 218 | JavaScript variable declarations introduced by |
| 219 | [var](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/var) |
| 220 | are hoisted to the beginning of their containing function, which may be |
| 221 | surprising to C++ and Java developers. By contrast, |
| 222 | [const](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/const) |
| 223 | and |
| 224 | [let](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/let) |
| 225 | declarations are block-scoped, just like in C++ and Java, and have the added |
| 226 | benefit of expressing mutability intent. |
| 227 | |
| 228 | For the reasons above, a reasonable default is to prefer `const` and `let` over |
| 229 | `var`, with the same caveat as above. |
| 230 | |
| 231 | ### Strict Mode |
| 232 | |
| 233 | JavaScript's |
| 234 | [strict mode](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Strict_mode), |
| 235 | activated by adding `'use strict';` to the very top of a script, helps catch |
| 236 | some errors, such as mistyping a variable name, forgetting to declare a |
| 237 | variable, or attempting to change a read-only property. |
| 238 | |
| 239 | Given that strict mode gives some of the benefits of using a compiler, adding it |
| 240 | to every test is a good default. This does not apply when specifically testing |
| 241 | sloppy mode behavior. |
| 242 | |
| 243 | Some developers argue that adding the `'use strict';` boilerplate can be |
| 244 | difficult to remember, weighs down smaller tests, and in many cases running a |
| 245 | test case is sufficient to discover any mistyped variable names. |
| 246 | |
| 247 | ### Promises |
| 248 | |
| 249 | [Promises](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) |
| 250 | are a mechanism for structuring asynchronous code. When used correctly, Promises |
| 251 | avoid some of the |
| 252 | [issues of callbacks](http://colintoh.com/blog/staying-sane-with-asynchronous-programming-promises-and-generators). |
| 253 | For these reasons, a good default is to prefer promises over other asynchronous |
| 254 | code structures. |
| 255 | |
| 256 | When using promises, be aware of the |
| 257 | [execution order subtleties](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) |
| 258 | associated with them. Here is a quick summary. |
| 259 | |
| 260 | * The function passed to `Promise.new` is executed synchronously, so it finishes |
| 261 | before the Promise is created and returned. |
| 262 | * The functions passed to `then` and `catch` are executed in |
| 263 | _separate microtasks_, so they will be executed after the code that resolved |
| 264 | or rejected the promise finishes, but before any other event handler. |
| 265 | |
| 266 | ### Classes |
| 267 | |
| 268 | [Classes](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Classes) |
| 269 | are syntactic sugar for JavaScript's |
| 270 | [prototypal inheritance](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain). |
| 271 | Compared to manipulating prototypes directly, classes offer a syntax that is |
| 272 | more familiar to developers coming from other programming languages. |
| 273 | |
| 274 | A good default is to prefer classes over other OOP constructs, as they will make |
| 275 | the code easier to read for many of your fellow Chrome developers. At the same |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 276 | time, most web tests are simple enough that OOP is not justified. |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 277 | |
| 278 | ### Character Encoding |
| 279 | |
| 280 | When HTML pages do not explicitly declare a character encoding, browsers |
| 281 | determine the encoding using an |
| 282 | [encoding sniffing algorithm](https://html.spec.whatwg.org/multipage/syntax.html#determining-the-character-encoding) |
| 283 | that will surprise most modern Web developers. Highlights include a default |
| 284 | encoding that depends on the user's locale, and non-standardized |
| 285 | browser-specific heuristics. |
| 286 | |
| 287 | The easiest way to not have to think about any of this is to add |
| 288 | `<meta charset="utf-8">` to all your tests. This is easier to remember if you |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 289 | use a template for your web tests, rather than writing them from scratch. |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 290 | |
| 291 | ## Tests with Manual Feedback |
| 292 | |
| 293 | Tests that rely on the testing APIs exposed by WPT or Blink will not work when |
| 294 | loaded in a standard browser environment. When writing such tests, default to |
| 295 | having the tests gracefully degrade to manual tests in the absence of the |
| 296 | testing APIs. |
| 297 | |
| 298 | The |
Kent Tamura | 59ffb02 | 2018-11-27 05:30:56 | [diff] [blame] | 299 | [document on web tests with manual feedback](./web_tests_with_manual_fallback.md) |
pwnall | 59aadcb | 2017-01-26 23:27:21 | [diff] [blame] | 300 | describes the approach in detail and highlights the trade-off between added test |
| 301 | weight and ease of debugging. |