ユニットテスト初学者がKiwiFramework非同期テストで失敗した

4,677 views

Published on

ヤフー vs クラスメソッド Buttle6 発表資料

Published in: Technology
  • Be the first to comment

ユニットテスト初学者がKiwiFramework非同期テストで失敗した

  1. 1. ユニットテスト初学者が Kiwi framework 非同期テストで失敗した ヤフー vs クラスメソッド Buttle 6   Yuichi Adachi ! 2014 Feb 25 Copyright © Classmethod, Inc. 1
  2. 2. Self Introduction ! ! ・iOSアプリ開発&エンジニア歴もう少しで二年 ! ・去年12月にクラスメソッドに入社しました ! ・テスト歴は二ヶ月くらいです Copyright © Classmethod, Inc. 2
  3. 3. 今日話すこと ! ・Unit Test の利点 ! ・Kiwiの特徴 ! ・非同期テストでの失敗 Copyright © Classmethod, Inc. 3
  4. 4. Unit Testの利点 Copyright © Classmethod, Inc. 4
  5. 5. Unit Testの利点 ・ヘッダのコメント等では把握しきれない挙動  も把握できる。 Copyright © Classmethod, Inc. 5
  6. 6. Unit Testの利点 ・ヘッダのコメント等では把握しきれない挙動  も把握できる。 ! ・画面表示をせず、 +Uのみで挙動が期待する  内容かチェックできる。 Copyright © Classmethod, Inc. 6
  7. 7. Unit Testの利点 ・ヘッダのコメント等では把握しきれない挙動  も把握できる。 ! ・画面表示をせず、 +Uのみで挙動が期待する  内容かチェックできる。 ! ・副作用を含まないコードに貪欲になれる。 Copyright © Classmethod, Inc. 7
  8. 8. Kiwiの特徴 Copyright © Classmethod, Inc. 8
  9. 9. Kiwiの特徴 ! ・XCTest, OCUnitのようにテストメソッド名  を英語で逐一考えなくていい ! ! Copyright © Classmethod, Inc. 9
  10. 10. Kiwiの特徴 ! ・XCTest, OCUnitのようにテストメソッド名  を英語で逐一考えなくていい ! ・テストケースを対象ごと、文脈ごとに区切れる ! Copyright © Classmethod, Inc. 10
  11. 11. ! サーバーと切り離して 非同期ユニットテスト Copyright © Classmethod, Inc. 11
  12. 12. ! テストコードが 実行されない Copyright © Classmethod, Inc. 12
  13. 13. ! ソースURL: http://github.com/UsrNameu1/KiwiTestStudy Copyright © Classmethod, Inc. 13
  14. 14. テスト概略 Copyright © Classmethod, Inc. 14
  15. 15. テスト概略 Copyright © Classmethod, Inc. この部分を 15 テスト
  16. 16. テスト概略 Copyright © Classmethod, Inc. この部分を 16 テスト stub:withBlock: で置き換え
  17. 17. ブロックハンドラメソッド の挙動を決定 + (void)stub:(SEL)aSelector withBlock:(id (^)(NSArray *))block Copyright © Classmethod, Inc. 17
  18. 18. ブロックハンドラメソッド の挙動を決定 + (void)stub:(SEL)aSelector withBlock:(id (^)(NSArray *))block 返したいメソッドのセレクタを挿入 Copyright © Classmethod, Inc. 18
  19. 19. ブロックハンドラメソッド の挙動を決定 + (void)stub:(SEL)aSelector withBlock:(id (^)(NSArray *))block メソッド呼び出しの 引数、返り値を決め打ち ブロック引数はNSArray Copyright © Classmethod, Inc. 19 で取得できる
  20. 20. YADWebServiceSpec.m [NSURLConnection stub:@selector(sendAsynchronousRequest:queue:completionHandler:) withBlock:^id(NSArray *params) { void (^handler)(NSURLResponse *, NSData *, NSError *) = params[2]; handler(nil, data, nil); return nil; }]; }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; }); Copyright © Classmethod, Inc. 20
  21. 21. YADWebServiceSpec.m [NSURLConnection stub:@selector(sendAsynchronousRequest:queue:completionHandler:) withBlock:^id(NSArray *params) { void (^handler)(NSURLResponse *, NSData *, NSError *) = params[2]; handler(nil, data, nil); return nil; }]; Comments for describe, context, it }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; テスト コード }); Copyright © Classmethod, Inc. 21
  22. 22. YADWebServiceSpec.m [NSURLConnection stub:@selector(sendAsynchronousRequest:queue:completionHandler:) withBlock:^id(NSArray *params) { void (^handler)(NSURLResponse *, NSData *, NSError *) = params[2]; handler(nil, data, nil); return nil; }]; stub:withBlock: Comments for で置き換え describe, context, it }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; テスト コード }); Copyright © Classmethod, Inc. 22
  23. 23. Copyright © Classmethod, Inc. 23
  24. 24. BreakPointで ハンドラ内部が走っているか確認 Copyright © Classmethod, Inc. 24
  25. 25. YADWebServiceSpec.m [NSURLConnection stub:@selector(sendAsynchronousRequest:queue:completionHandler:) withBlock:^id(NSArray *params) { void (^handler)(NSURLResponse *, NSData *, NSError *) = params[2]; ! handler(nil, data, nil); return nil; ! }]; }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ テストに対するコメント [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; 使い分けてますか? }); Copyright © Classmethod, Inc. 25
  26. 26. YADWebServiceSpec.m [NSURLConnection stub:@selector(sendAsynchronousRequest:queue:completionHandler:) withBlock:^id(NSArray *params) { void (^handler)(NSURLResponse *, NSData *, NSError *) = params[2]; ! handler(nil, data, nil); return nil; ! }]; }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ テストに対するコメント [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; 使い分けてますか? }); Copyright © Classmethod, Inc. 26
  27. 27. 実行しない! Copyright © Classmethod, Inc. 27
  28. 28. ! Kiwi非同期ブロックハンドラ テストの注意点 Copyright © Classmethod, Inc. 28
  29. 29. ! Kiwi非同期ブロックハンドラ テストの注意点 ・ブロック内で結果を取得、ブロックの後で確認 ! Copyright © Classmethod, Inc. 29
  30. 30. ! Kiwi非同期ブロックハンドラ テストの注意点 ・ブロック内で結果を取得、ブロックの後で確認 ! ・expectFutureValue shouldEventually Copyright © Classmethod, Inc. 30
  31. 31. it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; Comments for describe, context, it }); Copyright © Classmethod, Inc. 31
  32. 32. it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; Comments for describe, context, it }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ __block NSDictionary *res; [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { res = response; }]; [[expectFutureValue(res) shouldEventually] beNonNil]; [[expectFutureValue(res[@"id"]) shouldEventually] equal:object[@"id"]]; [[expectFutureValue(res[@"name"]) shouldEventually] equal:object[@"name"]]; }); Copyright © Classmethod, Inc. 32
  33. 33. it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; Comments for describe, context, it }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ __block NSDictionary *res; [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { res = response; }]; [[expectFutureValue(res) shouldEventually] beNonNil]; [[expectFutureValue(res[@"id"]) shouldEventually] equal:object[@"id"]]; [[expectFutureValue(res[@"name"]) shouldEventually] equal:object[@"name"]]; }); Copyright © Classmethod, Inc. 33
  34. 34. it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; ぶ }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ __block NSDictionary *res; [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { res = response; }]; [[expectFutureValue(res) shouldEventually] beNonNil]; ! [[expectFutureValue(res[@"id"]) shouldEventually] equal:object[@"id"]]; [[expectFutureValue(res[@"name"]) shouldEventually] equal:object[@"name"]]; ブロック内で結果を取得、 ブロックの後で確認 }); Copyright © Classmethod, Inc. 34
  35. 35. it(@"ブロックハンドラから正常に値が帰ってくる", ^{ [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { [[response should] beNonNil]; [[response[@"id"] should] equal:object[@"id"]]; [[response[@"name"] should] equal:object[@"name"]]; }]; Comments for describe, context, it }); it(@"ブロックハンドラから正常に値が帰ってくる", ^{ __block NSDictionary *res; [webService fetchDataWithCompletion:^(NSDictionary *response, NSError *err) { res = response; }]; [[expectFutureValue(res) shouldEventually] beNonNil]; [[expectFutureValue(res[@"id"]) shouldEventually] equal:object[@"id"]]; [[expectFutureValue(res[@"name"]) shouldEventually] equal:object[@"name"]]; expectFutureValue shouldEventually }); Copyright © Classmethod, Inc. 35
  36. 36. Copyright © Classmethod, Inc. 36
  37. 37. 実行される! Copyright © Classmethod, Inc. 37
  38. 38. References ! ! ・Asynchronous Testing - allending/Kiwi Wiki last edited by Dave Meehan, cited 2014 Feb 09  Available from : https://github.com/allending/Kiwi/wiki/Asynchronous-Testing Copyright © Classmethod, Inc. 38

×