技術系

NodeでE2Eテスト

技術系

こんにちは、なかにしです。

今回はE2Eテストを試してみようと思います!

E2Eテストとは

フロントエンドテストの中でも最終段階で行われるテストです。

ユーザーの視点に立ち、アプリケーション全体の動作を確認することで、機能の一貫性と信頼性を保証します。

ライブラリ選定

有名どころだと、以下があります。

・Selenium
・Cypress
・playwright

今回はplaywrightを使用します。

playwrightの特徴は、以下です。
・Microsoft で開発およびメンテナンスが行われている、Node.js ベースの E2E テスト自動化フレームワーク
・マルチブラウザ対応(Chrome,Edge,Firefoxなど)
・モバイル用ブラウザも対応
・導入が簡単

CypressやSeleniumは使用したことがあったので、
playwrightも使ってみたいなーと思ったのが本音です。

テストを実施する

初期設定~導入

今回はNext.jsのアプリを対象として、E2Eテストを実施していきます。

まずは、Next.jsのアプリを用意します。

npx create-next-app

念のため、サーバが起動するか確認します。

npm run dev

初期画面が表示されることを確認したら、playwrightを導入していきます。

npm init playwright@latest

▽どのディレクトリに導入しますか?などを聞かれるので答えていきます。

▽ 終わりました。
Happy hacking!と言われたので楽しみます。

▽ testディレクトリ配下に、サンプル用のテストが書かれています。
3~8行目では、playwrightのページへ遷移し、Titleタグに「Playwright」という文字があるかを確認しているみたいですね。

テストの実行(サンプル)

それでは、先ほど作成されたサンプル用のテストを実行してみます。
以下コマンドで、testディレクトリ配下のテストをすべて実行します。

npx playwright test

▽ 終わったみたいです。

結果を見るには以下コマンドを打てと言われているので、確認します。

npx playwright show-report

▽ 結果が表示されました。
サンプルのコードでは、「has title」と「get started link」の2つのテストがありましたので、それが各ブラウザで実行されているようです。

今回はchromium、firefox、webkitで実行されています。
WebKitというと、Safariに使用されているHTMLレンダリングエンジンですね。

このあたりのブラウザ設定は、playwright.config.tsから変更することができます。

▽ 現在は chromium、firefox、webkitのみコメントアウトが外されています。
他のブラウザも、コメントアウトを外すことで実行できます。

// 35行目~  
/* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },

    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },

    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },

    /* Test against mobile viewports. */
    // {
    //   name: 'Mobile Chrome',
    //   use: { ...devices['Pixel 5'] },
    // },
    // {
    //   name: 'Mobile Safari',
    //   use: { ...devices['iPhone 12'] },
    // },

    /* Test against branded browsers. */
    // {
    //   name: 'Microsoft Edge',
    //   use: { ...devices['Desktop Edge'], channel: 'msedge' },
    // },
    // {
    //   name: 'Google Chrome',
    //   use: { ...devices['Desktop Chrome'], channel: 'chrome' },
    // },
  ],

UIモードを使用すると、ブラウザを使用してテストの実行をしたり、ログやエラーの詳細を見ることができます。公式もオススメしている方法です。

npx playwright test --ui

▽ ブラウザが立ち上がり、手動実行できる

テストの実行(オリジナル)

基本的な使い方も分かったので、オリジナルのテストを書いていこうと思います。

今回は、以下の処理をテストしてみたいと思います。
・ボタンを押したらRoute HandlersにGETリクエストを投げる
・Route HandlersからJSON Placeholderにリクエストを投げ、データを取得する

▽ まずはボタンを用意します。

"use client";
import styles from "./page.module.css";

export default function Home() {
  const requestToAPIRoute = async () => {
    const response = await fetch("/api/getJsonData");
    const data = await response.json();
    console.log(data);
  };

  return (
    <main className={styles.main}>
      <div>
        <button onClick={requestToAPIRoute}>
          API Routeにリクエストするボタン
        </button>
      </div>
    </main>
  );
}

▽ Route Handlersを用意します。

import { NextResponse } from "next/server";

export async function GET() {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  const data = await response.json();
  return NextResponse.json(data);
}

テストを用意します。
今回は、2種類用意しました。

テスト① API側をモック化し、ブラウザの挙動のみにフォーカスしたテスト
テスト② API側をモック化せず、実際の動きにフォーカスしたテスト

▽ テスト①

import { expect, test } from "@playwright/test";

test("APIボタンのテスト", async ({ page }) => {
  // ページに移動
  await page.goto("http://localhost:3000/");

  // ボタンが配置されているか確認
  const button = await page.locator("button");
  await expect(button).toBeVisible();

  // ボタンのテキストが正しいか確認
  await expect(button).toHaveText("API Routeにリクエストするボタン");

  // APIリクエストのモックを設定
  await page.route("http://localhost:3000/api/getJsonData", (route) => {
    route.fulfill({
      status: 200,
      body: JSON.stringify({ message: "Success" }),
    });
  });

  // ボタンをクリック
  await button.click();

  // コンソールにAPIリクエストの結果が出力されるか確認
  page.on("console", (msg) => {
    if (msg.type() === "log") {
      expect(msg.text()).toContain("Success");
    }
  });
});

▽ テスト②

import { expect, test } from "@playwright/test";

test("API Routeへリクエストが飛ぶかテスト", async ({ page }) => {
  await page.goto("http://localhost:3000/");

  // ボタンが配置されているか確認
  const button = await page.locator("button");
  await expect(button).toBeVisible();

  // ボタンのテキストが正しいか確認
  await expect(button).toHaveText("API Routeにリクエストするボタン");

  // ボタンをクリック
  await button.click();

  // コンソールにAPIリクエストの結果が出力されるか確認
  const consoleMessage = await page.waitForEvent("console");
  if (consoleMessage.type() === "log") {
    const messageText = consoleMessage.text();

    // 実際に取得されるデータの中身をチェック
    expect(messageText).toContain("est rerum tempore");
  }
});

▽ どちらのテストも成功しました。

さいごに

各ブラウザで手軽にテストが実行できるのはいいですね!
導入やコマンドが簡単なのも個人的に好みです。

私はChromeをメインで使用しているので、個人アプリだとSafariやEdgeでの確認をつい怠ってしまうのですが、これだけ簡単に導入できると、ちょっと頑張って書いてみようと思えますね。

テストはアプリの品質に直結するので、ガツガツ書いて慣れていこうと思います。

今回はここまで!
Enjoy Hacking!!

タイトルとURLをコピーしました