読者です 読者をやめる 読者になる 読者になる

Page Object PatternをベースにTestCafeでE2Eテストを作ってみた

E2E TestCafe


以前のエントリでKotlinでSelenideを使ったE2Eテストを作ったときもPage Object Patternを利用して見通しの良いテストコードが書けました。TestCafeでも同様にPage Object Patternを利用することが推奨されています

今回はTestCafeでもPage Object Patternを利用してテストを書いてみました。

何をテストするか

次のサイトのログイン認証をテストします。

freshlive.tv

テスト内容としては次のとおりです。

  • 認証画面のURLを開く
  • IDとパスワードを入力する
  • ログインボタンをクリックする
  • ログインが完了するとHome画面にリダイレクトされるので正しくリダイレクトされているか
  • ログインが完了するとヘッダーモジュールにアカウント名が表示されてるので正しく表示されているか

テストコードのフォルダ構成

プロジェクトのフォルダ構成は次のように役割ごとに整理しました。

tests
├── features
├── operators
├── pages
└── support
  • featuresにはスペックコードをまとめます。
  • operatorsにはPageオブジェクトから画面要素を参照してログインボタンをクリックするなどのオペレーションをまとめます。
  • pagesには画面の要素を参照できるようなPageオブジェクトを画面ごとにまとめます。今回は認証画面とHome画面をPageクラスにしました。
  • supportにはスペックコードでテストを進めるときに画面キャプチャを撮るなどのユーティリティ機能をまとめます。

次からはTestCafeのAPIを利用して記述したコード例を紹介します。

Pageクラス

TestCafeのAPIを利用して認証画面のPageクラスを作ります。

import { Selector } from 'testcafe';

export default class AuthPage {
    constructor () {

        this.url = 'https://freshlive.tv/auth/fresh_id';

        this.idInput = Selector('#user_id');
        this.pwInput = Selector('#password');

        this.submitBtn = Selector('button[type=submit]');
    }
}
  • 認証画面のURLを変数に定義する。
  • テストに必要な画面要素はSelectorを利用して定義する。
  • idInputはログインID、pwInputはパスワードの入力フィールドです。
  • submitBtnはログインボタンです。

これで認証画面の要素をまとめたAuthPageクラスができあがりました。

Operatorクラス

TestCafeのAPIを利用してOperatorクラスを作ります。
今回は認証画面でログイン認証する必要があるのでログイン操作をまとめます。

import {t} from 'testcafe';
import AuthPage from '../../pages/auth/auth-page.js';

export default class AuthOperator {
    constructor () {
        this.page = new AuthPage();
    }

    async open() {
        await t
            .navigateTo(this.page.url)
    }

    async authorize(id, password) {
        await this.open();

        await t
            .typeText(this.page.idInput, id)
            .typeText(this.page.pwInput, password)
            .click(this.page.submitBtn)
    }
}
  • constructor ()でAuthPageクラスからPageオブジェクトを生成します。
  • authorize(id, password)では認証画面を開きIDの入力とパスワードの入力を行い最後にログインボタンをクリックしています。typeTextclickで入力とクリックの操作ができます。
  • tはTestCafeのTestConrollerオブジェクトです。async-awaitとimportをすることでテスト実行時のTestConrollerオブジェクトと同期できます。0.13.0のリリース(Using test controller outside of test code (#1166))でTestConrollerをテストコード外でも参照することができるようになりました。(いいね!)

Supportクラス

TestCafeのAPIを利用してのSupportクラスを作ります。
今回は画面キャプチャを撮るユーティリティクラスを作りました。

import {t} from 'testcafe';

export default class ScreenshotSupport {
    constructor () {
    }

    async take() {
        await t
            .takeScreenshot;
    }
}
  • TestControllerには画面キャプチャを撮るメソッドが用意されています。
  • 取った画像を配置するフォルダもテスト実行時のオプションで指定できます。
  • 保存される画像のサイズは表示したブラウザのサイズになり縦長の画面の場合には画面全体を撮ることはできないようです。

Specクラス

TestCafeのAPIを利用してのSpecクラスを作ります。
このクラスでテスト内容をまとめていきます。

import { expect } from 'chai';

import HomePage from '../../pages/home/home-page.js';
import AuthOperator from '../../operators/auth/auth-operator.js';
import ScreenshotSupport from '../../support/screenshot-support.js';

const homePage = new HomePage();
const authOperator = new AuthOperator();
const screenshot = new ScreenshotSupport();

const userId = ' xxxxxxxx';
const password = 'xxxxxxxx';
const accountId = 'My Account';

fixture `auth fixtures`;

test('authorized at page then is appeared your account name on element of header.', async t => {

    // ログインする
    await authOperator.authorize(userId, password);

    // スクリーンショット撮る
    await screenshot.take();

    // ログイン後にHomeにリダイレクトをするのでURLが正しく切り替わっているか
    const docURI = await t.eval(() => document.documentURI);
    expect(docURI).eql(`${homePage.url}?&login_succeeded=true`);

    // ヘッダーメニューにログインしたアカウント名が表示されているか
    await t
        .expect(homePage.accountMenuDropdown.exists).eql(true)
        .expect(homePage.accountName.exists).eql(true)
        .expect(homePage.accountName.innerText).eql(accountId);
});
  • fixtureはテストをカテゴライズする機能でテスト実行時にfixtures単位でテストを実行するオプションがあります。
  • testではテストのタイトルとテストコードを記述していきます。
  • Operatorクラスでまとめた認証画面でログインするauthorize(userId, password)を呼びだしてログインを実行しています。
  • ログイン後にURLが切り替わっているかdocURI変数にURLを入れてチェックしています。
  • 最後にexpectを利用してヘッダーモジュールにアカウント名が表示されているかをチェックしています。

まとめ

  • Page Object Design PatternベースにTestCafeでテストを書いてみました。新しいAPIということもあり画面をオブジェクト化しやすい機能が揃っている印象です。
  • テストコードから画面要素と画面操作を分離してコード化することができました。
  • 以前のエントリではChatOpsとの連携も試してみました。E2Eテストを快適に実施と運用していくことを考えるとTestCafeの採用を検討していきたい:coffee:

ソースを公開しています

github.com

関連エントリ

naruto-io.hatenablog.com