Karmaを使うとブラウザ上でのテストが行えますが、さらにPreprocessorのうちkarma-html2js-preprocessorを使用するとHTMLファイルを使ってテストができるようになるようです。
参考)
イマドキのJSテスト - karma + karma-html2js-preprocessorでブラウザ/DOMを絡めたUIテストを実行する編 〜 JSおくのほそ道 #031
CLIでJavaScriptのテストを実行する時にHTML fixtureを利用する方法。Karma... | niwaringo() {Tumblr}
KarmaでDOM操作のテストをする | shoarai.com
karma+mocha+power-assertでDOM操作を含むユニットテストをES6で書く | WebDesign Dackel
JavaScriptでHTMLを読み込んで、DOMを使ったテストができるようになる代物だとか。
というわけで、簡単に試してみます。
準備
Karmaおよびkarma-html2js-preprocessorを使うわけですが、個人的にBrowserifyとBabelは入れておきたいため、ここまでをセットにします。テスト自体にはMocha、Chai、そしてDOM操作にはjQueryを使用することにします。
以下、各種モジュールインストール。
## Babel $ npm install --save-dev babelify babel-preset-es2015 $ npm install --save babel-polyfill ## Browserify $ npm install --save-dev browserify watchify ## Mocha, Chai $ npm install --save-dev mocha chai ## Karma $ npm install --save-dev karma karma-browserify karma-chai karma-mocha $ npm install --save-dev karma-chrome-launcher ## Karma Html2Js Preprocessor $ npm install --save-dev karma-html2js-preprocessor ## jQuery $ npm install --save jquery
今回は、「karma-html2js-preprocessor」をインストールするところがポイントです。
Babelの設定ファイルも用意して
$ echo '{ "presets": ["es2015"] }' > .babelrc
Karmaの設定ファイルも作成します。
$ ./node_modules/karma/bin/karma init
自動生成後からいじったところは、このあたりですね。
// frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['browserify', 'mocha', 'chai'], browserify: { transform: ['babelify'] }, // list of files / patterns to load in the browser files: [ 'src/**/*.js', 'test/**/*-test.js', 'html/**/*.html' ], // list of files to exclude exclude: [ ], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors: { 'src/**/*.js': ['browserify'], 'test/**/*-test.js': ['browserify'], '**/*.html': ['html2js'] },
今回のテーマでいくと、「files」にHTMLファイルを含めるようにすることと、「preprocessors」でHTMLに対して「html2js」を指定しておくことがポイントです。
npm runで、Karmaが起動するように指定。
"scripts": { "test:karma": "karma start" },
あとは、ソースコード、テストコード、HTML配置用のディレクトリを作成して、準備完了。
$ mkdir src test html
テスト対象のコードとHTML
テスト対象は、特定の要素をクリックすると、別の要素内に子要素とテキストを追加するものにします。
src/click-add.js
import "babel-polyfill"; import $ from "jquery"; export function bindClick() { $("#button").bind("click", () => { $("#messages").append("<div class='added-message'>Hello Karma!!</div>"); }); };
HTMLファイルは、こんな感じの単純なものを用意。
html/index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Karma Test Code</title> </head> <body> <div id="messages"></div> <input id="button" type="button" value="クリック!!"> </body> </html>
このうえで、先ほどのコードを動かすようにします。
テストコード
で、それを行うためのテストコードがこちら。3回クリックしてみます。
test/click-add-test.js
import "chai"; import $ from "jquery"; const should = chai.should(); import { bindClick } from "../src/click-add.js"; describe("click-add test", () => { it("click triple from HTML file.", () => { document.body.innerHTML = __html__["html/index.html"]; bindClick(); let button = document.getElementById("button"); Array.from(Array(3), (v, k) => k + 1).forEach(i => button.click()); let messages = document.getElementsByClassName("added-message"); messages.should.to.have.lengthOf(3); let messageTexts = Array.from(messages).map(e => e.textContent); messageTexts .should .deep .equal(["Hello Karma!!", "Hello Karma!!", "Hello Karma!!"]); }); });
ポイントはこの部分で、
document.body.innerHTML = __html__["html/index.html"];
karma-html2js-preprocessorを利用すると__html__という表記が利用できるようになり、これでHTMLファイルが読み込めます。読み込んだ内容を、documentに反映すればDOMとして構築される、と。
documentがグローバルなので、beforeやafterなどでdocument.body.innerHTMLをクリアした方がよいかも?みたいな記述も見かけましたが、変わらなかったというかやるならテスト内でないと意味がなさそうです…。
まとめ
karma-html2js-preprocessorを使って、HTMLファイルを使った簡単なテストを書いてみました。
Karmaを使うとブラウザ上でテストはできますが、あらかじめDOMがないと実際には厳しいことも多いでしょうから、これは便利そうですね。