13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

HITOTSU株式会社Advent Calendar 2022

Day 11

【フロントエンドテスト】PlaywrightでE2Eテストを実施する。

Last updated at Posted at 2022-12-12

はじめに

はじめまして、河村康治です。HITOTSUアドベントカレンダーの11日目担当します!!
普段はバックエンドを主に担当しているのですが、テスト基盤構築に力をいれて行こうと思い、今回のアドベントカレンダーではフロントのテストに関して記載して行こうと思います!!!
今回は、Playwrightを活用したE2Eテストの記事を書いて行きます!!

Playwrightとは??

Microsoft開発中のE2Eのテストライブラリです。もう少しイメージしやすく言うと、SeleniumやPuppeteerなどのスクレイピング実行やコード生成を実行できるツールです。最近の開発では採用される事が増えており、リグレッションテストや受け入れテストを自動化し、テスト工数を削減し品質を高める事に一役買っています!!

スクリーンショット 2022-12-12 17.47.27.png

Playwrightの強みは??

結局、SeleniumやPuppeteerと比べて何がいいかと言うと、一番はコードを自動生成してくれる所です。スクレイピングを実施する場合、Domツリーを解析しコードに落とし込むのが大変。やった人ならばわかるのですが、開発者ツール開いて、class名は〜〜で、idは〜〜みたいな感じでコード解析し、コードに落とし込む。で、トライ&エラーを繰り返しながら作る。ただ、PlaywrightならばGUIでポチポチしていく事でコードが自動生成されます。百聞は一見にしかずなので、下記動画をご覧ください。

■サンプル動画(iphoneの購入サイトへの画面遷移)

E2Eテスト

では、実際にPlaywrightを利用しE2Eテストの実装をしていきましょう!!今回は、Redmineを元にテストを実施していきたいと思います。

Redmineの準備
RedmineはDockerを使いローカルに立てます。
docker-compose.yml
version: '3.8'
services:
  redmine:
    image: redmine
    container_name: redmine
    ports:
      - 3010:3000
    volumes:
      - ./data/plugins:/usr/src/redmine/plugins
      - ./data/themes:/usr/src/redmine/public/themes
    environment:
      REDMINE_DB_MYSQL: redmine-db
      REDMINE_DB_PASSWORD: redmine
    depends_on:
      - redmine-db
    restart: always
    
  redmine-db:
    image: mariadb
    container_name: redmine-db
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: redmine
      MYSQL_DATABASE: redmine
    volumes:
      - ./data/db:/var/lib/mysql
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    restart: always

これでOK!!
http://localhost:3010/でアクセスし、ユーザIDとパスワード共に、adminで入れます。
その後、パスワード変更やプロジェクト作成やトラッカー作成などの準備が必要です。

成果物は下記動画の様になります。

ソースコード

yarnコマンド
yarn create playwright ←これすると、Playwrightで必要な定義ファイルを作ってくれます。
ディレクトリ構成
~/develop/react/playwright_test$ tree -I node_modules               
.
├── README.md
├── docker-compose.yml
├── package.json
├── playwright-report
│   ├── data
│   │   └── 9e7d941236a5e77523b746a304baf6cab737bbc8.webm
│   └── index.html
├── playwright.config.ts
├── prettier.config.js
├── tests
│   ├── example.spec.ts
│   └── redmine.spec.ts
├── tsconfig.json
└── yarn.lock

7 directories, 15 files
redmine.spec.ts
/* eslint-disable testing-library/prefer-screen-queries */
import { test, expect } from '@playwright/test'
import * as dotenv from 'dotenv'
dotenv.config()

test('test', async ({ page }) => {
  const userName = process.env.REACT_APP_USER_NAME || ''
  const password = process.env.REACT_APP_PASSWORD || ''

  await page.goto('http://localhost:3010/')
  await page.getByRole('link', { name: 'ログイン' }).click()
  await page.getByLabel('ログインID').click()
  await page.getByLabel('ログインID').fill(userName)
  await page.getByLabel('ログインID').press('Tab')
  await page.getByLabel('パスワード\n    パスワードの再設定').fill(password)
  await page.getByRole('button', { name: 'ログイン' }).click()
  await page.locator('#top-menu').getByRole('link', { name: 'プロジェクト' }).click()
  await page.getByRole('link', { name: 'test' }).click()
  await page.locator('#main-menu').getByRole('link', { name: 'チケット' }).click()
  await page.getByRole('link', { name: '新しいチケット' }).click()
  await page.getByLabel('題名 *').fill('PlayWright test')
  await page.getByLabel('説明').click()
  await page.getByLabel('説明').fill('PlayWright test')
  await page.locator('input[name="commit"]').click()
  await page.waitForTimeout(3000) // 確認様に3秒待機
  const actual = await page.locator('h2').first().innerText() // ①データ取得
  console.log('actual:', actual)
  await expect(actual).toContain('テスト') // ②値比較
})

ソースコード実装時のPoint

