身份验证
介绍
Playwright 在称为 浏览器上下文 的隔离环境中执行测试。这种隔离模型提高了可重现性,并防止级联测试失败。测试可以加载现有的身份验证状态。这消除了在每次测试中进行身份验证的需要,并加快了测试执行速度。
核心概念
无论您选择何种身份验证策略,您都可能将已验证的浏览器状态存储在文件系统中。
我们建议创建 playwright/.auth
目录并将其添加到您的 .gitignore
文件中。您的身份验证例程将生成已验证的浏览器状态,并将其保存到此 playwright/.auth
目录中的文件中。之后,测试将重用此状态,并以已验证的状态开始。
浏览器状态文件可能包含敏感的 Cookie 和标头,这些信息可能被用于冒充您或您的测试账户。我们强烈不建议将它们提交到私有或公共仓库中。
- Bash
- PowerShell
- Batch
mkdir -p playwright/.auth
echo $'\nplaywright/.auth' >> .gitignore
New-Item -ItemType Directory -Force -Path playwright\.auth
Add-Content -path .gitignore "`r`nplaywright/.auth"
md playwright\.auth
echo. >> .gitignore
echo "playwright/.auth" >> .gitignore
在每次测试前登录
Playwright API 可以自动执行与登录表单的交互。
以下示例登录到 GitHub。一旦执行这些步骤,浏览器上下文将完成身份验证。
var page = await context.NewPageAsync();
await page.GotoAsync("https://github.com/login");
// Interact with login form
await page.GetByLabel("Username or email address").FillAsync("username");
await page.GetByLabel("Password").FillAsync("password");
await page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync();
// Continue with the test
在每次测试中重新登录可能会减慢测试执行速度。为了缓解这个问题,请改为重用现有的身份验证状态。
重用已登录状态
Playwright 提供了一种在测试中重用已登录状态的方法。这样,您只需登录一次,然后就可以跳过所有后续测试的登录步骤。
Web 应用程序使用基于 cookies 或基于 token 的身份验证,其中已验证状态存储在 cookies、本地存储 或 IndexedDB 中。Playwright 提供了 BrowserContext.StorageStateAsync() 方法,可用于从已验证的上下文检索存储状态,然后使用预填充的状态创建新的上下文。
Cookies、本地存储和 IndexedDB 状态可以在不同浏览器中使用。它们取决于您的应用程序的身份验证模型,该模型可能需要 Cookies、本地存储或 IndexedDB 的某种组合。
以下代码片段从已验证的上下文检索状态,并使用该状态创建新的上下文。
// Save storage state into the file.
// Tests are executed in <TestProject>\bin\Debug\netX.0\ therefore relative path is used to reference playwright/.auth created in project root
await context.StorageStateAsync(new()
{
Path = "../../../playwright/.auth/state.json"
});
// Create a new context with the saved storage state.
var context = await browser.NewContextAsync(new()
{
StorageStatePath = "../../../playwright/.auth/state.json"
});
高级场景
会话存储
重用已验证状态涵盖了基于 cookies、本地存储 和 IndexedDB 的身份验证。极少数情况下,会话存储 被用于存储与已登录状态相关的信息。会话存储 特定于某个特定域,并且不会在页面加载时持久保存。Playwright 没有提供 API 来持久化会话存储,但可以使用以下代码片段来保存/加载会话存储。
// Get session storage and store as env variable
var sessionStorage = await page.EvaluateAsync<string>("() => JSON.stringify(sessionStorage)");
Environment.SetEnvironmentVariable("SESSION_STORAGE", sessionStorage);
// Set session storage in a new context
var loadedSessionStorage = Environment.GetEnvironmentVariable("SESSION_STORAGE");
await context.AddInitScriptAsync(@"(storage => {
if (window.location.hostname === 'example.com') {
const entries = JSON.parse(storage);
for (const [key, value] of Object.entries(entries)) {
window.sessionStorage.setItem(key, value);
}
}
})('" + loadedSessionStorage + "')");