【Swift】テストできない、純粋関数を意識しようよ。
はじめに
SwiftUIでアプリを開発していると、View
の中にロジックを書いてしまい、いざ単体テストをしようとするとテストできない……そんな経験はありませんか?
「実装者がどこまで想定して動作確認をおこなったのか分からない」「テストがしにくく、バグが潜んでいても気付きにくい」など、テストのしづらさは品質の低下につながります。
そこで重要なのが 純粋関数(Pure Function) です。本記事では、純粋関数を活用して、テストしやすいコードを設計する方法について解説します。
SwiftUIのViewの中にロジックを書くと何が問題?
SwiftUIでは、View
の中にロジックを書くと次のような問題が発生します。
1. テストが困難になる
View
はUIの描画を行うためのものであり、状態を持つことが多いため、
純粋に入力→出力の関係に基づいたテストができなくなる ことが多いです。
struct ContentView: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("\(count)")
Button("Increment") {
count += 1
}
}
}
}
この例では、ボタンを押すたびにcount
が増えますが、
このロジックを単体テストしようとすると、UIのイベントをシミュレートする必要があります。
2. 動作確認の範囲が曖昧になる
実装者がどの条件を想定して動作確認を行ったのか分からないため、
バグが潜んでいても気付きにくくなります。
純粋関数を活用しよう
純粋関数とは、
- 副作用がない(外部の状態を変更しない)
- 同じ入力に対して常に同じ出力を返す
という特性を持つ関数のことです。
純粋関数を用意すると、テストがしやすくなります。
例:ビジネスロジックを分離する
先ほどのcount
の更新を純粋関数に切り出してみましょう。
func increment(_ value: Int) -> Int {
return value + 1
}
この関数は、入力(現在の値)に対して常に同じ出力を返します。
このincrement
関数の単体テストは簡単に書けます。
import XCTest
class LogicTests: XCTestCase {
func testIncrement() {
XCTAsserEqual(increment(0), 1)
XCTAsserEqual(increment(5), 6)
}
}
Viewにロジックを埋め込まずに使う
increment
関数を利用して、Viewの中のロジックを整理します。
struct ContentView: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("\(count)")
Button("Increment") {
count = increment(count)
}
}
}
}
こうすることで、View
の責務はUIの描画に集中し、
ロジックはテスト可能な純粋関数として分離できます。
まとめ
SwiftUIのView
の中にロジックを書くと、
- テストが難しくなる
- 実装者の動作確認範囲が不明瞭になる
といった問題が発生します。
これを防ぐために、
✅ 純粋関数を活用し、テスト可能な形にロジックを分離する
✅ View
の責務をUIの描画に集中させる
ということを意識しましょう。
テスト可能で保守しやすいSwiftUIアプリを開発できます!
コメント
コメントを投稿