スポンサーリンク

.NETのReqnrollプロジェクトでPlaywrightを使うときのコード構成(基本)

この記事は「Reqnroll × Playwrightで始めるE2Eテスト入門」シリーズの一部です。

.NETのReqnrollプロジェクトでPlaywrightを使うときのコード構成(基本)

E2Eテストを.NETで実装する場合、BDDツールである Reqnroll と、ブラウザ自動化ツール Playwright を組み合わせるケースが増えています。

しかし、実際に実装しようとすると次の疑問が出てきます。

  • Playwrightの初期化コードはどこに書くのか
  • StepDefinitionからどうやってブラウザを操作するのか
  • Pageオブジェクトはどこで管理するのか

この記事では、ReqnrollプロジェクトでPlaywrightを使うときの基本的なコード構成を解説します。

※この記事では環境構築の説明は省略し、コード構成にフォーカスします。環境構築は以下の記事で解説。
⇒ Reqnroll + Playwrightの環境構築手順(.NET / C#)

Reqnroll + Playwrightの基本構成

ReqnrollでPlaywrightを使う場合、次のような構成にするのが一般的です。

TestProject
├ Hooks
│ └ PlaywrightHooks.cs

├ Pages
│ └ LoginPage.cs

├ Steps
│ └ LoginSteps.cs

└ Features
└ Login.feature

それぞれの役割は次の通りです。

フォルダ役割
FeaturesBDDのシナリオを書く
Stepsシナリオの実装
HooksPlaywrightの初期化
PagesPageObject

このように役割ごとにフォルダを分けることで、テストコードが増えても管理しやすくなります。

Playwrightの初期化(Hooks)

Playwrightのブラウザ起動処理は、ReqnrollのHooksに書くのが一般的です。

⇒ Hooksの解説は次の記事で確認できます。
ReqnrollのHooksとは?シナリオ前後で処理を実行する方法を解説(.NET)

Reqnrollには BeforeScenarioAfterScenario があり、テストの前後処理をまとめて管理できます。

例として、Playwrightの初期化コードは次のようになります。

using Microsoft.Playwright;
using Reqnroll;

[Binding]
public class PlaywrightHooks
{
public static IPage Page;
private static IBrowser browser;
private static IPlaywright playwright;

[BeforeScenario]
public async Task BeforeScenario()
{
playwright = await Playwright.CreateAsync();

browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = false
});

var context = await browser.NewContextAsync();

Page = await context.NewPageAsync();
}

[AfterScenario]
public async Task AfterScenario()
{
await browser.CloseAsync();
playwright.Dispose();
}
}

このクラスでは次の処理を行っています。

  • Playwrightの起動
  • ブラウザの起動
  • Pageオブジェクトの作成

このPageをStepDefinitionから利用します。

PlaywrightHooksクラスの解説

PlaywrightHooksクラスの役割

このクラスは、Reqnroll のHooks機能を使い、
テスト実行の前後で Playwright のブラウザを起動・終了するためのクラスです。

Reqnrollでは Hooks を使うことで、

  • テスト開始前の処理
  • テスト終了後の処理

を共通化できます。

このコードでは、Scenarioごとにブラウザを起動し、終了時に閉じる構成になっています。

usingディレクティブ

using Microsoft.Playwright;
using Reqnroll;

ここでは必要なライブラリを読み込んでいます。

名前空間役割
Microsoft.PlaywrightPlaywrightのAPI
ReqnrollReqnrollのBDD機能

Playwrightを操作するためのクラス(IPageやIBrowserなど)は、
Microsoft.Playwright 名前空間に含まれています。

Binding属性

[Binding]
public class PlaywrightHooks

[Binding]Reqnrollがこのクラスをテスト実行時に認識するための属性です。

この属性が付いているクラスは、

  • StepDefinition
  • Hooks

としてReqnrollに登録されます。

Hooksとして機能させる場合も、この属性が必要になります。

フィールド(変数)の定義

public static IPage Page;
private static IBrowser browser;
private static IPlaywright playwright;

ここではPlaywrightの主要なオブジェクトを定義しています。

変数役割
IPlaywrightPlaywright本体
IBrowserブラウザインスタンス
IPageブラウザのタブ

Playwrightでは次の階層でブラウザを操作します。

Playwright

Browser

BrowserContext

Page

今回のコードでは、最終的に PageをStepDefinitionから使えるようにしています。

Pagepublic staticにしているのは、
StepDefinitionクラスから参照できるようにするためです。

await PlaywrightHooks.Page.GotoAsync("https://example.com");

BeforeScenario

[BeforeScenario]
public async Task BeforeScenario()

[BeforeScenario] は、
シナリオ実行前に呼び出されるメソッドです。

つまり

Scenario開始

BeforeScenario実行

StepDefinition実行

という順番になります。

Playwrightの起動

playwright = await Playwright.CreateAsync();

