Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

11.2 GHUnitを用いた単体テスト

ginrou edited this page May 16, 2013 · 4 revisions

iOSにおけるロジックテストにはGHUnitを用いた単体テストについて紹介します。

iOSにおける単体テストの環境には

  • GHUnit
  • OCUnit

の二種類があります。それぞれを簡単に比較すると

OCUnit GHUnit
Xcodeによるサポート あり なし
実行UI Xcodeと統合 GUI上で実行可能
setup/tearDown なし あり
テストの範囲 ロジックのみ ロジックに加えて非同期やUIViewも可能
導入のしやすさ やや難
CIからの実行 可能 可能

のようになります。コンパクトなテストを行う場合はOCUnitを、高機能なテスト環境を用いたい場合はGHUnitという使い分けができるかと思います。

この章では、公式クライアントアプリの開発でも用いてきたGHUnitについて、導入方法と利用方法を説明します。

導入方法

導入には次のステップで行います。

  1. 新しいターゲットの追加
  2. CocoaPodsを用いてインストール
  3. Build Settingを修正
  4. main.mの修正

では順番に解説していきます。

すてにあるプロジェクトに対して追加する方法を解説します。

1. 新しいターゲットの追加

  • メニューバーより File → New → Target として新規ターゲットを追加します。
  • アプリケーションテンプレートはEmpty Templateを選択します
  • ターゲット名はここでは UnitTest としました。それ以外の名称にした場合は適宜読み替えてください

ターゲットの追加

ターゲットの追加が終わり次第、不要なファイルの削除とフレームワークの追加を行います。

  • QuartzCore.frameworkを追加します
    • プロジェクトの設定 → ターゲットをUnitTest → Link Binary With Libraries より 追加できます
    • CocoaPodsでインストールしたときにQuartzCore.frameworkが必要となるためです
  • UnitTest以下にあるAppDelegate.h, AppDelegate.m の削除

完了すると、以下のようになっていると思います。

プロジェクトの修正

(QuartzCore.frameworkはFramework以下に移動しても構いません)

2. CocoaPodsを用いてインストール

GHUnitはCocoaPodsを用いてインストールできます。Podfileは以下のように書きます

platform :ios, '6.1'

target :UnitTest, :exclusive => true do
       pod 'GHUnitIOS', '~> 0.5.5'
end

書けたら

pod install

でインストールします。完了したら .xcworkspace からプロジェクトを再起動します

3. Build Settingを修正

シミュレータ上で動かすために、Build Settingに以下の修正を加えます。

Other Linker Flags に -ObjC -all_loadを追加します。

なお、-ObjCは最初から入っていると思います。

BuildSettings修正

4. main.mの修正

ApplicationMainではなく、GHUnitのメインを立ち上げるために、UnitTest側のmain.mファイルを修正します。

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, @"GHUnitIOSAppDelegate");
    }
}

四つ目の引数を @"GHUnitIOSAppDelegate" に変えています。

ターゲットを UnitTest に変更して起動すると次のようにシミュレータが立ち上がれば成功です。

empty_gh_unit

テストの書き方と実行方法

導入ができたらGHUnitを使ってテストを書き、実行してみましょう

書き方

今回はロジックであるMixiJankenDeciderについてテストを書きます。

まず、テストを書きたいファイルをテストターゲットに追加します。

add_to_target

テストを書きたいファイルを選び、Xcode右側のUtilities、Target Membership の UnitTestにチェックを入れます。

次にテストファイルを作成します。

新規ファイル作成画面へ移動し、GHTestCaseのサブクラスとしてクラスを作成し、TargetはUnitTestのみにチェックを入れて作成します。 ヘッダファイルは不要となるので削除してください。 そして、.mファイルに以下のテンプレートを貼付けます。クラス名などは適宜読み替えてください。

//
//
// Template of Unit Test Case
//
//

#import <GHUnit.h>

@interface MixiJankenDeciderTest : GHTestCase

