Skip to content

Commit 9858363

Browse files
TimvdLippeCommit Bot
authored and
Commit Bot
committed
Add README for end-to-end tests
The shared README should be done in a follow-up, as it requires additional documentation in the `helper.ts` functions as well. [email protected] Change-Id: I665c9f07b8002fb395b7de2b202d1589472366db Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2115634 Commit-Queue: Tim van der Lippe <[email protected]> Reviewed-by: Paul Lewis <[email protected]>
1 parent f021bbb commit 9858363

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

Diff for: test/e2e/README.md

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Guide on end-to-end testing
2+
3+
This directory hosts the end-to-end tests we run on DevTools.
4+
These tests open a target page and a DevTools frontend page, for which the DevTools frontend connects to the target page over CDP.
5+
We use [Puppeteer] to talk over CDP and all functionality of Puppeteer is available to you as well when writing end-to-end tests.
6+
7+
The goal of these end-to-end tests is to implement core user journeys throughout the application.
8+
As such, the tests you write should read like a little story that you can read, even if you don't know how it is implemented.
9+
10+
The tests therefore have a dual purpose:
11+
1. Verify that core user stories are working as intended and are not broken by a particular DevTools frontend change.
12+
1. Serve as documentation and reference point for how DevTools is intended to be used.
13+
14+
## General implementation details
15+
16+
To that end, the "what" from the "how" are separate in end-to-end tests.
17+
The "what" is the actual end-to-end test.
18+
The "how" are functions in [helpers](helpers/) that implement the interaction with DevTools to perform a particular action.
19+
20+
For example, an end-to-end test might read like this:
21+
22+
```js
23+
it('can show newly created snippets show up in command menu', async () => {
24+
await openSourcesPanel();
25+
await openSnippetsSubPane();
26+
await createNewSnippet('New snippet');
27+
28+
await openCommandMenu();
29+
await showSnippetsAutocompletion();
30+
31+
assert.deepEqual(await getAvailableSnippets(), [
32+
'New snippet\u200B',
33+
]);
34+
});
35+
```
36+
37+
The test describes the user journey and then describes what actions the user takes to fulfill that journey.
38+
For example, when the user wants to "open the command menu", that is an action performed.
39+
The implementation is separated in a helper that implements "how" the user performs that action.
40+
41+
The separation of the two concepts allows us to change the underlying implementation of the action while making sure that the user journey remains intact.
42+
43+
For example, this is the implementation of `openCommandMenu()`:
44+
45+
```js
46+
export const openCommandMenu = async () => {
47+
const {frontend} = getBrowserAndPages();
48+
49+
switch (platform) {
50+
case 'mac':
51+
await frontend.keyboard.down('Meta');
52+
await frontend.keyboard.down('Shift');
53+
break;
54+
55+
case 'linux':
56+
case 'win32':
57+
await frontend.keyboard.down('Control');
58+
await frontend.keyboard.down('Shift');
59+
break;
60+
}
61+
62+
await frontend.keyboard.press('P');
63+
64+
switch (platform) {
65+
case 'mac':
66+
await frontend.keyboard.up('Meta');
67+
await frontend.keyboard.up('Shift');
68+
break;
69+
70+
case 'linux':
71+
case 'win32':
72+
await frontend.keyboard.up('Control');
73+
await frontend.keyboard.up('Shift');
74+
break;
75+
}
76+
77+
await waitFor(QUICK_OPEN_SELECTOR);
78+
};
79+
```
80+
81+
As you can see, the way the user opens the command menu is via key-bindings.
82+
We don't "bypass" the functionality by calling functions on components or on our models directly; we instruct Puppeteer to do exactly what a user would do.
83+
Doing so, we are certain that we don't test our component abstractions and potentially lose track of integration issues.
84+
85+
Secondly, the function has a `waitFor`, which waits for the command menu (found by the `QUICK_OPEN_SELECTOR`) to appear.
86+
For every action that is performed in DevTools, there must be a corresponding user-visible change in the UI.
87+
This means that you always have to wait for something to happen and you can't assume that, as soon as you have performed an action, the UI has updated accordingly.
88+
89+
**Note: Because of the async rendering of DevTools, content might not be strictly visible when DOM Nodes are appended to the DOM.**
90+
As such, be aware of the functionality you are testing and relying on, as it could render differently than you originally assumed.
91+
92+
To summarize:
93+
1. Separate the "what" from the "how".
94+
1. Use real actions (clicking, using key-bindings, typing) instead of "bypassing" via components/models.
95+
1. Every action must be observed by a change in the UI and must be waited for.
96+
1. Be aware of the async rendering of DevTools
97+
98+
## Helpers
99+
100+
There are two kinds of helpers:
101+
1. Helpers written as part of the end-to-end test, implementing the "how" of user actions.
102+
1. Helpers supplied to interact with a page and abstract away the way the tests are run.
103+
104+
The former are implemented in [helpers](helpers/), written by the DevTools maintainers and are specific to the implementation of the DevTools frontend.
105+
The latter are implemented in [../shared](../shared/), written by the Puppeteer maintainers and are predominantly DevTools-agnostic (apart from the handling of a target page + CDP connection).
106+
107+
In general, the e2e/helpers make use of the shared helpers.
108+
See [../shared/README.md](../shared/README.md) for more documentation on the shared helpers.
109+
110+
[Puppeteer]: https://pptr.dev/

Diff for: test/shared/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Helpers README
2+
3+
// TODO

0 commit comments

Comments
 (0)