RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

【Playwright】v1.4系の新機能まとめ

こんにちは、フロントエンド開発課所属のkoki_matsuraです!
本記事では、E2EテストライブラリであるPlaywrightのv1.40 ~ 最新版v1.43で追加された機能の中から僕の独断と偏見でいくつかを紹介したいと思います。
では早速、紹介していきます! 以下は目次です。

v1.40の新機能

Test Generatorにアサーションコード生成機能

Playwrightの目玉機能の画面上の操作をテストコードに書き起こしてくれる、Test Generatorにv1.40からアサーションコードを生成する機能が追加されました。
下画像はv1.39とv1.40のTest Generatorの初期画面を比較したものです。

  • v1.39

  • v1.40

違いは画面上部のツールです。
このツールには6つのアイコンがあります。


左から順に「ツールバーの移動」「Test Generateの中断」「要素の取得」「toBeVisibleアサーション」「toContainTextアサーション」「toHaveValueアサーション」を対応します。
今まではTest Generatorの中断や要素の取得はできていました。しかし、アサーションは対応していなかったのでユーザが自身で書かなければなりませんでした。
v1.40からは簡単なテストであれば、最初から最後までTest Generatorで書くことが可能になります!

toBeVisibleアサーション

使い方は簡単で、目のマークをクリックし、アサーションしたい要素をクリックするのみです。

上画像のように「ラクスの思い」というlinkをクリックすると、下記のテストコードが生成されます。

await expect(page.getByRole('link', { name: 'ラクスの思い' }).first()).toBeVisible();  

toContainTextアサーション

これも同様に、'ab'のアイコンをクリックして、アサーション対象をクリックします。
すると、textBoxが出てくるのでここに含むと思われるテキストを入力します。

チェックマークをクリックすればコードが生成されます。

await expect(page.locator('#APjFqb')).toContainText('ラクス');

toHaveValueアサーション

ここも同じです。
アサーション対象をクリックするだけで生成されます。

await expect(page.getByRole('combobox', { name: '検索' })).toHaveValue('ラクス');

v1.41の新機能

screenshot関数のstyleオプション

VRT(Visual Regression Test)を行う際にscreenshot関数を使った人も多いと思います。
この関数にはオプションがいくつかあるのですが、v1.41でstyleオプションが追加されました。
このオプションには記述したスタイルをスクリーンショット作成時に反映してくれます。
下記が具体的な書き方です。

 await page.screenshot({
      style: `${カスタムなスタイル}`,
      path: `${画像の保存先のパス}`,
 });

どの様な場面で使えるのかを一例を交えて紹介します。
下画像のようなトップ画面があるとします。(Muiのテンプレを使わせていただきました)

このトップ画面をスクショしたいのですが、一定の確率で邪魔なやつが出現します。

styleオプションが出るまでは、消す操作を行ったり、コード自体をいじったりして対応していました。ですが、一定の確率で出現する場合、消す操作をテストコードに入れると出現しなかった時、エラーを起こしてしまいます。

そういう時にこのstyleoptionが使えます。
使い方は簡単で、邪魔なやつの要素を指定して、非表示にするだけです。
テストコードだと下記の様になります。
邪魔なやつにはid="obstruction-card"を付与しています。

 await page.screenshot({
      style: "#obstruction-card { display : none }",
      path: "tests/screenshot/sample.png",
 });

これだけで保存されたスクショには邪魔なやつは写っていないはずです。

toHaveScreenshot関数のstylePathオプション

toHaveScreenshotは事前に保存していた画像と指定したpageまたはlocatorの画像を比較し、差分が出ている場合には差分の画像も出力してくれる便利な関数です。
この関数にも先ほどに似たスタイル系のオプションが増えました。
少し違うのは、スタイルシートではなく、スタイルシートへのパスを記述する点です。
下記の様に書きます。
sample.pngは事前に用意しておく画像です。
また、stylePath内のスタイルはこれからスクショする画像に対して、反映されます。

await expect(page).toHaveScreenshot("sample.png", {
      stylePath: "tests/sample.css",
});