@end

@implementation MixiJankenDeciderTest

- (void)testHogeFuga
{
    
}


@end

GHUnitではtestHogeFugaと書いたメソッドについてテストが実行されます。今回は試しに、ジャンケンの勝敗を決めるメソッドについてテストを書いてみます。

- (void)testJankenWithPeoples
{
    MixiJankenPeople *alice = [[MixiJankenPeople alloc] init];
    MixiJankenPeople *bob = [[MixiJankenPeople alloc] init];
    MixiJankenPeople *winner;

    alice.hand = JankenHandTypePaper;
    bob.hand = JankenHandTypePaper;

    winner = [MixiJankenDecider jankenWithPeoples:@[alice, bob]];

    GHAssertNil(winner, @"あいこではnilが返ってくるべき");

    alice.hand = JankenHandTypeScissors;
    winner = [MixiJankenDecider jankenWithPeoples:@[alice, bob]];

    GHAssertTrue(winner == alice, @"アリスが勝つべき");

}

Assertなどについては、また後ほど説明しますが、 GHAssertNil では引数がnilであることを期待します。 GHAssertTrueでは引数がYESとなることを期待します。

実行

それでは実行してみましょう。実行は、ターゲットをUnitTestに変更してRunすることで実行できます。

run_gh_unit

テストが失敗した時は、該当するテストの行が赤く表示されます

アサーション、setup/tearDown

ここでは、GHUnitに関するいくつかのアサーションと、テスト開始前/後のメソッドについて紹介します。

アサーション
アサーション 解説
GHAssertEquals(a1, a2, description, ...) a1とa2が同じであることを期待します。判断にはポインタを用います。
GHAssertNotEquals(a1, a2, description, ...) a1とa2が同じでないことを期待します。判断にはポインタを用います。
GHAssertEqualObjects(a1, a2, description, ...) a1とa2が同じであることを期待します。オブジェクトの構造を調べて同じかどうかを判断します。
GHAssertNotEqualObjects(a1, a2, desc, ...) a1とa2が同じでないことを期待します。オブジェクトの構造を調べて同じかどうかを判断します。
GHAssertGreaterThan(a1, a2, description, ...)  a > b を期待します
GHAssertLessThan(a1, a2, description, ...)  a < b を期待します
GHAssertEqualStrings(a1, a2, description, ...) 文字列 a1とa2が同じであることを期待します
GHAssertNotEqualStrings(a1, a2, description, ...) 文字列 a1とa2が同じでないことを期待します
GHAssertEqualCStrings(a1, a2, description, ...) Cの文字列char*について同じかどうかを比較します
GHAssertNil(a1, description, ...) nilであることを期待します
GHAssertNotNil(a1, description, ...) nilでないことを期待します
GHAssertTrue(expr, description, ...) 引数がYESであることを期待します

GHAssertEqualsとGHAssertEqualObjectsについては以下のような違いがあります

NSArray *a = @[obj];
NSArray *b = @[obj];

GHAssertEquals(a, b, nil); // fail
GHAssertEqualObjects(a, b, nil); // OK

詳細についてはこちらをご覧ください

http://gabriel.github.io/gh-unit/docs/appledoc_include/guide_testing.html

setup / tearDown

あるテストクラスの開始前と後に、初期化や後片付けを行う時に呼び出されるメソッドがあります。

メソッド名 解説
- (void)setUp 各テスト実行前に呼ばれる
- (void)tearDown 各テスト実行後に呼ばれる
- (void)setUpClass テストクラス実行前に呼ばれる
- (void)tearDownClass テストクラス実行後に呼ばれる

たとえば、あるデータをクラス内で共有して使いたい、何かしら副作用を生むのでその初期化を行いたいなどの場合に用います

Appendix

コマンドラインからのビルド

