こんにちは!ishiBです。
今回はJavascriptのテストフレームワーク「Jasmine」を紹介します。
Jasmineは、RSpec(http://rspec.info/)に近い記法を使ってJavaScriptのテスティングを行うフレームワークです。
Jasmineは(https://github.com/pivotal/jasmine/downloads)からダウンロードできます。
では早速実際にJasmineを使って、テストをしてみたいと思います。
ファイルの構成は以下のようになっています。
ダウンロードしたファイルにはサンプルファイルも入っているので、今回はそれをもとに説明していきたいと思います。
それではソースの中身を見ていきましょう。
テスト対象クラスは以下のようになっています。
[javascript] function Player() { } Player.prototype.play = function(song) { this.currentlyPlayingSong = song; this.isPlaying = true; }; Player.prototype.pause = function() { this.isPlaying = false; }; Player.prototype.resume = function() { if (this.isPlaying) { throw new Error("song is already playing"); } this.isPlaying = true; }; Player.prototype.makeFavorite = function() { this.currentlyPlayingSong.persistFavoriteStatus(true); }; [/javascript]
これに対するテストクラスは以下のように記述します。
[javascript] // `describe`メソッドにクラス等のテスト対象を記述します。 describe("Player", function() { var player; var song; beforeEach(function() { player = new Player(); song = new Song(); }); // `it`メソッドにテスト実施内容を記述します。 it("should be able to play a Song", function() { // テスト内容を記述します。 player.play(song); // 期待値との比較を行います。 expect(player.currentlyPlayingSong).toEqual(song); // 期待値との比較を複数回行うことができます(一つでも期待値に一致しない場合はNG)。 expect(player).toBePlaying(song); }); // `describe`メソッドの中に`describe`メソッドを追加することもできます。 describe("when song has been paused", function() { beforeEach(function() { player.play(song); player.pause(); }); // 上記と同じように`it`メソッドにテスト内容を記述します。 it("should indicate that the song is currently paused", function() { expect(player.isPlaying).toBeFalsy(); // demonstrates use of 'not' with a custom matcher expect(player).not.toBePlaying(song); }); it("should be possible to resume", function() { player.resume(); expect(player.isPlaying).toBeTruthy(); expect(player.currentlyPlayingSong).toEqual(song); }); }); // demonstrates use of spies to intercept and test method calls it("tells the current song if the user has made it a favorite", function() { spyOn(song, 'persistFavoriteStatus'); player.play(song); player.makeFavorite(); expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true); }); //demonstrates use of expected exceptions describe("#resume", function() { it("should throw an exception if song is already playing", function() { player.play(song); // 異常系のテストは以下のように記述します。 expect(function() { player.resume(); }).toThrow("song is already playing"); }); }); }); [/javascript]
※1 日本語のコメントは後から追加しました。
このテストを実行してみます。
SpecRunner.htmlは以下のように記述します。
[html]</pre> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html><head> <title>Jasmine Spec Runner</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-1.2.0/jasmine_favicon.png"> <link rel="stylesheet" type="text/css" href="lib/jasmine-1.2.0/jasmine.css"> <script type="text/javascript" src="lib/jasmine-1.2.0/jasmine.js"></script> <script type="text/javascript" src="lib/jasmine-1.2.0/jasmine-html.js"></script> <!-- テストファイルを読み込みます --> <script type="text/javascript" src="spec/SpecHelper.js"></script> <script type="text/javascript" src="spec/PlayerSpec.js"></script> <!-- テスト対象ファイルを読み込みます --> <script type="text/javascript" src="src/Player.js"></script> <script type="text/javascript" src="src/Song.js"></script> <script type="text/javascript"> (function() { var jasmineEnv = jasmine.getEnv(); jasmineEnv.updateInterval = 1000; var htmlReporter = new jasmine.HtmlReporter(); jasmineEnv.addReporter(htmlReporter); jasmineEnv.specFilter = function(spec) { return htmlReporter.specFilter(spec); }; var currentWindowOnload = window.onload; window.onload = function() { if (currentWindowOnload) { currentWindowOnload(); } execJasmine(); }; function execJasmine() { jasmineEnv.execute(); } })(); </script> </head> <body></body> </html> [/html]
実行結果
すべてのテストが成功しました。
エラーがある場合は以下のように表示されます。
・実行結果一覧画面(エラーのテストは赤字で表示されます)
・実行詳細画面
このように簡単にJavascriptのテストが実施できます。
今回の説明では詳しく触れませんが、Jasmineは非同期な動作もテストすることが出来ます。
またCI(継続的インテグレーション)に統合することも可能です。
興味のある方は参考にしてみてください。
ではでは~