Titanium Mobile + Jasmine + Jenkins でiPhoneアプリの自動テスト組んでみたよ
Jenkins Advent Calendar jp 2011の3日目です。
Titanium Mobile + Jasmine + Jenkins でiPhoneアプリの自動テスト組んでみた、っちゅう話をします。
本当はプラグインを作りたかったんですが、そこまで行かなかったので(言い訳だよ!)、せめて自動テストをどう組んだかの話をしますね。
Titaniumの自動テストを組みたい
最近Titanium Mobileを使ってiPhoneアプリなど作ってます。
Titanium Mobileについてはもう説明もいらないと思いますが、Javascriptを使ってスマートフォンアプリ(特にiPhoneとandroid)を開発することができるプラットフォームですね。
で、Jenkins野郎な私としては、Titaniumでも自動テストを組みたいんですよね。
Javascriptでテストってどう書くんだろう。
ふむふむ、色々あるね。
TitaniumにもDrillbitっていう組み込みのテストフレームワークがあるらしい。
http://developer.appcelerator.com/doc/mobile/drillbit
http://wiki.appcelerator.org/display/guides/Writing+Unit+Tests+with+Drillbit
でも、なんか動かないって言ってる人多いし、もうすこしメジャーっぽいテストフレームワークのほうがいいな。。
node.jsのテストも書かないといけないので、同じフレームワークを使えたほうがうれしいってのもあるし。
Jasmine可愛い
Jasmine
個人的にはこっちが本命。明確に RSpec-inspired.
Pivotal Labs がメンテナンスをしている。実はこれすごく重要。なぜなら JsUnit も pivotal/js-spec-server - GitHub も関係している Pivotal Labs があえて新しい JavaScript Testing Framework を作っているのだ。これが良くなくて一体何が良いのだ。
また、relevance/blue-ridge - GitHub というかなり気合いの入った Framework も今は「もうやらないから Jasmine 使え」って言ってるくらいなんだから、本命中の本命と言っていいと思う。
Pivotal Labs の名前を意識するようになったのはE和さんの中で流行っているという話を聞いてからだけど、jsUnit 自体は以前から知っていたので、これは正直期待しちゃうってもんだ。
http://aligach.net/diary/20101205.html
Jasmineよさそうじゃね。BDDってなんか濁点多くてカッコいいし、Pivotal Trackerも好きだし、よさそげ。
Jasmine
花が可愛い。これにしよう。これにするよ!
jasmine-titaniumがあるよ!
既にjasmine-titaniumっていう素敵なものを書いてくれてる方がいました。ありがとうございます。
これでTitaniumをJasmineでテストすることができます。
でもこのままだと、テスト結果をコンソールに吐くか、
iPhoneエミュレータで見るか、
しかありません。
コンソールは見づらいし、iPhoneエミュレータは面白いけどCI向きじゃない。
さらに、エミュレータの場合、内部的にはWebViewを使ってHTMLを表示しているだけなせいか、requireが動かんのですよね。。そもそもテストが実行できないし!*1
もう一歩踏み込みたいです。やっぱりJenkins野郎としてはsurefireを吐かせてJenkinsにテスト結果を集計させたいですよね。
JasmineはReporterを別途定義してやることでテスト結果を差し替えられるので、surefireを吐くReporterを書いてやればいいよね。
っと思ってたら、jasmine.titanium.JUnitXmlReporter.jsってのが既にあったよ。すごいね世界って。
https://github.com/sgrimault/jasmine-titanium-reporters
jasmine-titaniumとjasmine.titanium.JUnitXmlReporterをつなげてみたよ
というわけで、つなげてみた。
https://github.com/ikeike443/jasmine-titanium
下記を修正した感じです。
https://github.com/ikeike443/jasmine-titanium/commit/dbde36696337a88ab074f039052916a6d5e7f86d
- Reporterを足してオプションを増やしました。
- libをTi.includeするのをやめました。specからrequireしてしまえばいいので。っていうかincludeすると名前空間が混ざってしまって困るです。
- ライセンス関係の表記の仕方ってこれでいいんだっけ。。(プラグイン化するときにちゃんとします。。)
使い方は本家jasmine-titaniumとほぼ同じなんですが、ちょっとだけ違います。
まず、Titaniumのプロジェクトを作って、下記のようにして、vendor以下にjasmine-titaniumをcloneし、できたディレクトリの中に入って、.gitmodulesに定義されたsubmodule(jasmine自体とのリンクが貼ってある)のアップデートをします。
cd Resources mkdir spec vendor cd vendor git clone https://github.com/ikeike443/jasmine-titanium.git cd jasmine-titanium git submodule init git submodule update
次に、Titaniumプロジェクトのルートに.gitmodulesファイルを作り、下記のように保存します。要は、今度はアプリのプロジェクトとjasmine-titaniumのリンクを作るわけです。
[submodule "jasmine-titanium"] path=Resources/vendor/jasmine-titanium url=git://github.com/ikeike443/jasmine-titanium.git
テスト書くよ
さて、準備ができたのでテスト書きましょう。
テスト対象として、下記のようなコードがあったとします。
//db.js (function() { exports.dbutil = function() { var self = this; self.dbName = 'hoge.db'; self.getName = function(){ return self.dbName; }; self.open = function () { self.db = Titanium.Database.open(self.dbName); }; self.close = function () { self.db.close(); }; })();
こいつのテストをspec以下に書きます。
//db_spec.js describe("db", function() { var db; var dbutil; beforeEach(function() { db = new (require('models/db').dbutil); }); it("name should be hoge.db", function() { expect(db.getName()).toEqual('hoge.db'); }); });
とりあえずDB名があってるかどうかのテストを書いて見ました。
jasmineのテストは書き方がわかりやすくていいですね。
さて、ここまでできたらJenkinsの設定をしましょうぜ!
Jenkinsの設定しましょうぜ!!
フリースタイルのジョブを作って、バージョン管理からGitを選択(Gitプラグインは入ってますよね!)。
Gitじゃなくてももちろんいいんですが、今回はGit前提で話を進めます。
次に、ビルド「シェルの実行」を選んで下記を設定。
git submodule init git submodule update cd Resources/vendor/jasmine-titanium git submodule init git submodule update cd ../../ python vendor/jasmine-titanium/script/specs.py -r jenkins
さっき作った.gitmodulesの設定をもとに、submoduleを更新してやってから、specs.pyを実行します。
なんかcdを繰り返しててダサいですが気にしない。
iPhoneエミュレータが立ち上がったよ! うまく行ったっぽい!
まとめとお断り
というわけで、jasmine-titaniumとJenkinsを使ってiPhoneアプリのCI環境をちょろっと作って見ました。
プロビジョニングファイルのインストールとか、AppStoreへの申請とか、CIとして整備したいことはまだまだありますが、まずはテストを自動化することが出来ました。
尚、今回紹介したこの方法はまだ全然荒削りです。例えばエミュレータのプロセスをちゃんと殺してないので、自動テストの実行後、エミュレータは上がりっぱなしです。。(えー。。)
設定も色々面倒臭いので、もう少し時間をとって、プラグイン化するところまで行きたいなーと思います。
ともあれ、今回は、Titanium+Jasmine+JenkinsでiPhoneアプリを自動化するよ! の巻でした。
次のJenkins勉強会までにはプラグイン化してしましたいですね。本家本元の@masuidriveさんはRubyでTitanium-Jenkinsプラグインを書いてるという噂も聞くので、そっちの方がすごいものになってるとは思いますが。。
さて、明日は@linoさんです。Jenkins実践入門の作者ならではの話を期待してます!!
*1:ブラウザ上でTitaniumのrequireと同じ挙動をするrequireの実装があったら教えて欲しいです。。Require.jsはうまく行かなかった。。