Jenkins で定期的にテストを実行したい、と言った時にはXcodeからRunなどは難しいのでコマンドラインからテストを実行します。 次のステップで実行可能です

  • ビルドスクリプトの追加
  • main.mの修正
  • xcodebuildを用いてコマンドラインからテストを実行

ビルドスクリプトの追加

GHUnitのgithubよりビルドスクリプトを取得します。xcworkspaceやxcodeprojのあるディレクトリで

curl https://raw.github.com/gabriel/gh-unit/master/Scripts/RunTests.sh > RunTests.sh

としてスクリプトファイルを保存します。

次にプロジェクトの設定→ Build Phases より Add Build Phaseを選択して、スクリプトを追加します。 add script

スクリプトには

sh RunTests.sh

add script

と入力します。

xcodebuildを用いてコマンドラインからテストを実行

次のコマンドをプロジェクトルートから実行します

GHUNIT_CLI=1 xcodebuild ONLY_ACTIVE_ARCH=NO -workspace <xcworkspaceファイルへのパス> -scheme UnitTest -configuration Debug -sdk iphonesimulator build

はじめに

  1. iOSについて

  2. Xcode最初のステッフ

  3. 導入

  4. Objective C の基礎

  5. メモリ管理

  6. 1.3 UIViewController1 UIViewController のカスタマイズ(xib, autoresizing)

  7. 1.3 UIViewController1 UIViewController のカスタマイズ(storyboard)

  8. UIViewController2 - ModalViewController

  9. UIViewController2 - ModalViewController(storyboard)

  10. UIViewController3 - ライフサイクル

  11. HomeWork 1 Objective C の基本文法

  12. HomeWork 2 UIViewControllerとModalViewController

  13. HomeWork 3 UIViewController + Animation

  14. UIKit 1 - container, rotate-

  15. UINavigationController

  16. UITabController

  17. Custom Container View Controller

  18. Supporting Multiple Interface Orientations

  19. HomeWork 1 - タブバーからモーダルビューを表示する

  20. HomeWork 2 - NavigationController

  21. HomeWork 2.3 デバイスことに回転対応

  22. UIKit 2- UIView -

  23. UIView

  24. UIView のカスタマイズ

  25. UIView Animation

  26. HomeWork 1 - UIScrollView

  27. UIKit 3 - table view -

  28. UITableView について

  29. UITableViewとNavigationController

  30. custom UITableViewCell の作成

  31. UITableViewのその他のオプション、カスタマイズ

  32. HomeWork 1 - Dynamic height with a custom uitableviewcell

  33. UIKit 4 - image and text -

  34. UIImagePickerController

  35. Assets Library

  36. UITextFiled, UITextView

  37. KeyboardNotification

  38. Homework 1 - フォトの複数枚選択

  39. ネットワーク処理

  40. NSURLConnection

  41. JSONのシリアライズとデシリアライズ

  42. UIWebView

  43. ローカルキャッシュと通知

  44. NSUserDefaults, Settings Bundle

  45. NSFileManager

  46. Key Value Observing

  47. NSNotification、NSNotificationCenter を用いた通知

  48. UILocalNotification

  49. Blocks, GCD

  50. Blocks

  51. GCD

  52. 【演習】GCD,-Blocksを用いたHTTPリクエストマネージャの作成

  53. 設計とデザインパターン

  54. クラス設計 1

  55. クラス設計 2

  56. [クラス設計演習] (https://github.com/mixi-inc/iOSTraining/wiki/9.3-%E3%82%AF%E3%83%A9%E3%82%B9%E8%A8%AD%E8%A8%88%E6%BC%94%E7%BF%92)

  57. 開発ツール

  58. Instruments, デバッガ

  59. CocoaPods

  60. テスト

  61. iOS開発におけるテスト

  62. GHUnit

  63. Kiwi

  64. KIF

  65. In-App Purchase

  66. In-App Purchase

  67. 付録

  68. Tips of Xcode

  69. Auto Layout 入門

  70. Auto Layout ドリル

Edit sidebar

Clone this wiki locally