Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
iOSアプリ開発における効果的なUnitTestの戦略とその実装
Search
GO Inc. dev
September 28, 2023
Programming
1.2k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
iOSアプリ開発における効果的なUnitTestの戦略とその実装
後夜祭 iOSDC Japan 2023
で発表した資料です。
GO Inc. dev
September 28, 2023
More Decks by GO Inc. dev
See All by GO Inc. dev
タクシーアプリ『GO』の実践的データ活用〜位置情報データの収集とStreamlitでの可視化〜
mot_techtalk
2
270
バグチケットをAIで全自動解決する 生成AIに人の仕事を任せきるために必要だったこと
mot_techtalk
1
450
タクシーアプリ『GO』の実践的データ活用
mot_techtalk
4
580
エンジニアはドメイン知識とどう向き合うべきか?
mot_techtalk
1
670
ちょっとだけ踏み込んだ ダイナミックプライシング 〜オンデマンド交通への拡張〜
mot_techtalk
1
190
MySQL, PostgreSQLのオブザーバビリティをGrafanaで向上させた話
mot_techtalk
3
1k
タクシー車両の位置状態情報を支えるシステムのインフラ構成
mot_techtalk
2
1k
SREの視点で挑む Redis Stream 無停止移行
mot_techtalk
2
970
生成AIで社内データを整備しよう
mot_techtalk
1
340
Other Decks in Programming
See All in Programming
LLMは4年分のCompose移行を再現できるのか?実プロダクト279件のXMLで探る自動化の境界線
makun
0
590
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
360
What We Talk About When We Talk About XP
m_seki
2
570
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
140
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
140
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
0
220
自分的「カンファレンスの楽しみ方」
syumai
0
200
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
700
App Intentsのビルドプロセスを支える技術
kntkymt
0
310
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
470
GKE で Pod の見方を変えたら、スケールアウト時の挙動を真に捉えられた話
stkk
0
110
Webの地図
yosuke_furukawa
PRO
6
4.3k
Featured
See All Featured
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
450
ラッコキーワード サービス紹介資料
rakko
1
4.8M
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.8k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
380
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
980
Code Review Best Practice
trishagee
74
20k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Transcript
© GO Inc. iOSアプリ開発における効果的 なUnitTestの戦略とその実装 2023.09.26 開発本部 ソフトウェア開発統括部 ユーザーシステム開発部 ユーザーシステム1グループ
/ 髙橋秀宗 GO株式会社
© GO Inc. 2 自己紹介 GO株式会社 ユーザーシステム1グループ / 髙橋秀宗 2022年12月に入社。タクシーアプリ『GO』のiOSアプリ
開発を担当 趣味はエレキギター演奏 お気に入りのアンプはMarshall JCM800 @h1d3mun3
Index © GO Inc. 1. UnitTestとは 2. 単一責任原則 3. 実践UnitTest
4. まとめ 5. 参考資料 3
© GO Inc. UnitTestとは 01
© 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/
© 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/
© GO Inc. • 詳細設計で実装したものをテストする ◦ 作ったクラスや、変更した処理など • 要件定義・基本設計レベルの観点はテストしない UnitTestのスコープ
7
© GO Inc. • ホワイトボックステスト ◦ システムの内部も考慮したテスト ◦ if式やswitch式、guard式などが動くかどうかも考慮する •
ブラックボックステスト ◦ システムの外部をテストする ◦ 入力に対して期待する出力かどうかを考慮する ホワイトボックステスト・ブラックボックステスト 8
© GO Inc. • 🙆 メリット 🙆 ◦ 高速に、何度も、正確に実施できる ◦
実施コストが低い • 🙅 デメリット🙅 ◦ 状況に応じて操作を分けるのが難しい ◦ 人間的な操作など、非規則的なテストが難しい UnitTestの特徴 9
© GO Inc. • テスト対象 ◦ 詳細設計に対応するので、実装したクラスや処理などをチェック • コスト ◦
実行コストが低いので、CI上でDailyで回すなどして、問題の早期発見に活 用する • テスト方式 ◦ 問題の早期発見を主眼にするので、クラスや処理の入力と出力を見るブラッ クボックステストを行う UnitTestの効果的な使い方 10
© GO Inc. 単一責任原則 02
© GO Inc. • モジュールはたったひとつのアクターに対して責務を負うべきである、という原 則 • アクターとは「ユーザーやステークホルダーのグループ」のこと ◦ もちろんソースコード内部の別ファイルもアクターになりうる
🎉 → これが守られていると、モジュール(≒ソースコード)を変更する理由は必ず1つに なる 単一責任原則 12
© GO Inc. 実践UnitTest 03
© GO Inc. 1. 既存のコードをアクターを単位にして分割する 2. 分割したコードの振る舞いをProtocolに抽象化しDI可能にする 3. それぞれに対してMockを利用してテストをする 既存のコードにUnitTestを適用させる
14
© GO Inc. やってみよう! • Notification構造体でアプリ内お知らせを表現 • NotificationManagerクラスが、アプリ内お知らせを管理 し、下記を行っている ◦
現在のお知らせ一覧を返却する機能 ◦ メッセージの既読処理 ◦ APIを経由したサーバーへの反映処理 15
© GO Inc. Notification構造体 struct Notification { let title: String
let isRead: Bool } 16
© GO Inc. NotificationManagerクラス class NotificationManager { func getAllUnReadNotifications() ->
[Notification] { 〜〜〜 } func markAsRead(notification: Notification, completion: @escaping (() -> Void)) { 〜〜〜 } func postApi(notification: Notification, completion: @escaping (() -> Void)) { 〜〜〜 } } 17
© GO Inc. 修正前クラス図 18
© GO Inc. 1. 既存のコードをアクターを単位にして分割する 2. 分割したコードの振る舞いをProtocolに抽象化しDI可能にする 3. それぞれに対してMockを利用してテストをする 再掲:
既存のコードにUnitTestを適用させる 19
© GO Inc. 各責務をそれぞれ別々のファイルに分割する • メッセージの既読処理 ◦ → MarkAsReadUseCase •
現在のお知らせ一覧を返却する機能 ◦ → NotificationRepository • APIを経由したサーバーへの反映処理 ◦ → NotificationServerDataStore 既存のコードをアクターを単位にして分割する 20
© GO Inc. 修正後クラス図 21
© GO Inc. 1. 既存のコードをアクターを単位にして分割する 2. 分割したコードの振る舞いをProtocolに抽象化しDI可能にする 3. それぞれに対してMockを利用してテストをする 再掲:
既存のコードにUnitTestを適用させる 22
© GO Inc. UnitTestのときにMockを作成しやすくするため、責務をProtocolに抽象化する 分割したコードの振る舞いをProtocolに抽象化しDI可能にする 23
© GO Inc. 修正後クラス図 24
© GO Inc. 1. 既存のコードをアクターを単位にして分割する 2. 分割したコードの振る舞いをProtocolに抽象化しDI可能にする 3. それぞれに対してMockを利用してテストをする 再掲:
既存のコードにUnitTestを適用させる 25
© 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) } }
© GO Inc. UnitTestを書く 〜 MarkAsReadUseCaseImpl 27 MarkAsReadUseCaseImplの役割は1つ 1. RepositoryのStore関数を呼び出す
→ 上記が正しく動作することをUnitTestで確認する
© GO Inc. UnitTestを書く 〜 MarkAsReadUseCaseImpl 28 1. NotificationRepositoryのMockを作る 2.
MockをDIしてMarkAsReadUseCaseImplを初期化する 3. テスト用のNotificationを利用してmarkAsRead関数を呼び出す。 4. Repositoryの関数呼び出し回数と、取り扱っているデータが正しいことを確認 する
© 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() } }
© GO Inc. let fakeRepository = FakeNotificationRepository() execute関数のテストを書く 30
© GO Inc. let fakeRepository = FakeNotificationRepository() let subject =
MarkAsReadUseCaseImpl(notificationRepository: fakeRepository) execute関数のテストを書く 31
© GO Inc. let fakeRepository = FakeNotificationRepository() let subject =
MarkAsReadUseCaseImpl(notificationRepository: fakeRepository) let fakeNotification = Notification(title: "テストお知らせ", isRead: false) subject.execute(notification: fakeNotification, completion: { in }) execute関数のテストを書く 32
© 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
© GO Inc. UnitTestを書いたことによる副次的なメリット • アクターをベースとした責務で切り分けたので、既存コードに対して修正を行っ た際の意図せぬ副作用のリスクを低減できた 34
© GO Inc. まとめ 04
© GO Inc. まとめ 36 • UnitTestは詳細設計に対応するテストで、クラスや処理をテストする • UnitTestをCI上でDailyで回すなどして問題の早期発見に活かすと良い •
既存コードに適用する場合は、アクターという観点で既存コードを分解してから UnitTestを組む
© GO Inc. 参考資料 05
© 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
文章・画像等の内容の無断転載及び複製等の行為はご遠慮ください。 © GO Inc.