こんにちは、ほそ道です。
前回のJasmineモジュールテストに引き続きテストを掘り下げていきます。
今回はUIテストをやってみたいと思います。前回分も読んでおいていただくと理解度シナジーが起こって良い感じになると思います。
今回扱う範囲/扱わない範囲
- まずはブラウザ上でJavaScriptを実行しJasmineと絡めて実行結果をテストします。
- 次にブラウザ上のDOMの状態(スタイル含む)をテストします。
- 今回のテスト内容にとりあえず遷移というかページ(リ)ロードは含めません。これが絡むと非常に厄介さが増すので遷移は別途取り上げたいと思います。
Karmaを実行する
まずはKarmaの実行から。
Karmaは実ブラウザでJavaScriptコードを実行できる実行環境で、テストフレームワークと組み合わせてテストを行う事ができます。
エミュレータやヘッドレスブラウザではなく実ブラウザというところがミソです。ただPhantomJSの起動にも対応しています。
ブラウザはPCにインストールされている必要があるのでMacで気軽にIE立ち上げたりはできません。
インストール
それではプロジェクトディレクトリを作っていつものインストールから始めましょう。
npm init
npm i -D karma karma-jasmine karma-chrome-launcher karma-firefox-launcher
これでkarma --version
コマンドが通ればインストールは問題ありません。
うまく実行できない場合は別途下記のコマンドを叩いてCLIをグローバルインストールしましょう。
npm i -Dg karma-cli
conf.js
今回も被テストファイルはsrc
ディレクトリに、テストファイルはspec
ディレクトリに設置します。
上記ディレクトリが作成できたらKarmaの設定ファイルを出力しましょう。
下記のコマンドをたたきます。
karma init karma.conf.js
下記のように質問が出てくるので答えましょう。終わるとkarma.conf.js
が出力されます。
Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine
Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no
Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
> Firefox
>
What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> src/*.js
> spec/*.js
>
Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>
Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes
設定ファイルは手で作っても構いません。下記のようになります。
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: ['src/*.js', 'spec/*.js'],
exclude: [],
preprocessors: {},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome', 'Firefox'],
singleRun: false
});
};
テストの実行
それでは簡単なJSファイルを設置してテストしてみましょう。
ここまでの構成は下記のようになります。
.
├── karma.conf.js
├── node_modules
├── package.json
├── spec
│ └── sampleSpec.js
└── src
└── sample.js
- まずは被テストファイルから
function add(x, y) {
return x + y;
}
- 次にテストファイルです
describe("function-add", function() {
it("2つの引数の和を返すべし", function() {
expect(add(10, 20)).toBe(30);
});
});
- package.jsonにテストコマンドを記述しましょう。
{
…
"scripts": {
"test": "karma start karma.conf.js"
},
…
}
- 実行しましょう
npm test
ポコポコっとChromeとFirefoxのブラウザが起動してきて、TOTAL: 2 SUCCESS
の表示が出れば実行・テスト成功です。
テストコードはブラウザ上で実行されたことになります。
- テストファイルが
require
してないことにも注目です。コンフィグファイルのfiles: ['src/*.js', 'spec/*.js']
の設定は自動的に相互参照を可能とします。 - コンフィグファイルの
autoWatch: true
とsingleRun: false
の設定が効いていてファイルの内容を書き換えてセーブすると自動的にもう一回テストが流れるようになっています。
これじゃあただのjasmine-nodeモジュールテストとと変わらない?
と、最初は思っちゃいました。
ただ、この時点でもほそ道的には下記2点メリットはあると思うんですが、どうですかねー?
- ブラウザごとにで使用不能なメソッドの呼び出しを行っていないかテストできる
- isomorphicなJSモジュールになっているかテストできる
HTMLを絡めたテスト
環境準備
さて、HTMLを絡めましょう。わしゃあブラウザでテスト走らせるならHTMLテストがしたいんじゃー!!
先ほどのプロジェクトにkarma-html2js-preprocessorを追加インストールしましょう。
npm i -D karma-html2js-preprocessor
つづいてkarma.conf.js
に設定を追加します。
htmlファイルも実行対象に入れる。
htmlファイルにはkarma-html2js-preprocessorをカマす。
という設定です。
module.exports = function (config) {
config.set({
…
files: [
'*.html',
'src/*.js',
'spec/*.js'
],
…
preprocessors: {
'*.html': 'html2js'
},
…
});
};
WEB画面の構成
次にindex.html
, src/appendLi.js
, spec/appendLiSpec.js
の3ファイルを追加します。
さっき使ったsrc/sample.js
とspec/sampleSpec.js
は消しちゃって構いません。
プロジェクト構成は下記のようになります。
.
├──index.html
├── karma.conf.js
├── node_modules
├── package.json
├── spec
│ └── appendLiSpec.js
└── src
└── appendLi.js
それでは各ファイルの中身を見ていきましょう。
まずはsrc/appendLi.js
ファイルからです。
#list
なul要素にli要素を追加します。
function appendLi() {
var ul = document.getElementById('list'),
li = document.createElement('li');
li.innerHTML = 'karma!';
li.style.fontSize = '20px';
ul.appendChild(li);
}
次にindex.html
です。body部だけ。
src/appendLi.js
を参照していて、クリックされるとappendLi関数をコールします。
<body>
<input id="btn" type="button" value="click!" onclick="appendLi()">
<ul id="list"></ul>
<script src="src/appendLi.js"></script>
</body>
この時点でも下記のようにブラウザで動作が確認できます。
テストコード
さて、テストコードとなるspec/appendLi.js
です。
ボタンをクリックして期待通りの動作をするか。
ポイントはbeforeEach
内でHTMLの初期化をしているところです。
karma-html2js-preprocessorを使うと
window.__html__['index.html'];
のような記述でhtmlファイルをJavaScriptで扱える文字列として呼び出せます。
describe("function-appendLi", function() {
beforeEach(function() {
document.body.innerHTML = window.__html__['index.html'];
});
it("追加されたli要素のテキストは'karma!'となるべし", function() {
var btn, appendedLi;
btn = document.getElementById('btn');
btn.click();
appendedLi = document.getElementById('list').firstElementChild;
expect(appendedLi.innerText).toEqual('karma!');
});
it("追加されたli要素のテキスサイズは20pxとなるべし", function() {
var btn, appendedLi;
btn = document.getElementById('btn');
btn.click();
appendedLi = document.getElementById('list').firstElementChild;
expect(Number(appendedLi.style.fontSize.replace('px', ''))).toEqual(20);
});
it("li要素は複数追加できるべし", function() {
var btn, liCnt;
btn = document.getElementById('btn');
btn.click();
btn.click();
btn.click();
liCnt = document.getElementById('list').childElementCount;
expect(liCnt).toEqual(3);
});
});
さあ、npm test
でテストを実行してみましょう。
おや、なんかFirefoxの方だけエラーが起きてますね。。
あっ、検査文字列を取得するメソッドがinnerText
になっている!
ということでこれをinnerHTML
に変えてみましょう。これでこそマルチブラウザテスト!
今度は成功です!
DOMやスタイルに対するHTMLテストが出来ました!
karmaレポーター
さて、最後にもう少し便利にすることにトライしてみます。
テストしたHTMLファイルを表示する/テスト結果をもう少しリッチにする
ではテスト結果に彩りを添えるために下記のパッケージをインストールします。
npm i -D karma-spec-reporter karma-jasmine-html-reporter
さらにkarma.conf.js
に設定を変更します。結果表示用のreportersをデフォルトのprogressから変更します。
module.exports = function (config) {
config.set({
…
reporters: ['spec', 'html'],
…
});
};
さて、やる事はこれだけです。npm test
を実行してみましょう。
このHTMLはキャプチャではなくて実際にボタンをクリックする事ができます。
注意点:karma-jasmine-html-reporterをカマすとファイル監視とブラウザ実行の関連付けが切れます。何度もモジュールを書き換えながらテスト結果をチェックしたい場合はオフっておいた方が良さそうです
まとめ
今回インストールしたパッケージ群まとめ
パッケージ名 | 概要 |
---|---|
karma | 実ブラウザでJavaScriptコードを実行できる実行環境 |
karma-cli | -gでインストールすればどこからでもkarmaコマンドを実行できる |
karma-jasmine | KarmaをJasmineに適合させる事ができる |
karma-chrome-launcher | Chromeブラウザをを起動できる |
karma-firefox-launcher | Firefoxブラウザをを起動できる |
karma-html2js-preprocessor | HTMLファイルをJavaScriptで扱える文字列にコンバートできる |
karma-spec-reporter | コンソール上のテスト結果表示フォーマットを変更する |
karma-jasmine-html-reporter | launcherが起動したブラウザにWEB画面を表示する |
launcher, preprocessor, reporterはここで探す
Karmaを使って他にもいろんな事が出来るので探してみると新しい可能性が見つかるかもしれません。
今回は以上です。