テストランナー
はじめに
数行のコードで、Playwright をお好みの Java テストランナーに組み込むことができます。
Playwright と Browser インスタンスは、パフォーマンス向上のためにテスト間で再利用できます。各テストケースは新しい BrowserContext で実行することを推奨します。これにより、テスト間でブラウザの状態が分離されます。
JUnit
JUnit では、Playwright と Browser を @BeforeAll メソッドで初期化し、@AfterAll で破棄できます。以下の例では、3 つのテストメソッドすべてが同じ Browser を使用しています。各テストは、独自の BrowserContext と 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());
}
}
Playwright オブジェクトなどを自動的に初期化する実験的な JUnit 統合をご覧ください。
並列でのテスト実行
デフォルトでは、JUnit はすべてのテストを単一のスレッドで順番に実行します。JUnit 5.3 以降では、この動作を変更してテストを並列で実行し、実行速度を上げることができます ( こちらのページ を参照してください)。追加の同期なしに複数のスレッドから同じ Playwright オブジェクトを使用するのは安全ではないため、スレッドごとに Playwright インスタンスを作成し、そのスレッドでのみ使用することをお勧めします。以下は、複数のテストクラスを並列で実行する方法の例です。
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
アノテーションを使用して、JUnit にクラス内のすべてのテストメソッドに対してクラスのインスタンスを 1 つ作成させます (デフォルトでは、JUnit は各テストメソッドに対してクラスの新しいインスタンスを作成します)。Playwright および Browser オブジェクトをインスタンスフィールドに格納します。これらはテスト間で共有されます。クラスの各インスタンスは、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 の使用
Groovy または Kotlin で記述された Gradle ビルド構成スクリプトを使用できます。
- build.gradle
- build.gradle.kts
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()
}
plugins {
application
id("java")
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.microsoft.playwright:playwright:1.50.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")
}
}
テストは次のように起動できます
./gradlew run
また、Playwright コマンドラインツールは次のように実行できます
./gradlew playwright --args="help"
TestNG
TestNG では、Playwright と Browser を @BeforeClass メソッドで初期化し、@AfterClass で破棄できます。以下の例では、3 つのテストメソッドすべてが同じ Browser を使用しています。各テストは、独自の BrowserContext と 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());
}
}