docs: improve best practices (#20106)

This commit is contained in:
Debbie O'Brien 2023-01-16 10:52:36 +01:00 committed by GitHub
parent 780e64f2c6
commit e780a5c1ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,7 +16,29 @@ Automated tests should verify that the application code works for the end users,
Each test should be completely isolated from another test and should run independently with its own local storage, session storage, data, cookies etc. [Test isolation](./browser-contexts.md) improves reproducibility, makes debugging easier and prevents cascading test failures. Each test should be completely isolated from another test and should run independently with its own local storage, session storage, data, cookies etc. [Test isolation](./browser-contexts.md) improves reproducibility, makes debugging easier and prevents cascading test failures.
In order to avoid repetition for a particular part of your test you can use [before and after hooks](/api/class-test.md) or [global setup](/auth.md#reuse-signed-in-state). Within your test file add a before hook to run a part of your test before each test such as going to a particular URL or logging in to a part of your app. This keeps your tests isolated as no test relies on another. However it is also ok to have a little duplication when tests are simple enough especially if it keeps your tests clearer and easier to read and maintain. In order to avoid repetition for a particular part of your test you can use [before and after hooks](/api/class-test.md). Within your test file add a before hook to run a part of your test before each test such as going to a particular URL or logging in to a part of your app. This keeps your tests isolated as no test relies on another. However it is also ok to have a little duplication when tests are simple enough especially if it keeps your tests clearer and easier to read and maintain.
```js
import { test } from '@playwright/test';
test.beforeEach(async ({ page }) => {
// Runs before each test and signs in each page.
await page.goto('https://github.com/login');
await page.getByLabel('Username or email address').fill('username');
await page.getByLabel('Password').fill('password');
await page.getByRole('button', { name: 'Sign in' }).click();
});
test('first', async ({ page }) => {
// page is signed in.
});
test('second', async ({ page }) => {
// page is signed in.
});
```
You can also reuse the signed-in state in the tests with [global setup](/auth.md#reuse-signed-in-state). That way you can log in only once and then skip the log in step for all of the tests.
### Write fewer tests but longer tests ### Write fewer tests but longer tests
@ -24,9 +46,17 @@ When it comes to end to end testing having long tests is not a bad thing. It's o
If your test does fail, Playwright will give you an error message showing what part of the test failed which you can see either in VS Code, the terminal, the HTML report, or the trace viewer. You can also use [soft assertions](/test-assertions.md#soft-assertions) which do not terminate test execution but mark the test as failed. If your test does fail, Playwright will give you an error message showing what part of the test failed which you can see either in VS Code, the terminal, the HTML report, or the trace viewer. You can also use [soft assertions](/test-assertions.md#soft-assertions) which do not terminate test execution but mark the test as failed.
```js
// Make a few checks that will not stop the test when failed...
await expect.soft(page.getByTestId('status')).toHaveText('Success');
// ... and continue the test to check more things.
await page.getByRole('link', { name: 'next page' }).click();
```
### Avoid testing third-party dependencies ### Avoid testing third-party dependencies
Only test what you control. Don't try to test links to external sites or third party servers that you do not control. Not only is it time consuming and can slow down your tests but also you can not control the content of the page you are linking to, if there are cookie banners or overlay pages or anything else that might cause your test to fail. Only test what you control. Don't try to test links to external sites or third party servers that you do not control. Not only is it time consuming and can slow down your tests but also you can not control the content of the page you are linking to, or if there are cookie banners or overlay pages or anything else that might cause your test to fail.
### Testing with a database ### Testing with a database
@ -80,15 +110,24 @@ Playwright has a [test generator](./codegen.md) that can generate tests and pick
#### Use `codegen` to generate locators #### Use `codegen` to generate locators
To pick a locator you can run the `codegen` command and click on the pick locator button. Then hover over your page in the browser window and click on the element you want to pick. You can then copy and paste this locator into your code. You can also use `codegen` to record a test for you. To pick a locator run the `codegen` command followed by the URL that you would like to pick a locator from.
```bash ```bash
npx playwright codegen npx playwright codegen playwright.dev
``` ```
This will open a new browser window as well as the Playwright inspector. To pick a locator first click on the 'Record' button to stop the recording. By default when you run the `codegen` command it will start a new recording. Once you stop the recording the 'Pick Locator' button will be available to click.
You can then hover over any element on your page in the browser window and see the locator highlighted below your cursor. Clicking on an element will add the locator into the Playwright inspector. You can either copy the locator and paste into your test file or continue to explore the locator by editing it in the Playwright Inspector, for example by modifying the text, and seeing the results in the browser window.
<img width="1394" alt="generating locators with codegen" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212103268-e7d8ee8b-d307-4cba-be13-831f3fbb1f40.png" />
#### Use the VS Code extension to generate locators #### Use the VS Code extension to generate locators
You can also use the [VS Code Extension](./getting-started-vscode.md) to generate locators as well as record a test. The VS Code extension also gives you a great developer experience when writing, running, and debugging tests. You can also use the [VS Code Extension](./getting-started-vscode.md) to generate locators as well as record a test. The VS Code extension also gives you a great developer experience when writing, running, and debugging tests.
<img width="1394" alt="generating locators in vs code with codegen" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212269873-aca04043-16ce-4627-906f-7351d09740ab.png" />
### Use web first assertions ### Use web first assertions
Assertions are a way to verify that the expected result and the actual result matched or not. By using [web first assertions](./test-assertions.md) Playwright will wait until the expected condition is met. For example, when testing an alert message, a test would click a button that makes a message appear and check that the alert message is there. If the alert message takes half a second to appear, assertions such as `toBeVisible()` will wait and retry if needed. Assertions are a way to verify that the expected result and the actual result matched or not. By using [web first assertions](./test-assertions.md) Playwright will wait until the expected condition is met. For example, when testing an alert message, a test would click a button that makes a message appear and check that the alert message is there. If the alert message takes half a second to appear, assertions such as `toBeVisible()` will wait and retry if needed.
@ -117,28 +156,54 @@ Use web first assertions such as `toBeVisible()` instead.
#### Local debugging #### Local debugging
For local debugging we recommend you [debug your tests live in VSCode.](/getting-started-vscode.md#live-debugging) by installing the [VS Code extension](./getting-started-vscode.md). Running the tests in debug mode by right clicking on the line next to the test you want to run will open a browser window and pause at where the breakpoint is set. You can then modify your test right in VS Code while debugging. For local debugging we recommend you [debug your tests live in VSCode.](/getting-started-vscode.md#live-debugging) by installing the [VS Code extension](./getting-started-vscode.md). You can run tests in debug mode by right clicking on the line next to the test you want to run which will open a browser window and pause at where the breakpoint is set.
You can also debug your tests with the Playwright inspector by running your tests with the `--debug` flag. You can then step through your test as well as view actionability logs, or use the pick locator button to explore other available locators on the page. <img width="1338" alt="debugging tests in vscode" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212274675-5c6e1647-2aab-40fd-9804-8680c1ac2d16.png" />
You can live debug your test by clicking or editing the locators in your test in VS Code which will highlight this locator in the browser window as well as show you any other matching locators found on the page.
<img width="1394" alt="live debugging locators in vscode" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212273189-da271dc4-0f59-4138-92a8-10e719066cbe.png" />
You can also debug your tests with the Playwright inspector by running your tests with the `--debug` flag.
```js ```js
npx playwright test --debug npx playwright test --debug
``` ```
To debug a specific test at a specific point add the name of the test followed by the line number before the `--debug` flag. You can then step through your test, view actionability logs and edit the locator live and see it highlighted in the browser window. This will show you which locators match, how many of them there are.
<img width="1350" alt="debugging with the playwright inspector" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212276296-4f5b18e7-2bd7-4766-9aa5-783517bd4aa2.png" />
To debug a specific test add the name of the test file and the line number of the test followed by the `--debug` flag.
```js ```js
npx playwright test example.spec.ts:42 --debug npx playwright test example.spec.ts:9 --debug
``` ```
#### Debugging on CI #### Debugging on CI
For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of videos and screenshots. The trace viewer gives you a full trace of your tests as a local Progressive Web App (PWA) that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action, view network requests and more. For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of videos and screenshots. The trace viewer gives you a full trace of your tests as a local Progressive Web App (PWA) that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action using dev tools, view network requests and more.
Traces are set to run on CI on the first retry of a failed test. We don't recommend setting this to `on` so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the `--trace` flag. <img width="1516" alt="playwrights trace viewer" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212277895-c63d94c2-bd06-4881-864e-62790a072ca3.png" />
Traces are configured in the Playwright config file and are set to run on CI on the first retry of a failed test. We don't recommend setting this to `on` so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the `--trace` flag.
```js ```js
npx playwright test --trace on npx playwright test --trace on
``` ```
Once you run this command your traces will be recorded for each test and can be viewed directly from the HTML report.
```js
npx playwright show-report
````
<img width="1516" alt="Playwrights HTML report" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212279022-d929d4c0-2271-486a-a75f-166ac231d25f.png" />
Traces can be opened by clicking on the icon next to the test or by opening each of the test reports and scrolling down to the traces section.
<img width="1516" alt="Screenshot 2023-01-13 at 09 58 34" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212279699-c9eb134f-4f4e-4f19-805c-37596d3272a6.png" />
### Use Playwright's Tooling ### Use Playwright's Tooling
Playwright comes with a range of tooling to help you write tests. Playwright comes with a range of tooling to help you write tests.
@ -200,36 +265,42 @@ const config: PlaywrightTestConfig = {
export default config; export default config;
``` ```
### Mock third-party Links
If you want to test links to third party API's then you should intercept the route with a mock response. This ensures the link is visible and clickable. Before hitting the link the route gets intercepted and a mock response is returned. Clicking the link results in a new page being opened containing the mock response rather than the actual page. We can then check this has the URL we expect.
```js
test('github link works', async ({ page }) => {
await page.context().route('https://www.github.com/**', route => route.fulfill({
body: '<html><body><h1>Github - Playwright</h1></body></html>'
}));
const [page1] = await Promise.all([
page.waitForEvent('popup'),
page.getByRole('link', { name: 'GitHub' }).click()
]);
await expect(page1).toHaveURL('https://www.github.com/microsoft/playwright');
});
```
### Keep your Playwright dependency up to date ### Keep your Playwright dependency up to date
By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public. Check the [release notes](./release-notes.md) to see what the latest version is and what changes have been released. By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public.
```js ```js
npm install -D @playwright/test@latest npm install -D @playwright/test@latest
``` ```
Check the [release notes](./release-notes.md) to see what the latest version is and what changes have been released.
You can see what version of Playwright you have by running the following command.
```js
npx playwright --version
```
### Run tests on CI ### Run tests on CI
Setup CI/CD and run your tests frequently. The more often you run your tests the better. Ideally you should run your tests on each commit and pull request. Playwright comes with a [GitHub actions workflow](/ci-intro.md) already setup so that tests will run on CI for you with no setup required. Playwright can also be setup on the [CI environment](/ci.md) of your choice. Setup CI/CD and run your tests frequently. The more often you run your tests the better. Ideally you should run your tests on each commit and pull request. Playwright comes with a [GitHub actions workflow](/ci-intro.md) so that tests will run on CI for you with no setup required. Playwright can also be setup on the [CI environment](/ci.md) of your choice.
Use [parallelism and sharding](./test-parallel.md). Playwright runs tests in parallel by default. Tests in a single file are run in order, in the same worker process. Playwright can [shard]./test-parallel.md##shard-tests-between-multiple-machines) a test suite, so that it can be executed on multiple machines
Use Linux when running your tests on CI as it is cheaper. Developers can use whatever environment when running locally but use linux on CI. Use Linux when running your tests on CI as it is cheaper. Developers can use whatever environment when running locally but use linux on CI.
#### Use parallelism and sharding
Playwright runs tests in [parallel](./test-parallel.md) by default. Tests in a single file are run in order, in the same worker process. If you have many independent tests in a single file, you might want to run them in parallel
```js
import { test } from '@playwright/test';
test.describe.configure({ mode: 'parallel' });
test('runs in parallel 1', async ({ page }) => { /* ... */ });
test('runs in parallel 2', async ({ page }) => { /* ... */ });
```
Playwright can [shard](./test-parallel.md#shard-tests-between-multiple-machines) a test suite, so that it can be executed on multiple machines.
```js
npx playwright test --shard=1/3
```