JavaScriptでE2Eテストを記述できる、TestCafeを試してみる

E2Eテストについてちょこちょこ調べていて、ブラウザ操作の自動化でSelenium以外に何かないかなと思っていたら、TestCafeが割と良さそうだったのでメモ。

環境

TestCafe v1.10.0。

インストールにはNode.js v14.15.2、およびYarn v1.22.5を使用。

TestCafeとは

devexpress.github.io

JavaScriptまたはTypeScriptで実装できるE2Eテストツール。

インストールすればすぐに使え、Seleniumのように各ブラウザごとのドライバーなど用意しなくても動かせるのがメリット。

インストール

npmなら npm install -g testcafe 、Yarnなら yarn global add testcafe でグローバルインストールする。

testcafe -v でバージョン表示、 testcafe -b で、利用可能なブラウザ一覧を確認できる。

Redirecting…

FirefoxGoogle ChromeChromiumMicrosoft Edge、おまけでIE11の入ったWindows 10では、インストール時点で以下のように表示される。

$ testcafe -b
Using locally installed version of TestCafe.
firefox
chrome
ie
edge

テスト実行

Redirecting…

コマンドラインから実行する場合、 testcafe [-c 並行実行数] [実行するブラウザ] テスト実装ファイル

ブラウザは firefox,chrome,ie のように、カンマ区切りで複数実行可能。 firefox および chrome は、それぞれ firefox:headless および chrome:headless と記述することで、ヘッドレスモードでも実行できる。

また、 -c 並行実行数 を指定することで、並行実行も可能。

この他にも、後述のFixture名でフィルタリングしたりできる模様。

JavaScriptからの実行

APIを使用して、JavaScriptからも実行できる。

Redirecting…

const createTestCafe = require('testcafe');
const testcafe = await createTestCafe();
const runner = testcafe.createRunner();

await runner
    .src(['tests/fixture1.js', 'tests/fixture2.js'])
    .browsers(['firefox', 'chrome:headless', 'ie'])
    .concurrency(3)
    .run();

テスト実装

fixtureとtest

Redirecting…

テストファイル内に1つ以上のfixtureを、また1つのfixtureにつき1つ以上のtestを記述する。

fixture `MyFixture`;

test('Test1', async t => {
    // テストコードを記述
});

fixture, test、どちらでも、 page で実行する際のURLを指定できる。fixtureにpageを指定すると、そのfixtureに含まれるすべてのtestがそのURLを開いた状態で実行される。testでpageを指定することで、fixtureのURLを上書きできる。

fixture `MyFixture`
    .page `https://google.com`;

test('Test1', async t => {
    // Googleで実行される
});

この他、meta でメタ情報を付与したり、fixtureには beforeEach および afterEach 、testには before および after で前処理/後処理を記述したりできる。

TestController

testの第2引数で渡している関数の引数、 t の実体はTestControllerというクラス。

文字の入力、クリック、エンター押下などはTestControllerを通して行う。

また、 ctx プロパティにKey-Valueで値を設定することで、fixtureとtest間や、testのbeforeとテストコード間などで値の共有が可能。

Selector

HTMLの要素の取得などは、Selectorを使用する。

以下の記述より、SelectorはTestControllerのメソッドに渡されたり、アサート対象になったタイミングで、遅延評価される模様。

The selector value is evaluated each time you :

  • use the selector for an action;
  • assert selector’s properties;
  • call the selector directly in code to get it’s state;

Assert

TestControllerのメソッドとして、Assert用のメソッド expect が用意されている。

expect にactualを渡し、メソッドチェーンで比較用メソッドを実行して期待値を渡す。

expect に渡された値が、Selectorで取得したDOMノードやPromiseの場合、動的ページに対応するために、テストが失敗してもすぐにエラーにはならず、タイムアウトまで複数回実行されるとのこと。Smart Assertion Queryと呼ばれている。

Page Object Pattern

サンプルを見るとほとんど手続き的にテストを書いているが、Page Object Patternでも記述できる模様。

Redirecting…

振り返り

ちょっと試したが、なんといっても複数ブラウザでの実行が、Seleniumに比べると非常に楽。

タイムアウトまで再試行というのは、素のSeleniumを使っているならいざ知らず、Selenideのようなラッパーを使っていれば対応できるので、あまりメリットには感じなかった。

一方、やや不便に感じたのは、非同期処理には async/await を使用しているため、都度記述するのが面倒。これは慣れるしかないか。

セットアップや複数ブラウザ対応が楽というのは、運用開始時にはプラスになるが、運用が始まればあまり意味がなくなるので、既にSeleniumなどのE2Eテスト資産があれば乗り換えるメリットはないが、新規でE2Eテスト環境を構築しようと思っているのであれば十分候補になるかと思った。