v1.42の新機能

addLocatorHandler関数

※ これはExperimentalです。

この関数はLocatorとHandlerの2つの引数を取り、そのLocatorに対して、Handlerの内容を実行します。

await page.addLocatorHandler( ${Locator}, ${Handler} );

具体的な使い道としては、v1.41の一例で出したものと同じでE2Eテスト中に表示される邪魔なやつを処理したいときです。

上画像では「Sign In」のボタンの上に邪魔なやつが表示されています。
もしこの状態で下記ようなSignInボタンを押す処理が入っているテストを実行すると失敗してしまいます。

test(
      "Sign in ボタンを押すと、ログイン画面が表示されること",
      async ({ page }) => {
        await page.goto("http://localhost:5173/");
        await page.getByTestId("sign-in-button").click();
        expect(page.url()).toEqual("http://localhost:5173/login");
      }
 );

この様な場合に、邪魔なやつへの操作を最初に定義することで適切にテストが通ります。

 async ({ page }) => {
    await page.addLocatorHandler(
      page.getByTestId("obstruction-card"),
      async () => {
        await page.getByTestId("card-cancel-button").click();
      }
    
    await page.goto("http://localhost:5173/");
    ...
 )

タグの追加

各テストに対して、タグがつけられる様になりました。
test関数の第二引数のオプションから指定します。
付けたいタグが1つの場合はstring型でも大丈夫です。

test('sampleTest', {
  tag: ['@sample'],
}, async ({ page }) => {
  // ...
});

タグを指定できることによって、テストをタグ絞り込みで実行できます。
例えば、@sampleとタグ付けしたテストのみ実行したい場合は、下記の様にテスト実行を行います。

npx playwright test --grep @sample

今までのテスト実行では任意のテストのみ実行するのは難しかったので、個人的には非常に嬉しい機能です。

v1.43の新機能

LocatorとFrameLocatorの相互変換

LocatorにはFrameLocatorへ変換をかけるcontentFrameという関数、 FrameLocatorにはLocatorへ変換をかけるownerという関数が追加されました。

// FrameLocator型への変換
const frameLocator = locator.contentFrame(); 
// Locator型への変換
const locator = frameLocator.owner();

個人的にはFrameLocatorオブジェクトを保持しておき、好きなタイミングでLocatorにすぐに変換できるowner関数が嬉しいです。

clearCookiesのフィルター機能

Cookieを削除するclearCookies関数のオプションにフィルターの機能が増え、特定のCookieのみを削除するということが可能になりました。

使い方は下記の様にCookie情報を引数に与えることでフィルターをかけます。
具体的には、cookienameまたは、domainまたは、pathを指定します。

await context.clearCookies({ ${Cookie情報} });

具体的なテストコードの一例を載せておきます。
適当なCookieを2つ設定し、name : id-1のものを削除しています。

test("clearCookies id-1", async ({ context }) => {
    await context.addCookies([
      {
        name: "id-1",
        value: "value-1",
        url: "http://localhost:5173/",
      },
      {
        name: "id-2",
        value: "value-2",
        url: "http://localhost:5173/",
      },
    ]);

    await context.clearCookies({ name: "id-1" });

    const cookies = await context.cookies();

    expect(cookies).toEqual([
      {
        domain: "localhost",
        expires: -1,
        httpOnly: false,
        name: "id-2",
        path: "/",
        sameSite: "Lax",
        secure: false,
        value: "value-2",
      },
    ]);
  });
});

まとめ

本記事ではPlaywright v1.40~v1.43の中から僕の独断と偏見でアップデートした部分を紹介させていただきました。
個人的にはexperimentalではあるのですが、addLocatorHandlerが一番嬉しい機能でした!
Playwrightは去年あたりからユーザが増え、それに伴い、ものすごく便利な機能がどんどんと増えていて、開発で使っている身としては嬉しい限りです。

今回紹介していない機能もありますので、よければ公式サイトのRelease Noteを見ていただければなと思います。
最後まで読んでいただきありがとうございました!

Copyright © RAKUS Co., Ltd. All rights reserved.