メインコンテンツへスキップ

テストランナー

はじめに

数行のコードで、Playwrightをお気に入りのJavaテストランナーに接続できます。

PlaywrightとBrowserインスタンスは、パフォーマンス向上のためテスト間で再利用できます。各テストケースを新しいBrowserContextで実行することをお勧めします。これにより、テスト間でブラウザの状態が分離されます。

JUnit

JUnitでは、PlaywrightBrowser@BeforeAllメソッドで初期化し、@AfterAllで破棄できます。以下の例では、3つのテストメソッドすべてが同じ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());
}
}

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

テストは次のように起動できます

./gradlew run

また、Playwrightコマンドラインツールは次のように実行できます。

./gradlew playwright --args="help"

TestNG

TestNGでは、PlaywrightBrowser@BeforeClassメソッドで初期化し、@AfterClassで破棄できます。以下の例では、3つのテストメソッドすべてが同じ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());
}
}