Help us understand the problem. What is going on with this article?

Webテストを自動で行ってくれるTestCafeを導入してみようと思う

More than 1 year has passed since last update.

はじめに

弊社はECサイトの運営を行っています。
ユーザーに影響を与えないようにするためにデバッグも行っています。
が、時間がかかってしまいます。
なのでTestCafeというNode.jsのツールを導入してデバッグ工数削減を図りたいと思います。
本記事はTsetCafe導入にあたっての備忘録みたいなかんじです。
かなり初心者向けの内容になってると思います。

変なことを書いていたらご指摘お願いします。

導入環境

MacOS Mojave バージョン10.14.4

TestCafeとは

Node.jsのツールの1つ。
E2Eでブラウザテストを自動化するためのフレームワークです。
JavaScriptでテストコードを書いていくので、フロントエンドエンジニアがに導入しやすいツールなんじゃないかなと思います。
TestCafe公式ページ

E2E(End of End)とは
User Interface Testとも呼ばれている。
システム全体を通してテストを行う。
参考:E2Eテストの導入から学んだこと

特徴

公式ページなどを参考に、下記の事が記載されていました。

  • 自動待機メカニズムがある。
    → テストが開始されると、ページ読み込み、XHRの完了、DOM要素の表示が待機されるように作られている。

  • 最新のJS、またはTypeScriptでコードを記載する。
    → ES2017を含む以前のJS機能をサポートしている。JSでしか記載できない。公式ではTypeScriptを推奨してるっぽい。。

  • コード内のJSエラーを発見する事ができる
    → TsetCafeで記載したコードではなく、テストしているWebページ内のJSエラーを報告してくれる。この機能を無効にすることもできる。

  • 平行テストができる。
    → 同じブラウザの複数のインスタンスを開いてテストを実行することにより、テスト時間を短縮できる。

  • TestCafe,Node.jsがインストールされていない環境でもテストの実行ができる。
    → TestCafeが出力するURLを対象の環境ブラウザで開くだけでテストが実行される。

  • ライブモード
    → テスト中にTestCafeプロセスとブラウザがアクティブな状態になる。変更を加えるとテストが再開される。

ざっくりとこんな感じ、もっと特徴あると思うけど。

TestCafe以外のテストツール

SeleniumとかNightwatchとかProtractorとかあるみたいです。
E2Eテストを導入するのが初めてなので他のテストツールのことは全く知りません。

TestCafeをインストールしてみる

早速インストールしてみます。

下記のコマンド実行。
今回はglobalでインストールしました。

$ npm install -g testcafe

$ testcafe -v
1.2.0

プロジェクト単位とかでインストールしたい場合は下記のコマンドを実行。

npm install --save-dev testcafe

これでTestCafeを使用する環境は整いました。

コードの書き方からテスト実行までの流れ

ざっくりとした説明をしていきます。
見出し通り流れを掴んでいただければと思います。

今回はTypeScriptを使わずにテストコードを書いていこうと思います。

TestCafeのコードを記載していく.jsファイルを作成し、必要なtestcafeモジュールをインポートします。
とりあえずSelectorモジュールをインポート。
Selectorモジュールに関しては後ほど説明します。

import { Selector } from 'testcafe';

次にfixture関数を使ってテストフィクスチャの宣言をしていきます。
ちなにみテストフィクスチャとは、テストを実行、成功させるために必要な状態や前提条件の集合のことだそうです。

fixture `任意のテスト名`
    .page`対象ページのURL`;


fixture `ログインテスト`
    .page`https://hogehoge.com`;

次にtest関数を使ってtestコードを記載していきます。

test('テスト項目名', async t => {
  //テストコード
});

TestCafeではfixture関数の後にtest関数で処理を並べていく書き方が基本です。
ざっくりと下記のような構成になるかと思います。

// モジュールをインポート
import { Selector } from 'testcafe';

fixture `任意のテスト名`
    .page`対象ページのURL`;

test('テスト項目名1', async t => {
  //テストコード
});

test('テスト項目名2', async t => {
  //テストコード
});

テストコードが記載できたらテストを実行してみます。

テスト実行したいブラウザとファイルパスを指定して、コマンドシェルから実行します。

testcafe chrome test.js

コマンドを実行すると選択されたブラウザが開き、テストの実行が開始されます。

またテスト結果は、テスト実行中にコマンドシェル内で確認できます。

試しに下記のコードで実行してみました。

コードの詳しい解説は後ほどしていきます。

