跳至主要内容

测试运行器

简介

只需几行代码,您就可以将Playwright连接到您最喜欢的Java测试运行器。

Playwright和浏览器实例可以在测试之间重复使用以提高性能。我们建议在每个测试用例中使用新的BrowserContext,这样浏览器状态将在测试之间保持隔离。

JUnit

JUnit中,您可以在@BeforeAll方法中初始化PlaywrightBrowser,并在@AfterAll中销毁它们。在下面的示例中,所有三个测试方法都使用同一个Browser。每个测试使用自己的BrowserContextPage

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对象等功能。

并行运行测试

默认情况下,JUnit会在单一线程上顺序运行所有测试。从JUnit 5.3开始,您可以更改此行为以并行运行测试来加速执行(参见此页面)。由于在没有额外同步的情况下从多个线程使用相同的Playwright对象是不安全的,我们建议您为每个线程创建Playwright实例,并仅在该线程上使用它。以下是一个如何并行运行多个测试类的示例。

使用@TestInstance(TestInstance.Lifecycle.PER_CLASS)注解让JUnit为该类中的所有测试方法创建一个类实例(默认情况下每个JUnit会为每个测试方法创建新的类实例)。将PlaywrightBrowser对象存储在实例字段中,它们将在测试之间共享。每个类实例将使用自己的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核心数的1/2):

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

您可以使用Gradle构建配置脚本,该脚本可以用Groovy或Kotlin编写。

plugins {
application
id 'java'
}

repositories {
mavenCentral()
}

dependencies {
implementation 'com.microsoft.playwright:playwright:1.50.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()
}

测试可以按以下方式启动:

./gradlew run

此外,Playwright命令行工具可以通过以下方式运行:

./gradlew playwright --args="help"

TestNG

TestNG中,您可以在@BeforeClass方法中初始化PlaywrightBrowser,并在@AfterClass中销毁它们。在下面的示例中,所有三个测试方法都使用同一个Browser。每个测试使用自己的BrowserContextPage

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());
}
}