iOSテスト入門: BDD開発とQuick/Nimbleの体験記

# はじめに
これまで私はiOSのテストコードの作成経験がなかったのですが、
開発後の検証段階で実装漏れを発見するなどの手戻りに直面していました。
そのため、テストコードの知識が開発効率や品質を向上させる可能性があると感じ、
「iOSテスト全書」を手に取り、書籍の指南に基づきながらテストコードを実際に書き、
BDD開発フローに触れてみることにしました。

https://peaks.cc/books/iOS_testing

# 環境
Mac OS Monterey 12.6
Xcode version 14.2
Swift version 5.7.2

# テストに関連する用語について調べました
## ユニットテスト
単体テストとも呼ばれます。
プログラムを構成する比較的小さな単位(ユニット)が個々の機能を正しく果たしているかどうかを検証するテストです。
 通常、関数やメソッドが単体テストの単位(ユニット)となります。

## インテグレーションテスト
結合テストとも呼ばれます。
他のクラスや外部モジュールと結合して検証するテストです。
機能間の連携や一連の機能が仕様書通りに正しく動作するか確認します。

## 受け入れテスト
開発されたソフトウェアなどのシステムが、発注者の要求通りに動作するか確認するためのテストを指します。

テストピラミッド図でそれぞれのテスト関係を表しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/e8bcd221-7425-325a-659f-fa2f2db8a0f2.png)

https://gihyo.jp/dev/serial/01/savanna-letter/0005#:~:text=%E3%83%86%E3%82%B9%E3%83%88%E3%83%94%E3%83%A9%E3%83%9F%E3%83%83%E3%83%89%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%82%B9%E3%83%88,%E8%A6%96%E8%A6%9A%E5%8C%96%E3%81%97%E3%81%9F%E3%82%82%E3%81%AE%E3%81%A7%E3%81%99%E3%80%82

## BDD開発とは
振る舞い駆動開発（behavior driven development： BDD）と呼ばれます。
プログラム開発の一種で、TDD開発から派生した手法です。
ユーザーストーリーに重きを置き、エンジニアがユーザーの視点から実装すべき機能を考えます。
TDDの課題を解決するための手法です。
`- どこから始めるか？ 　- 何をテストするか？ 　- 何をテストしないか？ `

## TDD開発とは
テスト駆動開発（Test-Driven Development: TDD）と呼ばれます。
プログラムに必要な各機能について、以下の工程を短く繰り返すスタイルです。
1. 失敗するテストを書く
1. できる限り早く、テストに通るような最小限のコードを書く
1. コードの重複を除去する（リファクタリング）

# なぜBDD開発をやるのか
> 品質のよいソフトウェアを安定して継続的にリリースするため

当書では「外側の品質」と「内側の品質」という観点があり、
「外側の品質」は、利用者から見たソフトウェアの品質
「内側の品質」は、開発者から見たソフトウェアの内部構造における品質を表しています。
品質のよいソフトウェアを安定して継続的にリリースするためには、
「外側の品質」と「内側の品質」両方を考える必要があるようです。

BDDの全体像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/f9031aba-d242-3cdf-a776-a9438ba0a4b2.png)


iOSテスト全書P132,133より引用
# やってみたこと
数値をカウントするシンプルなアプリを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/1da49a5a-4a01-4708-71f2-56d2308f3064.png)

当書に合わせテストコードを初回はXCTestで作成し、
その後、Quick,Nimbleというテストライブラリを利用しました。
Quick,Nimble導入については割愛します。

https://qiita.com/uhooi/items/fb577e5dd259cca365c7

## 開発の流れ
1. BDD の土台を構築する
1. カウント機能を実装する
1. 永続化機能を実装する


### BDDの土台構築

1. Xcodeプロジェクトを作成する
1. 画面レイアウト(Storyboard)を作成する
1. ViewControllerとエントリポイントを作成する
1. 失敗する受け入れテストを作成する
1. 受け入れテストが成功するように実装する
1. CI / CD 環境を整備する
    
