Playwright 中更好的全局设置,通过项目依赖关系重用登录
等待 getByPlaceholder('Search')
许多团队和公司都在使用全局设置来登录应用程序,然后使用此设置进行需要处于身份验证状态的测试;然而,它缺少一些重要的功能。当您使用全局设置时,您看不到测试设置部分的跟踪信息,并且该设置不会出现在 HTML 报告中。这会使调试变得困难。全局设置中也无法使用 Fixture。
为了解决这个问题,我们创建了项目依赖项。
什么是项目依赖关系?
项目依赖关系是进行全局设置的更好方法。要添加依赖关系,使一个项目依赖于另一个项目,请在 Playwright 配置中为设置测试创建一个单独的项目,该项目中的每个测试都将成为设置例程中的一个步骤。
每次从基本项目运行测试时,它将首先从安装项目运行测试。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'basic',
dependencies: ['setup'],
},
],
});
通过使用项目依赖项,HTML 报告将显示设置测试,跟踪查看器将记录设置的跟踪,并且您可以使用检查器检查设置测试跟踪的 DOM 快照,还可以使用装置。
运行顺序
“设置”项目中的测试将首先运行,然后在设置中的所有测试完成后,“chromium”、“webkit”和“firefox”项目中的测试将并行运行。
如果依赖项失败会发生什么?
在以下示例中,您将看到一个“e2e 测试”项目,它同时依赖于“浏览器登录”项目和“数据库”项目。“浏览器登录”项目和数据库项目将并行运行。然而,由于“数据库”项目失败,“e2e 测试”项目将永远无法运行,因为它依赖于“浏览器登录”和“数据库”项目的通过。
项目依赖示例
Playwright 在称为浏览器上下文的隔离环境中运行测试。每个测试都独立于其他测试运行。这意味着每个测试都有自己的本地存储、会话存储、Cookie 等。但是,测试可以使用其他测试的存储状态(包含 Cookie 和本地存储快照),以便在登录状态下运行测试。
让我们创建一个示例,说明如何使用项目依赖项来进行全局设置,登录维基百科并保存存储状态,以便 e2e 项目的所有测试都在此登录状态下开始运行。
首先,使用CLI或VS Code 扩展安装 Playwright 。然后,您可以修改配置文件,创建登录测试,以及使用存储状态从登录状态启动的端到端测试。
配置安装项目
首先创建一个基本playwright.config.ts
文件,或者修改已创建的文件。所需的选项包括:testDir
存储测试的目录名称,以及projects
要运行的项目。
项目是使用相同配置运行的一组逻辑测试。您需要的第一个项目是名为“setup”的项目,您可以使用 来过滤所有以 结尾的文件,这样在运行“setup”项目时,只会运行这些测试。testMatch
setup.ts
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
],
});
创建登录测试
接下来,创建一个login.setup.ts
。为了更容易看出这是一个设置测试,您可以导入test as setup
,然后在编写测试时test
使用而不是 。setup
目标是创建一个测试,用于登录维基百科并确保用户处于登录状态。您可以使用 Playwright 的测试生成器,无论是从VS Code 扩展程序中获取,还是使用CLI 打开 Playwright Inspector,点击“登录”按钮并填写用户名和密码即可生成代码。然后,您可以添加断言,以确保登录后能够看到“个人工具”选项。
如果您还没有用户名或密码,您可以快速创建一个帐户,然后使用您自己的凭据来查看测试是否有效。
// login.setup.ts
import { test as setup, expect } from '@playwright/test';
setup('do login', async ({ page }) => {
await page.goto('https://en.wikipedia.org');
await page.getByRole('link', { name: 'Log in' }).click();
await page.getByPlaceholder('Enter your username').fill('your_username');
await page.getByPlaceholder('Enter your password').fill('your_password');
await page.getByRole('button', { name: 'Log in' }).click();
await expect(page.getByRole('button', { name: 'Personal tools' })).toBeVisible();
});
使用环境变量
为了确保您的用户名和密码的安全,您可以将它们存储为.env
变量,并在测试中通过process.env.USERNAME!
和访问它们process.env.PASSWORD!
。
// login.setup.ts
import { test as setup, expect } from '@playwright/test';
setup('do login', async ({ page }) => {
await page.goto('https://en.wikipedia.org');
await page.getByRole('link', { name: 'Log in' }).click();
await page.getByPlaceholder('Enter your username').fill(process.env.USERNAME!);
await page.getByPlaceholder('Enter your password').fill(process.env.PASSWORD!);
await page.getByRole('button', { name: 'Log in' }).click();
await expect(page.getByRole('button', { name: 'Personal tools' })).toBeVisible();
});
不要忘记dotenv
从 npm 安装包。
npm i dotenv
安装包后,将其导入到您的 Playwright 配置中,require('dotenv').config();
以便您可以访问.env
变量。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
require('dotenv').config();
export default defineConfig({
testDir: './tests',
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'e2e tests',
dependencies: ['setup'],
},
],
});
接下来,创建一个.env
文件并添加用户名和密码。确保将此文件添加到,.gitignore
这样你的机密就不会泄露到 CI 中。
USERNAME: your_username
PASSWORD: your_password
使用 CI 时,您可以使用 GitHub 机密信息。在仓库设置中创建仓库机密信息,然后将环境变量添加到安装 Playwright 时已创建的GitHub 操作工作流中。
env:
USERNAME: ${{secrets.USERNAME}}
PASSWORD: ${{secrets.PASSWORD}}
创建 e2e 测试项目
创建一个名为 的项目e2e tests logged in
。该项目将依赖于“setup”项目,并将匹配任何以 结尾的测试文件loggedin.spec.ts
。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
require('dotenv').config();
export default defineConfig({
testDir: './tests',
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'e2e tests logged in',
testMatch: '**/*loggedin.spec.ts',
dependencies: ['setup'],
},
],
});
添加存储状态
设置项目会将存储状态写入.auth
playwright 文件夹内某个文件夹中的“auth.json”文件中。这会导出一个 const,STORAGE_STATE
以便在项目之间共享存储文件的位置。
接下来,你需要告诉你的测试使用STORAGE_STATE
你创建的变量作为其 的值storageStage
。这将返回浏览器上下文的存储状态,并包含当前 cookie 和本地存储快照。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import path from 'path';
require('dotenv').config();
export const STORAGE_STATE = path.join(__dirname, 'playwright/.auth/user.json');
export default defineConfig({
testDir: './tests',
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'e2e tests logged in',
testMatch: '**/*loggedin.spec.ts',
dependencies: ['setup'],
use: {
storageState: STORAGE_STATE,
},
},
],
});
目前,文件中尚未保存任何内容,STORAGE_STATE
因此下一步是在执行登录操作后将存储状态填充到上下文中。这样,您只需登录一次,凭据就会存储在STORAGE_STATE
文件中,这意味着您无需在每次测试时都重新登录。首先从STORAGE_STATE
Playwright 配置文件中导入,然后使用此文件作为保存存储状态的路径。
// login.setup.ts
import { test as setup, expect } from '@playwright/test';
import { STORAGE_STATE } from '../playwright.config';
setup('do login', async ({ page }) => {
await page.goto('https://en.wikipedia.org');
await page.getByRole('link', { name: 'Log in' }).click();
await page.getByPlaceholder('Enter your username').fill('TestingLogin');
await page.getByPlaceholder('Enter your password').fill('e2etests');
await page.getByRole('button', { name: 'Log in' }).click();
await expect(page.getByRole('button', { name: 'Personal tools' })).toBeVisible();
await page.context().storageState({ path: STORAGE_STATE });
});
创建 e2e 测试
创建一些端到端测试,在登录状态下继续测试应用程序。运行文件中的所有测试时,设置将仅运行一次,并且由于storageState
配置中的指定,第二次测试将已通过身份验证启动。
// e2e-loggedin.spec.ts
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('https://en.wikipedia.org');
});
test('menu', async ({ page }) => {
await page.getByRole('link', { name: 'TestingLogin' }).click();
await expect(page.getByRole('heading', { name: /TestingLogin/i })).toBeVisible();
await page.getByRole('link', { name: /alerts/i }).click();
await page.getByText('Alerts', { exact: true }).click();
await page.getByRole('button', { name: /notice/i }).click();
await page.getByText('Notices').click();
await page.getByRole('link', { name: /watchlist/i }).click();
})
test('logs user out', async ({ page }) => {
await page.getByRole('button', { name: /Personal tools/i }).check();
await page.getByRole('link', { name: /Log out/i }).click();
await expect(page.getByRole('heading', { name: /Log out/i })).toBeVisible();
await expect(page.getByRole('link', { name: 'Log in', exact: true })).toBeVisible();
})
配置 baseURL
如果“setup”和“e2e 测试”使用相同的 URL,您可以在文件baseURL
中配置playwright.config.ts
。设置baseURL
意味着您可以在测试中直接使用page.goto('/')
,这样编写速度更快,不容易出现拼写错误,并且如果 baseURL 将来发生变化,也更容易管理。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import path from 'path';
require('dotenv').config();
export const STORAGE_STATE = path.join(__dirname, 'playwright/.auth/user.json');
export default defineConfig({
testDir: './tests',
use: {
baseURL: 'https://en.wikipedia.org',
},
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'e2e tests logged in',
dependencies: ['setup'],
use: {
storageState: STORAGE_STATE,
},
},
],
});
然后,您可以在所有后续测试(包括您创建的“设置”测试)中使用/
而不是“ https://en.wikipedia.org ” 。page.goto
// e2e-loggedin.spec.ts
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('/');
});
//...
配置 HTML 报告器
如果您的 Playwright 配置中尚未进行此设置,那么下一步是将 HTML 报告器添加到playwright.config.ts
文件中,以便为您的测试设置 HTML 报告。您还可retries
以为 CI 添加 ,将其设置fullyParallel
为 true ,并将 设置为trace
在测试失败后首次重试时记录。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import path from 'path';
require('dotenv').config();
export const STORAGE_STATE = path.join(__dirname, 'playwright/.auth/user.json');
export default defineConfig({
testDir: './tests',
// Configure the reporter
reporter: ['html'],
// Retry on CI only
retries: process.env.CI ? 2 : 0,
// Run tests in files in parallel
fullyParallel: true,
use: {
baseURL: 'https://en.wikipedia.org',
// run traces on the first retry of a failed test
trace: 'on-first-retry',
},
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'e2e tests logged in',
dependencies: ['setup'],
use: {
storageState: STORAGE_STATE,
},
},
],
});
您可以继续向配置中添加更多项目,以添加不需要用户登录的测试。使用测试过滤器,testIgnore
您可以在运行该项目中的测试时忽略所有设置测试和登录测试。
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import path from 'path';
require('dotenv').config();
export const STORAGE_STATE = path.join(__dirname, 'playwright/.auth/user.json');
export default defineConfig({
testDir: './tests',
// Configure the reporter
reporter: ['html'],
// Retry on CI only
retries: process.env.CI ? 2 : 0,
// Run tests in files in parallel
fullyParallel: true,
use: {
baseURL: 'https://en.wikipedia.org',
// run traces on the first retry of a failed test
trace: 'on-first-retry',
},
projects: [
{
name: 'setup',
testMatch: '**/*.setup.ts',
},
{
name: 'e2e tests logged in',
dependencies: ['setup'],
use: {
storageState: STORAGE_STATE,
},
},
{
name: 'e2e tests',
testIgnore: ['**/*loggedin.spec.ts', '**/*.setup.ts'],
},
],
});
如果您未指定浏览器,测试将默认在 Chromium 上运行。当然,您也可以在不同的浏览器和设备上运行这些测试,并设置更多项目。要了解有关项目和浏览器的更多信息,请查看 Playwright 文档。
查看 HTML 报告和跟踪查看器
现在,您可以使用标志从 CLI 运行测试,--trace on
以便查看测试的完整报告,包括“设置”和“登录的 e2e 测试”,还可以查看每个测试的跟踪。
npx playwright test --trace on
运行测试后,您应该在 CLI 中看到 2 个测试已通过,现在您可以运行命令来打开 HTML 报告。
npx playwright show-report
此命令打开 Playwright HTML 报告,您可以在其中看到您的两个项目,包含登录测试的“设置”项目和包含菜单测试和注销测试的“e2e 测试登录”项目。
您可以打开每个测试的报告(包括“设置测试”)并完成测试的每个步骤,这对于调试非常有帮助。
为了进一步提升调试体验,使用此--trace on
标志时,您将获得所有测试(包括设置测试)的完整跟踪记录。您可以打开跟踪记录并查看时间线或逐个查看每个操作,查看网络请求、控制台、测试源代码,并使用开发工具检查 DOM 快照。
通过单击 DOM 快照上方的弹出按钮,您可以完整查看您的跟踪,您可以在其中使用开发工具轻松检查代码并在需要时调试全局设置。
结论
使用项目依赖项可以更轻松地通过开箱即用的 HTML 报告和设置跟踪进行全局设置。
- 查看Playwright 文档以了解更多信息
- 观看1.31 版本视频,其中有类似的演示。
- 克隆此演示的存储库