AngularのテストではおなじみのKarma(=宿命、業)ですが、すごい名前ですよね...。karma
のRiotプラグインは日本語だと「宿命の反乱」でしょうか。フロントエンドのテストの話です、念のため。
というわけで、Riotの公式リポジトリにこのKarmaプラグインが仲間入りしたので、簡単に要所をまとめたいと思います。
アプリケーション構成(例)
極小構成ということで、この記事の登場人物はこの5ファイルだけです。動いているのをまず触りたいという方は、こちらにPlunkerで編集可能なものがあります。ソースとテスト一式はこちら。
- app.tag
- index.html
- karma.conf.js
- package.json
- test/
- specs.js
アプリケーション本体
まずapp.tag
ですが、簡単なルーティングのデモになっています。ここではテストの説明が主眼なので、細かい話は略。
<app>
<nav><a each={ data } href="#{ id }">{ title }</a></nav>
<article>
<h1>{ page.title || 'Not found' }</h1>
<p>{ page.body || 'Specified id is not found.' }</p>
</article>
<script>
var self = this
self.data = [
{ id: "", title: "Home", body: "Click the link above." },
{ id: "1", title: "First", body: "This is the first page." },
{ id: "2", title: "Second", body: "This is the second page." }
]
self.page = self.data[0]
riot.route(function(id) {
self.page = self.data.filter(function(r) { return r.id == id })[0] || {}
self.update()
})
</script>
</app>
アプリケーションとしては、これ(↑)をindex.html
から呼び出すだけ。
<!doctype html>
<html>
<head>
<title>Riot Router Example: Page Switching</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<app></app>
<!-- riot tags -->
<script type="riot/tag" src="app.tag"></script>
<!-- scripts we need -->
<script src="https://cdn.jsdelivr.net/g/riot@2.2(riot.min.js+compiler.min.js)"></script>
<!-- mount this app -->
<script> riot.mount('app') </script>
</body>
</html>
必要なライブラリのインストール
少なくとも、次の3つは必ずインストール。
$ npm install --save-dav riot karma karma-riot
この辺も入れておきましょう。※好みのライブラリに適宜差し替えてください。
$ npm install --save-dav expect.js karma-mocha karma-mocha-reporter karma-phantomjs-launcher
package.json
の中身はこんな感じになっているはずです。あと、テストの起動用にscripts
のところに記述をお忘れなく。
{
"devDependencies": {
"expect.js": "^0.3.1",
"karma": "^0.13.9",
"karma-mocha": "^0.2.0",
"karma-mocha-reporter": "^1.1.1",
"karma-phantomjs-launcher": "^0.2.1",
"karma-riot": "^1.0.0",
"riot": "^2.2.4"
},
"scripts": {
"test": "karma start"
}
}
karmaの設定
さて、このアプリケーション(と呼んでいいのか...)をテストしてみたいと思います。karmaの出番です。jasmine
でもOKですが、ここではなんとなくmocha
で。karma.conf.js
はこんな感じに。
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha', 'riot'], // フレームワークにriotを指定
plugins: [
'karma-mocha',
'karma-mocha-reporter',
'karma-phantomjs-launcher',
'karma-riot' // プラグイン指定
],
files: [
'node_modules/expect.js/index.js', // chaiとか好きなものでOK
'**/*.tag', // タグファイルの指定
'test/**/*.js' // テストファイルの指定
],
preprocessors: {
'**/*.tag': ['riot'] // プリプロセッサにriotを指定
},
browsers: ['PhantomJS'],
reporters: ['mocha'],
singleRun: true
})
}
karmaはfiles
で指定したファイルと、フレームワークで必要とするファイルをテスト時に自動的に読み込みます。その際、CoffeeScriptを自動変換したりするのに使えるのが、プリプロセッサです。karma-riot
プラグインが読み込まれていれば、Riotのタグもよしなにkarmaが変換してくれます。
プロダクション用をBrowserifyで1ファイルに固めてると、単一タグのテスト用に別途コンパイルが必要だったりしますが、このプリプロセッサがあればそれも不要ですね。
その他の部分は、ごく一般的なkarmaの設定です。詳しくはkarmaの公式サイトをどぞ。
テスト
ここまででお膳立てはできたので、テスト本体です。ここではdocument.body
の直下にDOMを追加して、そこにテストしたいタグをマウントする形をとりました。例として、(1)タグのマウントの確認、(2)ルーターの挙動をチェックするテストを入れています。
describe('Application specs', function() {
before(function() {
// create mounting points
var html = document.createElement('app')
document.body.appendChild(html)
})
it('タグのマウント', function() {
riot.mount('app')
expect(document.querySelector('article > h1').textContent)
.to.be('Home')
})
it('別URLに移動して表示内容を切り替え', function() {
riot.route('1') // http://localhost/1
expect(document.querySelector('article > h1').textContent)
.to.be('First')
riot.route('2') // http://localhost/2
expect(document.querySelector('article > h1').textContent)
.to.be('Second')
})
})
例では1ファイルにまとめていますが、長くなってきたら、テストのカテゴリーごとにファイルに分けていきます。
テストの実行
さあ、あとは...
$ npm test
するだけです。全部のテストがクリアなら"xx tests completed"と表示されます。
まとめ
Riotは見た目のHTMLっぽさが際立っていて、テストといってもピンとこないかもですが...、2ファイル(karma.conf.js
とテストファイル)を足すだけから始められます。やんなきゃ!
あとは、APIを叩くテストが入るならSinon.JSを叩くもよし、単体テストで切り出せるならmochaだけでテストしてもよし、普段のやり方でどぞ。