テスト駆動開発(Test-Driven Development)は、テストを先に書き、そのテストを通す最小実装を行い、リファクタリングで設計を洗練していく開発手法です。
- 変更容易性:小さなサイクルが回帰を可視化し、安心して改善できる
- 設計の質:テスト可能設計(疎結合・明確な責務)を自然に促す
- ドキュメント性:テストが実行可能な仕様として残る
Red → Green → Refactor の短サイクルで“変更に強い”設計を生む。小さく、速く、安全に。
// Calculator.swift
struct Calculator {
func add(_ a: Int, _ b: Int) -> Int { a + b }
func isLeapYear(_ y: Int) -> Bool {
// 400の倍数は閏年、100の倍数は平年、4の倍数は閏年
if y % 400 == 0 { return true }
if y % 100 == 0 { return false }
return y % 4 == 0
}
}
// CalculatorTests.swift
import XCTest
@testable import AppModule
final class CalculatorTests: XCTestCase {
func testAdd() {
XCTAssertEqual(Calculator().add(2, 3), 5)
}
func testLeapYearRules() {
XCTAssertTrue(Calculator().isLeapYear(2024))
XCTAssertFalse(Calculator().isLeapYear(1900))
XCTAssertTrue(Calculator().isLeapYear(2000))
}
}
下の関数を編集して を押すと、即席のユニットテストが走ります(安全のため、new Function で限定的に評価)。
| 層 | 推奨 | ポイント |
|---|---|---|
| ドメイン | 単体(Jest/Vitest, JUnit) | 副作用隔離・純粋ロジック化 |
| API | 統合(Contract, Supertest) | 契約テストで依存切断 |
| UI | UIテスト(RTL, Playwright) | 振る舞い中心・過度なスナップショット避け |
| レイヤ | iOS | Android |
|---|---|---|
| ユニット | XCTest | JUnit / KotlinTest |
| UI | XCUITest | Espresso |
| DI | Factory/Protocol | Hilt/Koin |
// 例:BankAccount のTDD(擬似コード)
class BankAccount {
constructor(){ this.balance = 0 }
deposit(amount){ if(amount<=0) throw new Error('invalid'); this.balance += amount }
withdraw(amount){ if(amount<=0 || amount>this.balance) throw new Error('invalid'); this.balance -= amount }
}
test('deposit increases balance', () => {
const a = new BankAccount()
a.deposit(100)
assert.equal(a.balance, 100)
})
test('cannot overdraw', () => {
const a = new BankAccount()
a.deposit(50)
assert.throws(() => a.withdraw(100))
})