编写测试
简介
Playwright 测试非常简单,它们
- 执行操作,并且
- 根据预期断言状态。
在执行操作之前无需进行任何等待:Playwright 会在执行每个操作之前自动等待各种可操作性检查通过。
在执行检查时也无需处理竞态条件——Playwright 断言的设计方式使得它们能够描述最终需要满足的预期。
就是这样!这些设计选择使 Playwright 用户可以彻底告别测试中不稳定的超时和竞态检查。
您将学到
第一个测试
请查看以下示例,了解如何编写测试。
- MSTest
- NUnit
- xUnit
- xUnit v3
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class ExampleTest : PageTest
{
[Test]
public async Task HasTitle()
{
await Page.GotoAsync("https://playwright.net.cn");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
}
[Test]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.net.cn");
// Click the get started link.
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
}
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright;
using Microsoft.Playwright.MSTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PlaywrightTests;
[TestClass]
public class ExampleTest : PageTest
{
[TestMethod]
public async Task HasTitle()
{
await Page.GotoAsync("https://playwright.net.cn");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
}
[TestMethod]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.net.cn");
// Click the get started link.
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
}
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task HasTitle()
{
await Page.GotoAsync("https://playwright.net.cn");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
}
[Fact]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.net.cn");
// Click the get started link.
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
}
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit.v3;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task HasTitle()
{
await Page.GotoAsync("https://playwright.net.cn");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
}
[Fact]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.net.cn");
// Click the get started link.
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
}
操作
导航
大多数测试都会从将页面导航到某个 URL 开始。此后,测试便可以与页面元素进行交互。
await Page.GotoAsync("https://playwright.net.cn");
Playwright 将在继续操作前等待页面达到加载状态。了解更多关于 Page.GotoAsync() 选项的信息。
交互
执行操作从定位元素开始。Playwright 使用 Locators API 来实现这一点。定位器(Locators)代表了一种在任何时刻查找页面元素的方法,了解更多关于可用不同类型的定位器的信息。Playwright 会在执行操作前等待元素变得可操作,因此无需等待其变为可用状态。
// Create a locator.
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
// Click it.
await getStarted.ClickAsync();
在大多数情况下,它会写在一行中
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
基本操作
以下是最常用的 Playwright 操作列表。请注意,还有更多操作,请务必查看 Locator API 部分以了解更多信息。
| 操作 | 描述 |
|---|---|
| Locator.CheckAsync() | 选中输入复选框 |
| Locator.ClickAsync() | 点击元素 |
| Locator.UncheckAsync() | 取消选中输入复选框 |
| Locator.HoverAsync() | 鼠标悬停在元素上 |
| Locator.FillAsync() | 填写表单字段,输入文本 |
| Locator.FocusAsync() | 聚焦元素 |
| Locator.PressAsync() | 按下单个键 |
| Locator.SetInputFilesAsync() | 选择要上传的文件 |
| Locator.SelectOptionAsync() | 在下拉列表中选择选项 |
断言
Playwright 提供了一个名为 Expect 的异步函数,用于断言并等待直到满足预期条件。
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
以下是最常用的异步断言列表。请注意,还有更多断言可供熟悉
测试隔离
Playwright 的 NUnit、MSTest、xUnit 和 xUnit v3 测试框架基类通过提供单独的 Page 实例将每个测试相互隔离。由于浏览器上下文(Browser Context)的存在,页面在测试之间是隔离的,这等同于一个全新的浏览器配置文件,每个测试即使在同一个浏览器中运行,也能获得全新的环境。
- MSTest
- NUnit
- xUnit
- xUnit v3
using System.Threading.Tasks;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class ExampleTest : PageTest
{
[Test]
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.net.cn");
}
}
using System.Threading.Tasks;
using Microsoft.Playwright.MSTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PlaywrightTests;
[TestClass]
public class ExampleTest : PageTest
{
[TestMethod]
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.net.cn");
}
}
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.net.cn");
}
}
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit.v3;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.net.cn");
}
}
使用测试钩子(Test Hooks)
- MSTest
- NUnit
- xUnit
- xUnit v3
您可以使用 SetUp/TearDown 来准备和清理您的测试环境
using System.Threading.Tasks;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class ExampleTest : PageTest
{
[Test]
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.net.cn/");
}
[SetUp]
public async Task SetUp()
{
await Page.GotoAsync("https://playwright.net.cn");
}
}
您可以使用 TestInitialize/TestCleanup 来准备和清理您的测试环境
using System.Threading.Tasks;
using Microsoft.Playwright.MSTest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace PlaywrightTests;
[TestClass]
public class ExampleTest : PageTest
{
[TestMethod]
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.net.cn/");
}
[TestInitialize]
public async Task TestInitialize()
{
await Page.GotoAsync("https://playwright.net.cn");
}
}
您可以使用 InitializeAsync/DisposeAsync 来准备和清理您的测试环境
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.net.cn/");
}
override public async Task InitializeAsync()
{
await base.InitializeAsync();
await Page.GotoAsync("https://playwright.net.cn");
}
public override async Task DisposeAsync()
{
Console.WriteLine("After each test cleanup");
await base.DisposeAsync();
}
}
您可以使用 InitializeAsync/DisposeAsync 来准备和清理您的测试环境
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit.v3;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.net.cn/");
}
override public async Task InitializeAsync()
{
await base.InitializeAsync();
await Page.GotoAsync("https://playwright.net.cn");
}
public override async Task DisposeAsync()
{
Console.WriteLine("After each test cleanup");
await base.DisposeAsync();
}
}