2009-11-26 木
■[iUnitTest]iUnitTestでやった事
須藤さんにコメントをもらったのに行けないので、実際の議題にマッチするか分かりませんがこちらにまとめておきます。
テーマが、「テスティングフレームワークに必要なもの - 書きやすさとデバッグのしやすさ」とあるので、書きやすさとデバックのしやすさについて書きます。
書きやすさ
iUnitTestはIUTTestクラスから派生したクラスのtestから始まるメソッドをメタ情報から探し出して来て自動的にテストします。
慣習的*1にはテストクラス名はTestで終わるようにしますが、IUTTestのサブクラスであれば名称は問いません。
// クラス名はTestで終わっているが、慣習的な物でBarとかでも良い
@interface FooTest : IUTTest {
}
@end
@implementation FooTest
- (void)testHoge
{
ASSERT(YES);
}
@end
必要なテストを追加するだけでiUnitTestがテストしてくれます。
一時的に外したい場合はtestXXXという名称を_testXXXの様に_を付けてtestから始まらない様にする事で外す事ができます。反面、戻すのを忘れてテストし忘れという事があるのは注意が必要です。
iUnitTestはiPhoneのアプリケーションとしてテストを実行します*2。この点は他と大きく異なる点で、面食らうかも知れません。
Xcodeのテンプレートを用意しているので、それを用いてもらえれば雛型が出来上がります。
そして、アプリ用プロジェクトとテスト用プロジェクトの2本立てで進めます。
テスト用プロジェクトにはアプリのソースコードを参照という形で追加します。そうする事でテスト用プロジェクト内でソースを修正してもアプリ用プロジェクトのソースに反映される*3様にします。
反面、後からソースを追加した場合は、同期がとれないので他のプロジェクトでも追加する必要があります。私は、1つのフォルダにまとめて、変更があった場合は一旦フォルダごと外して、もう一度追加するという事をしたりします。このやり方はXcodeでRailsが参考になると思います。
この方法の利点はアプリ用のプロジェクトに不要なコードが一切入らないので見通しが良い事です。
書きやすさというテーマから外れてしまってる気も・・・
デバッグのしやすさ
iUnitTestはiPhoneアプリケーション内に結果が表示されます。失敗すると、ソースファイルと行数が表示されるので、当初はその情報を元に該当箇所を探していました。この作業はけっこうめんどうなので、どうにかしたいと思っていて、opencodeというサービスを立ち上げて通信でXcodeに情報を伝える様にしました。こうする事で、iPhoneシミュレータ上の失敗した表示のセルをクリックするとXcode上で該当コードが表示される様になりました。こちらで書いてます。
その後、どんどんテストを追加してASSERTの回数が1000とか2000になってくると、終了するまで時間がかかる様になるので、時間短縮する為の方法を2つ追加しました。
一つ目は、一度全部テストし、失敗が出ると次回は失敗したテストだけをテストします。失敗したテストが全て通るとまた全部のテストを行う様にし、不具合のあるうちは、不具合箇所だけをテストし時間短縮出来る様にしました。
二つ目は一つ目の特性を生かして、わざと失敗するテストを追加して新しく追加したクラスだけテストする方法です。
他のユニットテストでは特定のクラスやメソッドだけテストするコマンドやインターフェイスが用意されていたりしますがiUnitTestにはありません。iPhoneソフトなのでUIを追加したとろで操作が面倒になるのが目に見えているし、Xcode上でソースをメンバーから外す方法もあるので、ソースコードにマークを入れる事で対応する様にしました。
// Uncomment it, if you want to test this class except other passed test classes.
//#define TESTS_ALWAYS
#ifdef TESTS_ALWAYS
- (void)testThisClassAlways { ASSERT_FAIL(@"fail always"); }
+ (BOOL)forceTestsAnyway { return YES; }
#endif
テンプレートから生成したテストファイルには上のコードがあり、#define TESTS_ALWAYSのコメントを外すと、testThisClassAlwaysをテストする様になります。最初は全てのテストを実行しますが、ダミーのtestThisClassAlwaysが失敗するので、次からはそのクラスだけテストする様になります。
本当はスタックトレースとか表示出来れば良いなと思う所もありますが、Xcodeでブレークポイントを設定すれば、Xcode上で見れるのでXcodeを使った方が便利だと思います。
自分が工夫した所はこんな所です。
他
今はファンクショナルテストをどうやるかとか考えたりしていて、現状では複数のメソッドをまたぐ必要があるので*4、独自の構文を作ってテストクラスを生成するとかじゃないと楽にならないかなという気がしたりしてます。
まだ何かある気がしますが、この辺で。思い出したりしたら追記します。
とりあえず明日のFSIJ月例会が始まるまで書いてみようという事で、的外れだったりするかも知れませんが書いてみました。
- 366 http://pipes.yahoo.com/pipes/pipe.info?_id=835956827daaff45b7e7c1630e8ce35f
- 11 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=I58&q=uitableview+セルが表示されない&btnG=検索&lr=lang_ja&aq=f&oq=
- 8 http://career-aid.com/blogs/blog/2009/03/19/ruby-on-railsはnamed_scopeでconditionsに命名できて便利すぎ。/
- 6 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GGLL_jaJP341JP342&q=着信の表形式のデータ+ストリーム+(TDS)+リ??%
- 4 http://ezsch.ezweb.ne.jp/search/ezGoogleMain.php?query=ガッター21&start-index=4&adpage=3&mode=02
- 4 http://www.func09.com/wordpress/archives/402
- 4 http://www.google.co.jp/search?hl=ja&q=github+削除&btnG=検索&lr=lang_ja&aq=f&oq=
- 4 http://www.google.co.jp/search?source=ig&hl=ja&rlz=1G1GGLQ_JAJP292&=&q=iPhone 電源オフ&btnG=Google+検索&meta=lr=&aq=f&oq=
- 4 http://www.google.com/search?hl=ja&safe=off&client=safari&rls=en&q=ipod+nano+5G+iCal&btnG=検索&lr=&aq=f&oq=
- 3 http://blog.livedoor.jp/gutskun/









