yasuoza diary

web and life

```Xcodeで非同期通信のテストを行う

最近はiPhoneアプリの開発を勉強しています。

で、iPhoneアプリを作る上でももちろんテストを書きたいと思い、いろいろ調べた結果、XCode4系標準のQUnit、非同期を簡単に扱えるGHUitあたりが有名だとわかりました(他にもたくさんあります)。

XCode標準ということはAppleの人たちもきっとQUitを使って開発しているはず!という勝手な思い込みからQUitを使うことにしました。 そのQUnitは標準で非同期をサポートしていないので、自前で非同期のテストを書かないといけません。 その実装をメモしておきます。

まずはコードから。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- (void)testAsyncronousRequest
{
  dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

  NSURLRequest *request = [NSURLRequest requestWithURL:url];
  asyncConnection = [[AsyncConnection alloc] initWithRequest:request]; 
  //Automatically asyncConnection.delegate is set asyncConnection in AsyncConnection

  asyncConnection.completion = ^(JSONConnection *connection,
                                  NSData *downloadData,
                                  NSHTTPURLResponse* response,
                                  NSError* error) {
        // Test code here..
    
        dispatch_semaphore_signal(semaphore);
    };
    
    
    while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                                 beforeDate:[NSDate dateWithTimeIntervalSinceNow:5]];
    } 

    dispatch_release(semaphore);
}

まず、

1
  dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

でセマフォをプールサイズ0で登録します。

その後、

1
2
3
4
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) {
 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                             beforeDate:[NSDate dateWithTimeIntervalSinceNow:5]];
} 

でセマフォのカウンタが0の時は

1
2
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
                           beforeDate:[NSDate dateWithTimeIntervalSinceNow:5]];

を実行してメインループをブロックします。 ブロックしている間にasyncConnection.completionのブロックで指定した関数が実行され、

1
dispatch_semaphore_signal(semaphore);

によってセマフォのカウンタが1インクリメントされます。 セマフォのカウンタが1以上だった、もしくは待機中にカウンタが1以上になった場合は

1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)

が0になり、while文を抜け出し、セマフォを開放した後、testAsyncronousRequestが終了します。

こんなかんじでGCDを使って非同期テストを行うことができました。

GCDについて詳しくは

エキスパートObjective-Cプログラミング -iOS/OS Xのメモリ管理とマルチスレッド-
坂本 一樹
インプレスジャパン
売り上げランキング: 119084


参考サイト