当書に沿って進めて今回、CI/CD環境の整備は割愛しています。

### BDD開発
カウント機能、永続化機能それぞれ受け入れテストを作成します。
1. (失敗する) 受け入れテストを作成する[^1]
1. TDDを利用して機能を実装する
1. 受け入れテストが成功するまで 2. を繰り返す
1. 1. に戻って繰り返す

[^1]:当書では ViewController を介したテストのこと

### TDD開発
1. （失敗する）ユニットテストを作成する
1. テスト失敗 
XCTestの例![スクリーンショット 2023-10-12 13.40.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/58eea5fb-e6df-aab2-608d-64134a98c3ae.png)

1. 機能を追加する
1. テスト成功　
XCTestの例![スクリーンショット 2023-10-12 16.45.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/99502ae1-c006-5dd2-22c1-04de418b4de4.png)
1. リファクタリング
1. テスト成功
1. 1. に戻って繰り返す

# Quick,Nimbleについて
## Quickとは
テストとテストグループの文法を提供するライブラリです。
RSpec, Specta, Ginkgoにインスパイアされています。

## Nimbleとは
アサーションの文法を提供するライブラリです。
アサーションとはアプリケーションが期待する動作をしているか確認するステップです。

https://help.mabl.com/docs/best-practices-for-assertions-ja#:~:text=%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E7%9B%AE%E7%9A%84%E3%81%8C%E7%89%B9%E5%AE%9A,%E3%81%84%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%81%A7%E3%81%99%E3%80%82

## XCTestとの違い
今回Quick,Nimbleで作成したテストコードの一部です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/28b3c622-ad48-37d3-17bb-e23249fff213.png)

XCTestと比較していきます。
アサーションの文法例です。
```swift
// XCTest
XCTAssertEqual(vc.countLabel.text, "0")

// Nimble
expect(vc.countLabel.text).to(equal("0"))
```
エラー文の例です。
XCTest
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/30a0b561-5a37-c8a3-d8ed-9fb63e9023a6.png)
Nimble
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/da277a1e-9d23-6def-e035-584c8cf34fac.png)

Xcode左側のテストナビゲータです。
XCTest（CounterSampleTests）はテスト関数が表示され、
Quick（CounterSpec）はテスト内容が表示され可読性が上がっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/2b14d230-da34-d3a2-bdb4-84cf0b451960.png)

テストライブラリを利用すると可読性が上がっていることがわかります。
しかし、コードの量が増えてしまうため、テストコードが増えた時の扱いが難しそうに思いました。

# BDD開発を体験して学んだこと
- テストから作成する考え方
- 「どう実装するのか」でなく「どのように振る舞うべきか」という視点の重要性
- XCtestとQuick/Nimbleの違い

# 感想
テストコードを手を動かして実際に書き、Xcodeのテスト機能の奥深さを実感しました。
テストファーストのアプローチは、ステップごとの実装を明確に分解する点で、
タスクの階層的な分解としてのWBSに似ていると感じました。
しかし、テスト内容の設計や設定には時間がかかり、特に適切なテストケースの設定は容易ではありませんでした。
完全なBDD活用のためには、CI/CDの組み込みも必要と感じ、今回はそれが課題として残りました。
実務でのテスト手法の導入には、コストや時間、チームのスキルを考慮する必要があり、
そのバランスをどう取るかは今後の学びの中で探求していきたいです。

# 運動通信社について

運動通信社は「日本を世界が憧れるスポーツ大国にする」というビジョンを達成するべく、一緒に働く仲間を募集しています！
PMやWebエンジニアなど色んな職種を募集しておりカジュアル面談大歓迎なので是非採用フォームよりご連絡ください！
ぜひ一緒に、自分たちも世の中もワクワクするサービスを作りましょう！

https://sportsbull.jp/about/#recruit