61
58

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 5 years have passed since last update.

Nightmare v2(Electron) でブラウザ上でES2015のコードを個別にrequireしてユニットテストを書く

Last updated at Posted at 2016-02-12

自分の開発環境では, nodeで単体テストと分離してモデル層を抽出出来たが、e2eほどではないがブラウザ上でテストしたいコードというのは結構ある。モーダル制御とか、ブラウザ上のイベントに依存する奴とか。

それらを Nightmare でテストするアプローチを紹介する。

概要

Nightmare はヘッドレステストランナーとそのDSLを提供する。v2でランナーがphontomjsから Electronになった。

コードはbabel/commonjsで書かれており、本番環境でJSは1つにまとまっているが、Electron の nodeIntegration を有効化して走らせることで、ビルド前のコードを個別にrequireできる。グローバルを避けてrequireで依存が明示されていれば、理論上そのコードは完結して動くはず。

実装例

適当なエントリー用のHTMLを用意する。必要だったらここで各種コンテナを用意してもいい。

browser-spec/test.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <h1>Blowser Test Env</h1>
  </body>
</html>

ヘルパを用意する。

browser-spec/spec-helper.js
'use strict';

// nightmare
const Nightmare = require('nightmare');
const path = require('path');
const TEST_HTML_PATH = "file://" + path.join(__dirname, "test.html");

// create
global.browser = null;
let startBrowser = function * (){
  global.browser = Nightmare({
    show: false,
    nodeIntegration: true
  });

  yield browser
    .goto(TEST_HTML_PATH)
    .wait('body')
    .evaluate(() => {
      require("babel-register"); // to evaluate spec-helper
      require("../src/main"); // 初期化コードを読み込む
    });
}

let finishBrowser = function * (){
  yield global.browser.end();
}

exports.useBrowser = function() {
  // should init in mocha env
  require("mocha-generators").install();

  before(function * () {
    yield startBrowser();
  });

  after(function * () {
    yield finishBrowser();
  });
}
browser-spec/foo-spec.js
'use strict';

var helper = require('./browser-spec-helper');

describe('browser specs', () => {
  helper.useBrowser();

  it('render foo view', function*() {
    var qiitaProps = yield browser
      .evaluate(function () {
        // Backboneっぽい擬似コード
        let FooView = require("../src/foo-view");
        new FooView().renderTo("body"); 
      });
    yield browser.wait('.foo-inner');
  });
});

mocha で実行。

$ mocha -r browser-spec/spec-helper browser-spec/*.js -t 24000

解説

NightmareをnodeIntegration: trueで初期化することでrequireが使用可能になる。

browser.evalueteの中のコードはelectronの中で実行される。コードの式としての評価は実行ホスト側で行われるが、実際に実行されるのはブラウザの中である点に注意。そしてその中はnodeとブラウザプロセスをattachしたelectronのプロセス内で、requireが使える、という仕組み。

mochaと一緒に使う注意点

Nightmareはインターフェースが yield で統一されているのだが、babelのgenerator-transformerは generatorをAST変換して継続渡しスタイルに変換する。これが邪魔なので切っておかないといけない。

上記のコードのテスト部分node v4.2で評価して、babel は使っていない。register('babel-register')を走らせた後のrequire先は babel でも構わない。

まとめ

e2e, nodeのユニットテストという軸だけではやりづらかった、ブラウザでのコンポーネントのユニットテストがこれによって非常にやりやすくなった。

Electronはアプリ配布用としてだけではなく、開発環境をエンハンスするのにもとても便利。

61
58
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
61
58

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?