Hatena::Groupiphone-dev

Ni chicha, ni limona - 平均から抜けられない僕

2009-05-28

[iPhone][Develop][Test] iUnitTestを使ってみた。 17:40  [iPhone][Develop][Test] iUnitTestを使ってみた。 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][Develop][Test] iUnitTestを使ってみた。 - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][Develop][Test] iUnitTestを使ってみた。 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

伊藤ソフトデザインさんがiPhone向けユニットテストフレームワーク「iUnitTest」をGitHubで公開(SourceForgeの記事)していて、その評判が良いので使ってみることにしました。

ただ、まだ使いこなし方がよく分かっていないので、今回はインストールと使い始めのところだけ(リアルタイムに)記録しています。

インストール

次の手順で行いました。

  1. まずGitHubからソース一式を持ってきて、展開。
  2. ReadMe.jp.txtをCarbonEmacsで読む(テキストエディットだと文字コードのせいか開けなかった)。
  3. ReadMeのとおり、展開したフォルダで「sudo ./setup」を実行。同じフォルダにはsetup.rbもあるけれどコチラじゃない*1
    • Xcodeの新規プロジェクト/新規ファイルでiUnitTest用のプロジェクトやクラスが作成できるようになる

簡単ですね。setup処理もすぐ終わりました。

サンプルを見て、知る

ReadMeに「サンプルプロジェクト'PrefecturesTest'を見てください」とあるので見てみることに。


ふむふむ、プロジェクトを開いたときにある「TargetClasses」グループにテストしたいクラスを置いて、そして「Tests」にはインストール作業で使えるようになったiUnitTest用クラスを置くといいんですね。


あれ?この TargetClasses にあるファイル、 PrefecturesTest の隣にある Prefectures 内のファイルを「プロジェクトを基準」で参照するようになっている。

・・・そうか、テストプロジェクトで分かった不具合の修正を本プロジェクトに即座に反映させるためか。この

 「テストプロジェクトにはコピーではなく参照でターゲットファイルを含めること

は今後の注意事項として覚えておこうっと。

それ以外をざっと見ても、このファイルはプロジェクトで使うファイルそのままで、特に何もiUnitTest用には手が加えられていないことを確認。


次に「Tests」グループのファイル。

なるほど、この〜Testというファイルの中で、テストしたいクラスのインスタンスを作成し、そのテストケースを「test」で始まるメソッドに書いてあげればいいんだな。ここを読んで気づいた点は、


  • 新規ファイルで作成できるテストクラスには「無垢(IUTTest)」「NavigationBarベース」「NavigationとTabベース」「Tabベース」があるけれど、サンプルでテスト対象になっているUITableViewControllerクラスにはNavigationBarベース(UINavigationBarBasedTest)」を使っている
  • どのテストクラスも、以下の特徴がある
    • setup/tearDown/deallocメソッドはテンプレートのまま触っていない
    • (UIViewController *)rootViewControllerで、テスト対象のクラスがインスタンス化されるようクラス名を変更している
    • testで始まっていればテストメソッド名は何でもよいみたい
    • 各テストメソッドそれぞれでテスト対象クラスをインスタンス化しなくても良い(毎回インスタンス化されるという情報をいただきました)
    • Testsというセクションにテストが書いてある(場所は関係ないと思うけれど・・・)。別に「Helpers」として何か書かなくても良いっぽい
    • サンプルプロジェクトでは「ASSERT_EQUAL」「ASSERT_EQUAL_INT」が使われている

など。


どんなテスト用マクロがあるの?

ASSERT_〜はIUTAssertion.hに書いてあったので、マクロだけ抜粋してみました。SAMEとEQUALの違いなども元ソースを調べて書いてあるので、単なるコピペではないです。

マクロ意味
ASSERT(value)値が真であることを期待する
ASSERT_FAIL(m)常に失敗する
ASSERT_SAME(_expected, _value)オブジェクトが同じであることを期待する(==演算子を使用)
ASSERT_NOT_SAME(_expected, _value)オブジェクトが同じではないことを期待する(==演算子を使用)
ASSERT_EQUAL(_expected, _value)オブジェクトが同じであることを期待する(isEqualメソッドを使用)
ASSERT_NOT_EQUAL(_expected, _value)オブジェクトが同じではないことを期待する(isEqualメソッドを使用)
ASSERT_EQUAL_INT(_expected, _value)int型の値が同じであることを期待する
ASSERT_NOT_EQUAL_INT(_expected, _value)int型の値が同じではないことを期待する
ASSERT_EQUAL_FLOAT(_expected, _value)float型の値が同じであることを期待する
ASSERT_NOT_EQUAL_FLOAT(_expected, _value)float型の値が同じではないことを期待する
ASSERT_EQUAL_FLOAT_DELTA(_expected, _value, _delta)float型の値が誤差Δの範囲で同じであることを期待する
ASSERT_EQUAL_DOUBLE(_expected, _value)double型の値が同じであることを期待する
ASSERT_NOT_EQUAL_DOUBLE(_expected, _value)double型の値が同じではないことを期待する
ASSERT_EQUAL_DOUBLE_DELTA(_expected, _value, _delta)double型の値が誤差Δの範囲で同じであることを期待する
ASSERT_NIL(_value)オブジェクトnilであることを期待する
ASSERT_NOT_NIL(_value)オブジェクトnilではないことを期待する
ASSERT_EQUAL_POINT(_expected, _value)CGPoint型の構造体が同じ値を持っていることを期待する
ASSERT_EQUAL_SIZE(_expected, _value)CGSize型の構造体が同じ値を持っていることを期待する
ASSERT_EQUAL_RECT(_expected, _value)CGRect型の構造体が同じ値を持っていることを期待する
ASSERT_RAISE(expr)指定した処理で例外が発生することを期待する
ASSERT_NOTHING_RAISED(expr)指定した処理で例外が発生しないことを期待する

色々あるものですね。


自分でテストプロジェクトを作ってみる

・・・。


・・・すみません、ここでブログを書く力が尽きてしまいました。

詳しいことは作者のブログはてなブログ」にあるPDFファイルを見ていただくといいと思います。


ここで書こうと思っていたことが分かりやすく書いてあったので、という言い訳をさせてくださいな。

まとめ

その他で気づいた点


あまり参考にならなかったかもしれませんが、そのへんはご容赦ください。

*1:setupの中身を見ると分かるけど、実はsetup.rbを呼んでいるだけなんですけどね。

gutskungutskun2009/05/28 23:35マクロをまとめていただいてありがとうございます。

>毎回インスタンス化される?使い回される?
ここは毎回インスタンス化されます。

ReadMe.jp.txtには書き忘れてますが、opencodeも併用してみて下さい。
http://d.hatena.ne.jp/gutskun/20090427/1240825326

paellapaella2009/05/29 21:08コメントありがとうございます。まだ使いこなしている状態ではないので恐縮です。

毎回インスタンス化されるんですね。となればテストは前後のテスト状態を気にせず使えると理解しました。確かに、使い回されるとテストがテストである意味がなくなってしまいますものね。

opencodeも参考にさせてもらいます。
ありがとうございました。