Claude-skill-registry ios-test-design
XCTest/XCUITestを用いたiOSアプリのテスト設計支援スキル。テスト戦略立案、モック/スタブ設計、テストデータ管理、カバレッジ分析を包括的にサポート。Use when: iOSテスト設計、XCTest実装、UITest作成、テストカバレッジ向上、テスト戦略立案、テストダブル設計。
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/ios-test-design" ~/.claude/skills/majiayu000-claude-skill-registry-ios-test-design && rm -rf "$T"
manifest:
skills/data/ios-test-design/SKILL.mdsource content
iOS Test Design(iOSテスト設計支援)
概要
XCTestおよびXCUITestを活用したiOSアプリケーションのテスト設計を支援するスキル。 デトロイト学派寄りのアプローチを採用し、実際のコンポーネント連携をテストすることで、信頼性の高いテストスイートを構築する。
対象範囲
- Unit Test: XCTestによる単体テスト設計
- Integration Test: コンポーネント間連携テスト
- UI Test: XCUITestによるUIテスト設計
- テストダブル: モック/スタブ/フェイク/スパイの設計
- テストデータ: フィクスチャ、ファクトリ、シード管理
実行条件
以下の状況でこのスキルを起動する:
- iOSアプリのテスト設計・実装を行う時
- 既存テストのリファクタリングを検討する時
- テストカバレッジを向上させたい時
- テストダブル(モック/スタブ)の設計を相談したい時
- テスト戦略を立案したい時
- テストの保守性・可読性を改善したい時
プロセス
Phase 1: テスト対象の分析
1.1 対象コードの理解
- テスト対象のクラス/構造体/関数を特定
- 依存関係を洗い出す
- 公開インターフェースを確認
- 副作用(ネットワーク、永続化、通知等)を特定
1.2 テスト可能性の評価
| 評価項目 | 確認内容 |
|---|---|
| 依存性注入 | コンストラクタ/プロパティ経由で差し替え可能か |
| 副作用の分離 | I/O操作がプロトコル経由で抽象化されているか |
| 状態の観測 | 内部状態の変化を外部から検証可能か |
| 決定論性 | 同一入力に対して同一出力が保証されるか |
Phase 2: テスト戦略の策定
2.1 テストピラミッドの設計
╱╲ ╱ ╲ E2E Test(XCUITest): 主要シナリオのみ ╱────╲ ╱ ╲ Integration Test: コンポーネント間連携 ╱────────╲ ╱ ╲ Unit Test: ビジネスロジック中心 ╱────────────╲
2.2 テストレベル別の方針
| レベル | 対象 | テストダブル | 実行頻度 |
|---|---|---|---|
| Unit | ビジネスロジック、ViewModel、Utility | スタブ/モック | 常時 |
| Integration | UseCase + Repository、View + ViewModel | スタブ(外部境界のみ) | PR/CI |
| UI | 主要ユーザーフロー | なし(実環境に近づける) | デイリー/リリース |
Phase 3: XCTestによるUnitテスト設計
詳細は
references/xctest-patterns.md を参照。
3.1 テストケースの構造
final class SampleTests: XCTestCase { // MARK: - Properties private var sut: SystemUnderTest! private var mockDependency: MockDependency! // MARK: - Setup/Teardown override func setUp() { super.setUp() mockDependency = MockDependency() sut = SystemUnderTest(dependency: mockDependency) } override func tearDown() { sut = nil mockDependency = nil super.tearDown() } // MARK: - Tests func test_methodName_condition_expectedBehavior() { // Given(前提条件) let input = ... // When(実行) let result = sut.method(input) // Then(検証) XCTAssertEqual(result, expected) } }
3.2 命名規則
test_<対象メソッド>_<条件>_<期待される振る舞い> 例: test_login_withValidCredentials_returnsSuccess test_fetchUser_whenNetworkError_throwsError test_calculate_withNegativeInput_returnsZero
Phase 4: テストダブルの設計
詳細は
references/test-doubles.md を参照。
4.1 テストダブルの種類と使い分け
| 種類 | 用途 | 実装例 |
|---|---|---|
| Stub | 事前定義した値を返す | |
| Mock | 呼び出しを検証する | |
| Fake | 軽量な実装 | |
| Spy | 呼び出し履歴を記録 | |
4.2 プロトコルベースのテストダブル
// 抽象化されたプロトコル protocol UserRepositoryProtocol { func fetch(id: String) async throws -> User } // 本番実装 final class UserRepository: UserRepositoryProtocol { ... } // テストダブル final class MockUserRepository: UserRepositoryProtocol { var fetchResult: Result<User, Error> = .success(User.stub) var fetchCallCount = 0 var lastFetchedId: String? func fetch(id: String) async throws -> User { fetchCallCount += 1 lastFetchedId = id return try fetchResult.get() } }
Phase 5: XCUITestによるUIテスト設計
詳細は
references/xcuitest-patterns.md を参照。
5.1 Page Objectパターン
// Page Object final class LoginPage { private let app: XCUIApplication var emailField: XCUIElement { app.textFields["email"] } var passwordField: XCUIElement { app.secureTextFields["password"] } var loginButton: XCUIElement { app.buttons["login"] } init(app: XCUIApplication) { self.app = app } func login(email: String, password: String) -> HomePage { emailField.tap() emailField.typeText(email) passwordField.tap() passwordField.typeText(password) loginButton.tap() return HomePage(app: app) } }
5.2 Accessibility Identifierの設計
| 要素 | 命名規則 | 例 |
|---|---|---|
| 画面 | | |
| ボタン | | |
| テキストフィールド | | |
| ラベル | | |
| セル | | |
Phase 6: テストデータ管理
詳細は
references/test-data.md を参照。
6.1 Factoryパターン
enum UserFactory { static func make( id: String = UUID().uuidString, name: String = "Test User", email: String = "test@example.com", isActive: Bool = true ) -> User { User(id: id, name: name, email: email, isActive: isActive) } static var activeUser: User { make(isActive: true) } static var inactiveUser: User { make(isActive: false) } }
6.2 フィクスチャファイル
Tests/ ├── Fixtures/ │ ├── JSON/ │ │ ├── user_response.json │ │ └── error_response.json │ └── Stubs/ │ └── UserStub.swift
Phase 7: テストカバレッジ分析
7.1 カバレッジ目標
| レベル | 目標 | 説明 |
|---|---|---|
| 行カバレッジ | 80%以上 | 実行された行の割合 |
| 分岐カバレッジ | 70%以上 | if/switch分岐の網羅 |
| 重要パス | 100% | ビジネスクリティカルなパス |
7.2 Xcodeでのカバレッジ確認
- スキーム設定 → Test → Options → Code Coverage有効化
でテスト実行Cmd + U- Report Navigator → Coverage でレポート確認
7.3 カバレッジ改善の優先順位
- ビジネスロジック: Domain層、UseCase層
- 状態管理: ViewModel、Reducer
- データ変換: Mapper、Parser、Formatter
- エラーハンドリング: 例外処理、リトライロジック
出力形式
テスト設計ドキュメント
# テスト設計書: <機能名> ## 1. テスト対象 - クラス/構造体: `ClassName` - 責務: 〇〇を行う ## 2. テスト戦略 - テストレベル: Unit / Integration / UI - テストダブル: 使用する依存のリスト ## 3. テストケース一覧 | ID | カテゴリ | テスト内容 | 期待結果 | |----|---------|----------|---------| | TC-001 | 正常系 | ... | ... | | TC-002 | 異常系 | ... | ... | ## 4. テストダブル設計 - MockXxx: 〇〇の呼び出しを検証 - StubYyy: 〇〇の値を返す ## 5. テストデータ - Factory: XxxFactory - Fixture: xxx_response.json
テストコード
import XCTest @testable import TargetModule final class FeatureTests: XCTestCase { // 上記パターンに従ったテストコード }
ガードレール
必須遵守事項
- テストの独立性: 各テストは他のテストに依存しない
- テストの決定論性: 同じ条件で常に同じ結果
- テストの高速性: Unitテストは1秒以内に完了
- 明確な命名: テスト名から内容が分かる
禁止事項
- 本番コードのテスト用変更: テストのために本番コードにテスト用分岐を入れない
- ネットワーク依存: Unitテストで実ネットワークアクセスしない
- 時間依存:
直接使用ではなく注入するDate() - グローバル状態: シングルトンの直接参照を避ける
警告事項
- 過度なモック: 全てをモックすると実装詳細への依存が増す
- テストの重複: 同じ振る舞いを複数箇所でテストしない
- 実装の検証: 「どう動くか」ではなく「何をするか」をテスト
参照
: XCTestパターン集references/xctest-patterns.md
: XCUITestパターン集references/xcuitest-patterns.md
: テストダブル設計ガイドreferences/test-doubles.md
: テストデータ管理ガイドreferences/test-data.md