测试运行器
介绍
¥Introduction
只需几行代码,你就可以将 Playwright 连接到你最喜欢的 Java 测试运行器。
¥With a few lines of code, you can hook up Playwright to your favorite Java test runner.
Playwright 和浏览器实例可在测试之间重复使用,以获得更佳性能。我们建议在新的 BrowserContext 中运行每个测试用例,这样浏览器状态将在测试之间隔离。
¥Playwright and Browser instances can be reused between tests for better performance. We recommend running each test case in a new BrowserContext, this way browser state will be isolated between the tests.
JUnit
在 JUnit 中,你可以在 @BeforeAll 方法中初始化 Playwright 和 Browser,并在 @AfterAll 方法中销毁它们。在下面的示例中,所有三个测试方法都使用同一个 Browser。每个测试使用自己的 BrowserContext 和 Page。
¥In JUnit you can initialize Playwright and Browser in @BeforeAll method and destroy them in @AfterAll. In the example below all three test methods use the same Browser. Each test uses its own BrowserContext and Page.
package org.example;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestExample {
// Shared between all tests in this class.
static Playwright playwright;
static Browser browser;
// New instance for each test method.
BrowserContext context;
Page page;
@BeforeAll
static void launchBrowser() {
playwright = Playwright.create();
browser = playwright.chromium().launch();
}
@AfterAll
static void closeBrowser() {
playwright.close();
}
@BeforeEach
void createContextAndPage() {
context = browser.newContext();
page = context.newPage();
}
@AfterEach
void closeContext() {
context.close();
}
@Test
void shouldClickButton() {
page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>");
page.locator("button").click();
assertEquals("Clicked", page.evaluate("result"));
}
@Test
void shouldCheckTheBox() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
page.locator("input").check();
assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked"));
}
@Test
void shouldSearchWiki() {
page.navigate("https://www.wikipedia.org/");
page.locator("input[name=\"search\"]").click();
page.locator("input[name=\"search\"]").fill("playwright");
page.locator("input[name=\"search\"]").press("Enter");
assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url());
}
}
请参阅实验性 JUnit 集成,了解如何自动初始化 Playwright 对象等。
¥See experimental JUnit integration to automatically initialize Playwright objects and more.
并行运行测试
¥Running Tests in Parallel
默认情况下,JUnit 将在单线程上顺序运行所有测试。从 JUnit 5.3 开始,你可以更改此行为以并行运行测试,从而加快执行速度(参见 此页面)。由于在多个线程中使用相同的 Playwright 对象而不进行额外的同步是不安全的,我们建议你为每个线程创建 Playwright 实例,并在该线程上独占使用。以下是如何并行运行多个测试类的示例。
¥By default JUnit will run all tests sequentially on a single thread. Since JUnit 5.3 you can change this behavior to run tests in parallel to speed up execution (see this page). Since it is not safe to use same Playwright objects from multiple threads without extra synchronization we recommend you create Playwright instance per thread and use it on that thread exclusively. Here is an example how to run multiple test classes in parallel.
使用 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
注解使 JUnit 为该类中的所有测试方法创建一个类的实例(默认情况下,每个 JUnit 都会为每个测试方法创建一个该类的新实例)。将 Playwright 和 Browser 对象存储在实例字段中。它们将在测试之间共享。该类的每个实例都将使用自己的 Playwright 副本。
¥Use @TestInstance(TestInstance.Lifecycle.PER_CLASS)
annotation to make JUnit create one instance of a class for all test methods within that class (by default each JUnit will create a new instance of the class for each test method). Store Playwright and Browser objects in instance fields. They will be shared between tests. Each instance of the class will use its own copy of Playwright.
// Subclasses will inherit PER_CLASS behavior.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestFixtures {
// Shared between all tests in the class.
Playwright playwright;
Browser browser;
@BeforeAll
void launchBrowser() {
playwright = Playwright.create();
browser = playwright.chromium().launch();
}
@AfterAll
void closeBrowser() {
playwright.close();
}
// New instance for each test method.
BrowserContext context;
Page page;
@BeforeEach
void createContextAndPage() {
context = browser.newContext();
page = context.newPage();
}
@AfterEach
void closeContext() {
context.close();
}
}
class Test1 extends TestFixtures {
@Test
void shouldClickButton() {
page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>");
page.locator("button").click();
assertEquals("Clicked", page.evaluate("result"));
}
@Test
void shouldCheckTheBox() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
page.locator("input").check();
assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked"));
}
@Test
void shouldSearchWiki() {
page.navigate("https://www.wikipedia.org/");
page.locator("input[name=\"search\"]").click();
page.locator("input[name=\"search\"]").fill("playwright");
page.locator("input[name=\"search\"]").press("Enter");
assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url());
}
}
class Test2 extends TestFixtures {
@Test
void shouldReturnInnerHTML() {
page.setContent("<div>hello</div>");
assertEquals("hello", page.innerHTML("css=div"));
}
@Test
void shouldClickButton() {
Page popup = page.waitForPopup(() -> {
page.evaluate("window.open('about:blank');");
});
assertEquals("about:blank", popup.url());
}
}
配置 JUnit 在每个类中顺序运行测试,并在并行线程上运行多个类(最大线程数等于 CPU 核心数的一半):
¥Configure JUnit to run tests in each class sequentially and run multiple classes on parallel threads (with max number of thread equal to 1/2 of the number of CPU cores):
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = same_thread
junit.jupiter.execution.parallel.mode.classes.default = concurrent
junit.jupiter.execution.parallel.config.strategy=dynamic
junit.jupiter.execution.parallel.config.dynamic.factor=0.5
使用 Gradle
¥Using Gradle
你可以使用用 Groovy 或 Kotlin 编写的 Gradle 构建配置脚本。
¥You can use a Gradle build configuration script, written in Groovy or Kotlin.
- Groovy
- Kotlin
plugins {
application
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.microsoft.playwright:playwright:1.51.0'
}
application {
mainClass = 'org.example.App'
}
// Usage: ./gradlew playwright --args="help"
task playwright(type: JavaExec) {
classpath sourceSets.test.runtimeClasspath
mainClass = 'com.microsoft.playwright.CLI'
}
test {
useJUnitPlatform()
}
plugins {
application
id("java")
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.microsoft.playwright:playwright:1.51.0")
}
application {
mainClass.set("org.example.App")
}
// Usage: ./gradlew playwright --args="help"
tasks.register<JavaExec>("playwright") {
classpath(sourceSets["test"].runtimeClasspath)
mainClass.set("com.microsoft.playwright.CLI")
}
tasks.test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
然后可以按如下方式启动测试:
¥Tests can then be launched as follows:
./gradlew run
此外,可以使用以下命令运行 Playwright 命令行工具:
¥Also, Playwright command line tools can be run with :
./gradlew playwright --args="help"
TestNG
在 TestNG 中,你可以在 @BeforeClass 方法中初始化 Playwright 和 Browser,并在 @AfterClass 方法中销毁它们。在下面的示例中,所有三个测试方法都使用同一个 Browser。每个测试使用自己的 BrowserContext 和 Page。
¥In TestNG you can initialize Playwright and Browser in @BeforeClass method and destroy them in @AfterClass. In the example below all three test methods use the same Browser. Each test uses its own BrowserContext and Page.
package org.example;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import org.testng.annotations.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
public class TestExample {
// Shared between all tests in this class.
Playwright playwright;
Browser browser;
// New instance for each test method.
BrowserContext context;
Page page;
@BeforeClass
void launchBrowser() {
playwright = Playwright.create();
browser = playwright.chromium().launch();
}
@AfterClass
void closeBrowser() {
playwright.close();
}
@BeforeMethod
void createContextAndPage() {
context = browser.newContext();
page = context.newPage();
}
@AfterMethod
void closeContext() {
context.close();
}
@Test
void shouldClickButton() {
page.navigate("data:text/html,<script>var result;</script><button onclick='result=\"Clicked\"'>Go</button>");
page.locator("button").click();
assertEquals("Clicked", page.evaluate("result"));
}
@Test
void shouldCheckTheBox() {
page.setContent("<input id='checkbox' type='checkbox'></input>");
page.locator("input").check();
assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked"));
}
@Test
void shouldSearchWiki() {
page.navigate("https://www.wikipedia.org/");
page.locator("input[name=\"search\"]").click();
page.locator("input[name=\"search\"]").fill("playwright");
page.locator("input[name=\"search\"]").press("Enter");
assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url());
}
}