基本的に、npx playwright codegen localhost:3010を利用して記載していきます。
ただ、データ取得や値の比較は実装する必要があるため、記載していきます。
①データ取得
ブラウザの開発者モードを開き、DOMツリーを解析。解析結果を当てはめます。
 スクリーンショット 2022-12-12 19.08.34.png

②実行値と期待値の検証
 今回はチケットのタイトルが「テスト」であるかを検証項目としています。タイトルは「テスト #19」のように余計な値が含まれており、#19はチケット番号を含むため、可変の値となります。そのため、完全一致ではなく、部分一致するかを確認する検証としています。
スクリーンショット 2022-12-12 19.10.45.png

Appendix

Playwrightの設定ファイル
playwright.config.ts
import type { PlaywrightTestConfig } from '@playwright/test';
import { devices } from '@playwright/test';

const config: PlaywrightTestConfig = {
  testDir: './tests',
  /* Maximum time one test can run for. */
  timeout: 30 * 1000,
  expect: {
    timeout: 5000,
  },
  /* Run tests in files in parallel */
  fullyParallel: true,
  /* Fail the build on CI if you accidentally left test.only in the source code. */
  forbidOnly: !!process.env.CI,
  /* Retry on CI only */
  retries: process.env.CI ? 2 : 0,
  /* Opt out of parallel tests on CI. */
  workers: process.env.CI ? 1 : undefined,
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
  reporter: 'html',
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
  use: {
    actionTimeout: 0,
    headless: false, // ブラウザを表示するかどうか
    /* Base URL to use in actions like `await page.goto('/')`. */
    launchOptions:{
      slowMo: 1000, // テスト実行時のスローモーション
    },
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome'],
        locale: 'ja-JP', // ロケールを日本語に設定
      },
    },
  ],

};

export default config;

覚えておきたい事は下記。
①ヘッドレスモードの有無。テスト実行時にブラウザ表示するか。デバッグ時には必須機能!!
②テスト実行時の速度設定。デフォルト設定の場合実行速度が速すぎるため、デバッグ時はスローモーション設定必須。
③ローケールの設定

  use: {
    actionTimeout: 0,
    headless: false, // ブラウザを表示するかどうか
    /* Base URL to use in actions like `await page.goto('/')`. */
    launchOptions:{
      slowMo: 1000, // テスト実行時のスローモーション
    },
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome'],
        locale: 'ja-JP', // ロケールを日本語に設定
      },
    },

Playwrightで覚えておきたい関数

①何秒か待つ
  Debug時や処理を待ちたい時に利用する関数

何秒か待つ
  await page.waitForTimeout(3000) 

②動きを止める
Debug時に開発者ツールでセレクターや値を確認する。

動きを止める
  await page.pause()

test実行時に覚えておきたいオプション

①ブラウザ表示有りで実行
 playwright.config.tsでも定義できますが、開発時はブラウザあり、リグレッションテスト時はブラウザ無し等の要望に答えるため、実行時パラメータで制御可能です!! 

ブラウザありの実行
  ~/develop/react/playwright_test$ npx playwright test redmine.spec.ts --headed

②デバッグモードでのテスト実行
 ブレークポイントを利用したテストが可能となります。

デバッグモードでの実行
~/develop/react/playwright_test$ npx playwright test redmine.spec.ts --debug

スクリーンショット 2022-12-12 20.13.56.png
実行部分がStepByStepで確認でき、赤いポインターが出てどこのセレクターを指しているのかわかりやすいです!!

③show-traceの活用
え、こんなこともできるの、PlayWrightって感じだった機能です。テスト実行時に動作毎にスクショを撮り、後でどんな動きをしたのかを確認できる機能です。事前にコードを仕込む必要があるので、それも記載しておきます。

デバッグモードでの実行
~/develop/react/playwright_test$ npx playwright show-trace ./trace.zip 
コード抜粋
test('test', async ({ page, context }) => {
  await context.tracing.start({ screenshots: true, snapshots: true }) 最初に記載する
  const userName = process.env.REACT_APP_USER_NAME || ''
  const password = process.env.REACT_APP_PASSWORD || ''

  await page.goto('http://localhost:3010/')
~~~~~~~~~~~~~~~~~~~~~割愛~~~~~~~~~~~~~~~~~~~~~~~~~~~
  await expect(actual).toContain('テスト')

  await context.tracing.stop({ path: 'trace.zip' }) ←最後に記載する
})

スクリーンショット 2022-12-12 20.40.59.png
上記画像の様に、各スクリーンショットに対し、実行時間やSelector、値等のさまざまな情報が含まれており、DebugやTrobuleシューティングですごい役立ちそうな機能です!!しかも、Before、Action、Afterのスクショがならんでいるので、ここで何したっていうのが一目瞭然なんですよ!!
SIerで働いてた時、こんな風にスクショ取ってExcelにペタペタ貼ってたので、これは感動しました😭

Before.png
Action.png
After.png

最後に

Playwrightの学習は、Youtubeを中心にやりました。公式サイトや海外Youtuberの方が懇切丁寧に解説してくれているため、効果的に利用すると学習しやすいですよ!!!ちなみに僕は下記で学習しております。

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?