Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSアプリ開発における効果的なUnitTestの戦略とその実装

GO Inc. dev
September 28, 2023

 iOSアプリ開発における効果的なUnitTestの戦略とその実装

後夜祭 iOSDC Japan 2023で発表した資料です。

GO Inc. dev

September 28, 2023
Tweet

More Decks by GO Inc. dev

Other Decks in Programming

Transcript

  1. © GO Inc. 2 自己紹介 GO株式会社 ユーザーシステム1グループ / 髙橋秀宗 2022年12月に入社。タクシーアプリ『GO』のiOSアプリ

    開発を担当 趣味はエレキギター演奏 お気に入りのアンプはMarshall JCM800 @h1d3mun3
  2. © GO Inc. V字モデル 5 実装 基本設計 結合テスト 詳細設計 コンポーネントテスト

    (単体テスト ・UnitTest) 要件定義 システム/受け入れ テスト 対応するテストスコープ https://shiftasia.com/ja/column/v%E5%AD%97%E3%83%A2%E3%83%87%E3%83%AB%E3%81%A8%E3%81%AF/
  3. © GO Inc. V字モデル 6 実装 基本設計 結合テスト 詳細設計 コンポーネントテスト

    (単体テスト ・UnitTest) 要件定義 システム/受け入れ テスト 対応するテストスコープ https://shiftasia.com/ja/column/v%E5%AD%97%E3%83%A2%E3%83%87%E3%83%AB%E3%81%A8%E3%81%AF/
  4. © GO Inc. • ホワイトボックステスト ◦ システムの内部も考慮したテスト ◦ if式やswitch式、guard式などが動くかどうかも考慮する •

    ブラックボックステスト ◦ システムの外部をテストする ◦ 入力に対して期待する出力かどうかを考慮する ホワイトボックステスト・ブラックボックステスト 8
  5. © GO Inc. • 🙆 メリット 🙆 ◦ 高速に、何度も、正確に実施できる ◦

    実施コストが低い • 🙅 デメリット🙅 ◦ 状況に応じて操作を分けるのが難しい ◦ 人間的な操作など、非規則的なテストが難しい UnitTestの特徴 9
  6. © GO Inc. • テスト対象 ◦ 詳細設計に対応するので、実装したクラスや処理などをチェック • コスト ◦

    実行コストが低いので、CI上でDailyで回すなどして、問題の早期発見に活 用する • テスト方式 ◦ 問題の早期発見を主眼にするので、クラスや処理の入力と出力を見るブラッ クボックステストを行う UnitTestの効果的な使い方 10
  7. © GO Inc. やってみよう! • Notification構造体でアプリ内お知らせを表現 • NotificationManagerクラスが、アプリ内お知らせを管理 し、下記を行っている ◦

    現在のお知らせ一覧を返却する機能 ◦ メッセージの既読処理 ◦ APIを経由したサーバーへの反映処理 15
  8. © GO Inc. NotificationManagerクラス class NotificationManager { func getAllUnReadNotifications() ->

    [Notification] { 〜〜〜 } func markAsRead(notification: Notification, completion: @escaping (() -> Void)) { 〜〜〜 } func postApi(notification: Notification, completion: @escaping (() -> Void)) { 〜〜〜 } } 17
  9. © GO Inc. 各責務をそれぞれ別々のファイルに分割する • メッセージの既読処理 ◦ → MarkAsReadUseCase •

    現在のお知らせ一覧を返却する機能 ◦ → NotificationRepository • APIを経由したサーバーへの反映処理 ◦ → NotificationServerDataStore 既存のコードをアクターを単位にして分割する 20
  10. © GO Inc. UnitTestを書く 〜 MarkAsReadUseCaseImpl 26 protocol MarkAsReadUseCase {

    func execute(notification: Notification, completion: @escaping (() -> Void)) } struct MarkAsReadUseCaseImpl: MarkAsReadUseCase { let notificationRepository: NotificationRepository func execute(notification: Notification, completion: @escaping (() -> Void)) { notificationRepository.store(notification: readNotification, completion: completion) } }
  11. © GO Inc. UnitTestを書く 〜 MarkAsReadUseCaseImpl 28 1. NotificationRepositoryのMockを作る 2.

    MockをDIしてMarkAsReadUseCaseImplを初期化する 3. テスト用のNotificationを利用してmarkAsRead関数を呼び出す。 4. Repositoryの関数呼び出し回数と、取り扱っているデータが正しいことを確認 する
  12. © GO Inc. NotificationRepositoryのMockを作る 29 struct FakeNotificationRepository: NotificationRepository { func

    getAllNotification() -> [Notification] { return [] } var storeCallCount = 0 var storeArguments: Notification! func store(notification: Notification, completion: @escaping (() -> Void)) { storeCallCount += 1 storeArguments = notification completion() } }
  13. © GO Inc. let fakeRepository = FakeNotificationRepository() let subject =

    MarkAsReadUseCaseImpl(notificationRepository: fakeRepository) execute関数のテストを書く 31
  14. © GO Inc. let fakeRepository = FakeNotificationRepository() let subject =

    MarkAsReadUseCaseImpl(notificationRepository: fakeRepository) let fakeNotification = Notification(title: "テストお知らせ", isRead: false) subject.execute(notification: fakeNotification, completion: { in }) execute関数のテストを書く 32
  15. © GO Inc. let fakeRepository = FakeNotificationRepository() let subject =

    MarkAsReadUseCaseImpl(notificationRepository: fakeRepository) let fakeNotification = Notification(title: "テストお知らせ", isRead: false) subject.execute(notification: fakeNotification, completion: { in }) expect(fakeRepository.storeCallCount).to(equal(1)) expect(fakeRepository.storeArguments).to(equal(fakeNotification)) execute関数のテストを書く 33
  16. © GO Inc. まとめ 38 • V字モデルとは ◦ https://shiftasia.com/ja/column/v%E5%AD%97%E3%83%A2%E3%83 %87%E3%83%AB%E3%81%A8%E3%81%AF/

    • ホワイトボックステストとは ◦ https://service.shiftinc.jp/column/4801/ • solid+cqs+dry ◦ https://speakerdeck.com/kgmyshin/solid-plus-cqs-plus-dry