test.js
import { Selector } from 'testcafe';

fixture`Qittaログインテスト`
    .page`https://qiita.com/`;

test('ログイン画面遷移', async t => {

    /** テストに必要な要素を取得 **/
    const 
         // ログイン画面遷移ボタン
         loginBtn = await Selector('.st-Header_loginLink')
         // ユーザーID or メールアドレスの記入窓
        ,inputUserId = await Selector('#identity')
         // パスワードの記入窓
        ,inputPassword = await Selector('#password')
         // ログインボタン
        ,loginFormBtn = await Selector('.loginSessionsForm_submit')
    ;

    /** テストアクション実行 **/
    await t
        // ログイン画面遷移ボタン
        .click(loginBtn)
        // ユーザーID or メールアドレスを記入
        .typeText(inputUserId, 'ユーザーID or メールアドレス')
        // パスワードを記入
        .typeText(inputPassword, 'ログインパスワード')
        // ログインボタンクリック
        .click(loginFormBtn)
    ;

    /** テストが成功しているか判断させる **/
    // ログイン完了後の'.st-Header_postButton'のテキスト取得
    const postBtn = await Selector('.st-Header_postButton').innerText;
    // 取得したテキストが「投稿する」だった場合テスト成功とする
    await t.expect(postBtn).eql('投稿する');
});

実行するとこんな画面が立ち上がります。
スクリーンショット 2019-06-18 13.27.05.png

ブラウザが立ち上がり、テストが開始されます。
スクリーンショット 2019-06-18 13.27.17.png

テスト後のシェルはこんな感じです。
失敗した場合は赤文字でエラー表示されます。
スクリーンショット 2019-06-18 13.27.40.png

テストコード解説

Selectorモジュール

Selectorはテストに必要な要素を取得するためのものです。
JQueryみたいな感じで簡単に要素を取得できるようになります。
TestCafeが提供するメソッドチェーンをつなげて目的の要素まで絞り込めるので便利です。
色々なメソッドが存在するのでこちらをご参照ください。

ClientFunctionモジュール

今回のテストコードには記載されていないですがよく使いそうなのでメモしておきます。
テスト実行環境のDOMからではなく、JavaScriptからアクセスできるデータを使いたい場合に使用します。
現在のページURLを確認したい場合とかに使用します。
今回のテストページで使用すると下記のようなコードになると思います。

import { Selector } from 'testcafe';
import { ClientFunction } from 'testcafe';

const getWindowLocation = ClientFunction(() => window.location);
//
//途中略
//
test('ログイン画面遷移', async t => {
    //
    //途中略
    //

    /** テストが成功しているか判断する部分 **/
    const location = await getWindowLocation();
    await t.expect(location.href).eql('https://qiita.com/');
});

Qiitaの場合ログイン時のURLは下記の通りになります。

ログイン失敗時 : https://qiita.com/login/
ログイン成功時 : https://qiita.com/

ホームのURLに戻ってきたらログイン成功といえます。

テストコントローラー

テストコードにあった「await t」のtの部分がテストコントローラーと呼ばれるものです。
値の入力やクリックなどのアクションが期待通りの動作をしているか検証するためのアサーションメソッドを提供してくれています。
色んなアクションが存在するのでこちらをご参照ください。

またアクションだけでなくalertなどのダイアナログの操作も行ってくれます。

await t
    // ダイアログの操作
    // trueを返すと「OK」を選択したことになる
    .setNativeDialogHandler(() => true)

   // 引数の設定もできるみたいですが今回は省きます。

expectメソッド

こいつは大事かなって思うので他のメソッドとは個別でピックアップしときます。

このexpectメソッドを使って、テストされたwebページが想定した状態に一致するかどうかを確認するためのアサーションです。
アサーションってなんぞやって方はこちらをご参照ください。

今回のテストコードで使ったアサーションメソッドはeqlになります。
値が等しいことを判定してくれます。

他にも指定した値が含まれてるか判定してくれるcontainsメソッドなどもあります。

色んなアサーションメソッドが存在するのでこちらをご参照ください。

最後に

TestCafeについて最低限の情報をまとめてみました。
似たようなページたくさん作るし、毎回デバッグも大変ってときはTestCafe使ってあげるといいかもしれないですね。

参考ページ

ex_4ever
新卒二年目でフロントエンドエンジニアやってます。 わからないことだらけなので色々調べて、てきとーに記事書いてみようかなって思ってます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away