ランサーズ(Lancers)エンジニアブログ > JavaScript > TestCafeでのE2EテストをBrowserStackでやろう

TestCafeでのE2EテストをBrowserStackでやろう

yokoi|2017年07月26日
JavaScript

ランサーズCTOの横井です。

最近、個人でE2Eの画面テストを書く際にSeleniumからTestCafeに乗り換えつつあります。導入が(個人的には)Seleniumより楽っていうのと、要素の出現とかをよしなに待ってくれるので、テスト書くときにあんまりその辺を意識しないで書けるっていうのが良い感じです(まだでかいプロジェクトでがっつり使い込んでいないので、落とし穴にはまっていないだけかもしれません)。

とりあえず

$ npm install -g testcafe

やるだけでサクッと始められますが、今回はより色々な環境でのテストを行いたいので、BrowserStackと連携させてみます。

準備

まずは今回のテスト用の画面を作ってしまいます。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>samplepage</title>
    <link rel="stylesheet" href="">
</head>
<body>
    <h1>hello world</h1>
    <script>
    !function() {
        if ( typeof history.pushState !== "function" ) {
            throw Error("under IE9!!");
        }
    }();
    </script>
    
</body>
</html>

だけのシンプルなindex.htmlを作ります。普通のプロジェクトであればローカルにサーバがいたりするかと思いますが、今回はサンプルなので、適当にテストコードの最初らへんで立てちゃいます。その上でテストを書いたのがこちら。

const nodeStatic = require('node-static');
const fileServer = new nodeStatic.Server('./public');

// サンプル用にサーバを立てる
const __server = require('http').createServer( (req,res)=>{
    req.addListener('end', ()=>{ fileServer.serve(req, res); }).resume();
} ).listen(3000);

fixture('Sample Test')
    .page('http://localhost:3000/')
    .after( async (ctx) => {
        __server.close();
    });

test('Assert page title', async (t) => {
    const title = await t.eval( () => window.document.querySelector('title').text );
    await t.expect( 'samplepage' ).eql( title );
});

この時点でもコマンドラインから

$ testcafe chrome tests/sample.test.js

で、Chrome上でのテストが動かせます。

BrowserStackを使用する

まずは、BrowserStackに登録したのち、ログイン後画面から「Account->Settings->Automate」のところにUsernameとAccessKeyが書いてあるのでコピっておきましょう。

次に、TestCafeから使えるようにtestcafe-browser-provider-browserstackを入れておきます。あとは環境変数に「BROWSERSTACK_USERNAME」と「BROWSERSTACK_ACCESS_KEY」をセットして

$ testcafe "browserstack:Chrome@53.0:Windows 10" tests/sample.test.js

上記を動かすと、BrowserStack上で指定したテストが動き、結果をコマンドライン上で確認できます。あとは、BrowserStackで指定できる組み合わせで色々指定すればOKというわけです。

もうちょいプロジェクトっぽくする

このままだと、環境変数毎回設定したり、どのブラウザでテストしているかの見通しが悪いのでプロジェクト化します。
まずはpackage.json

{
  "name": "sample_test",
  "description": "E2E test using testcafe",
  "scripts": {
    "test": "node runner.js"
  },
  "dependencies": {
    "dotenv": "^4.0.0",
    "node-static": "^0.7.9",
    "testcafe": "^0.15.0",
    "testcafe-browser-provider-browserstack": "^1.1.1"
  }
}

環境変数は.envファイルに逃がします。あとはブラウザの指定をコードで管理したいのでTestRunnerのキックをコードで行います。

require('dotenv').config();
const createTestCafe = require('testcafe');
let testcafe         = null;

createTestCafe('localhost', 1337, 1338)
    .then(tc => {
        testcafe     = tc;
        const runner = testcafe.createRunner();

        return runner
            .src('tests/sample.test.js')
            .browsers([ 'browserstack:Edge@15.0:Windows 10', 'browserstack:IE@10:Windows 8' ])
            .run();
    })
    .then(failedCount => {
        console.log('Tests failed: ' + failedCount);
        testcafe.close();
    })
    .catch(err => {
        console.log("err", err);
        testcafe.close();
    });

これをrunner.jsとして、npm test時にキックするようにすればOKです。あとは、browsersの引数の配列を増やしていくだけで、一個のテストを一気に色々な環境で動かすことができます。

実際に意味のありそうなことをやってみよう

冒頭のindex.htmlのscriptタグの中のコードはIE9以下であればErrorとなるはずです。なので、ブラウザーの指定で

.browsers([ 'browserstack:Edge@15.0:Windows 10', 'browserstack:IE@9:Windows 7' ])

IE9を指定してテストを実行してみます。

すると

Running tests in:
 - Edge 15.15063.0 / Windows 10 0.0.0
 - IE 9.0.0 / Windows 7 0.0.0

 Sample Test
 ✖ Assert page title

   1) Error on page "http://localhost:3000/":

      under IE9!!

      Browser: IE 9.0.0 / Windows 7 0.0.0



 1/1 failed (2s)

しっかり検知できました! IE9を外してあげるとテストはパスします。

まとめ

いい感じですね。