ここではPlaywrightのインスタンスを作成しています。

Playwrightを使うときは、まずこのオブジェクトを作る必要があります。

ブラウザの起動

browser = await playwright.Chromium.LaunchAsync(
new BrowserTypeLaunchOptions
{
Headless = false
});

ここではChromiumブラウザを起動しています。

Headless の設定によって、ブラウザ表示の有無が変わります。

設定意味
true画面を表示しない
falseブラウザを表示する

テストのデバッグ時は、falseにしておくとブラウザ動作を確認できます。

BrowserContextの作成

var context = await browser.NewContextAsync();

BrowserContext は、ブラウザの独立したセッションです。

イメージとしては

ブラウザ
├ シークレットセッション1
├ シークレットセッション2

のような構造になります。

テストでは、シナリオごとに新しいContextを作ることで

  • Cookie
  • LocalStorage
  • セッション情報

を分離できます。

Pageの作成

Page = await context.NewPageAsync();

ここで ブラウザタブ(Page) を作成しています。

Playwrightで実際に操作するのは、このPageオブジェクトです。

例えば

Page.GotoAsync()
Page.ClickAsync()
Page.FillAsync()

などの操作を行います。

AfterScenario

[AfterScenario]
public async Task AfterScenario()

[AfterScenario]
シナリオ終了後に呼ばれるメソッドです。

処理の流れ

Scenario終了

AfterScenario実行

ブラウザ終了

await browser.CloseAsync();

ここではブラウザを閉じています。

テストごとにブラウザを終了することで、

  • メモリリーク防止
  • テストの独立性確保

ができます。

Playwrightの破棄

playwright.Dispose();

Playwrightのリソースを解放しています。

.NETでは、外部リソースを使うライブラリは
Disposeを呼んで解放するのが推奨されています。

このコードの処理の流れ

最終的にこのHooksは次のように動きます。

Scenario開始

BeforeScenario

Playwright起動

Browser起動

Context作成

Page作成

StepDefinition実行

AfterScenario

Browser終了

Playwright破棄

StepDefinitionからPlaywrightを使う

StepDefinitionでは、Hooksで作成したPageを利用してブラウザ操作を行います。

例として、ログインページを操作するStepDefinitionは次のように書けます。

using Reqnroll;

[Binding]
public class LoginSteps
{
[Given(@"ログインページを開く")]
public async Task OpenLoginPage()
{
await PlaywrightHooks.Page.GotoAsync("https://example.com/login");
}

[When(@"ユーザー名とパスワードを入力する")]
public async Task InputLogin()
{
await PlaywrightHooks.Page.FillAsync("#user", "test");
await PlaywrightHooks.Page.FillAsync("#password", "password");
}

[When(@"ログインボタンを押す")]
public async Task ClickLogin()
{
await PlaywrightHooks.Page.ClickAsync("#login");
}
}

このようにすると、次の流れでテストが実行されます。

Feature → StepDefinition → Playwright → ブラウザ操作

PageObjectを使った構成

テストコードが増えてくると、StepDefinitionに直接Playwrightの操作を書くと管理が難しくなります。

そのため、多くのプロジェクトでは PageObjectパターン を使います。

例として、ログインページのPageObjectは次のように書きます。

using Microsoft.Playwright;

public class LoginPage
{
private readonly IPage page;

public LoginPage(IPage page)
{
this.page = page;
}

public async Task Open()
{
await page.GotoAsync("https://example.com/login");
}

public async Task Login(string user, string password)
{
await page.FillAsync("#user", user);
await page.FillAsync("#password", password);
await page.ClickAsync("#login");
}
}

StepDefinitionでは、このPageObjectを利用します。

[Binding]
public class LoginSteps
{
private readonly LoginPage loginPage;

public LoginSteps()
{
loginPage = new LoginPage(PlaywrightHooks.Page);
}

[Given(@"ログインページを開く")]
public async Task OpenPage()
{
await loginPage.Open();
}
}

この構成にすると、次のメリットがあります。

  • StepDefinitionがシンプルになる
  • UI変更の影響を受けにくい
  • 同じ操作を複数テストで再利用できる

Reqnroll + Playwrightの処理の流れ

最終的にテストは次のような構造になります。

Featureファイル

StepDefinition

PageObject

Playwright

ブラウザ操作

このような構成にすることで、E2Eテストが増えても保守しやすいコードになります。

まとめ

.NETのReqnrollプロジェクトでPlaywrightを使う場合は、次の構成にすると管理しやすくなります。

基本構成

  • Hooks
    Playwrightの初期化
  • StepDefinitions
    シナリオの実装
  • Pages
    PageObject

処理の流れ

Feature
→ StepDefinition
→ PageObject
→ Playwright

このような構成にしておくことで、テストコードが増えても整理されたE2Eテストを維持することができます。

.NET
スポンサーリンク
シェアする
trelab