【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アプリを開発できます!

コメント

このブログの人気の投稿

【iOS】SwiftでCGAffineTransformから角度・ラジアン・度数・スケールを計算する方法

【Android】WebViewのズームボタン(ピンチイン・ピンチアウト)を非表示にする方法

【iOS】UILabelでヒラギノフォントの上下が切れる問題と対処法