単体テストの考え方 / 使い方【第2部 : 単体テストとその価値】　読書メモ

**どんな本か**
単体テストの価値を最大限引き出す「良い」テストを書くための原則と実践方法のパターンを紹介する本。

**構成**
大きく4つのパートに分かれている。
1. 単体テストの概要・一般的に広く知られている単体テストの原則の紹介 (第1〜3章)
1. 良い単体テストを構成するものとは何か&どうすれば既存のテストをより価値のあるものにすることができるのかの解説 (第4〜7章)
1. 結合テストについて (第8〜10章)
1. 単体テストでよくあるアンチパターンの紹介 (第11章)

今回は第2部のメモ

# 第2部 単体テストとその価値
## 第4章 良い単体テストを構成する4本の柱
### 良い単体テストを構成する4本の柱
- 退行 (regression) に対する保護
- リファクタリングへの耐性
- 迅速なフィードバック
- 保守のしやすさ

### 退行 (regression) に対する保護とリファクタリング
#### 退行 (regression) に対する保護とは
**退行 (regression)** : コードの変更に伴って、既存の機能が正しく動かなくなること

**退行 (regression) に対する保護** : テストをすることで退行を検出できる性質

:::note info
テスト時に実行されるプロダクション・コードの量が多いほど、多くの退行を検出できる
:::

#### リファクタリングへの耐性とは
**リファクタリングへの耐性** : コードをリファクタリングを可能にする性質

**偽陽性 (false positive)** : テスト対象のコードに問題がないにもかかわらず、テストが失敗すること (**嘘の警告**)

**偽陰性 (false negative)** : テスト対象のコードに問題があるにもかかわらず、テストが成功すること (**警告されないバグ**)

:::note info
ここでの `positive` は、`あることを検証した際に、なんらかの反応が検出されること` を指します。
つまり、テストを実施した際に`失敗した`という結果が検出された場合、そのテストは `positive (陽性)` です。
逆に、`negative`は、`あることを検証した際に、反応が検出されないこと` を指します。
:::

:::note info
嘘の警告が出るテストは、プロダクション・コードの正しい振る舞いを検証していないため、
対象のコードのリファクタリングを不可能にする。
:::

#### 偽陽性は、テスト・スイート&開発全体にどんな影響を与えるのか
- 開発者のプロダクション・コードの問題を解決する意思と能力を弱める
  - 開発者が嘘の警告に見慣れてしまい、注意を払わなくなる
- テストを信頼できるセーフティ・ネットとして見ることができなくなる

#### 偽陽性はなぜ発生するのか
- 偽陽性は、テスト対象のコードの内部と結びつくことで発生する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671379/abbe8ec9-a89c-fe68-45db-337c7d9db2f4.png" width=50%> 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671379/3dbbcbb0-60ba-a937-ac99-8e3ba314c556.png" width=50%>


退行に対する保護とリファクタリングへの耐性は**テストの正確性**に関わる
- テストをすることでどのくらいバグを検出できるのか
  - 検出できていないバグが少ないこと
    - 偽陰性によって示される
- テストをすることでバグがないことをどのくらい示せるのか
  - 嘘の警告が少ないこと
    - 偽陽性によって示される

### 迅速なフィードバックと保守のしやすさ
**迅速なフィードバック** : テストの検証結果をすぐに受け取ることができる性質

#### 迅速なフィードバックがあると何がいいか
- テストの頻度が増える
    - 実施するテストの数が増える
    - 用意できるテスト・ケースの数が増える
- コードの改善速度が速くなる

**保守のしやすさ**
- テスト・コードの保守性が高いかどうか
- テストの際に、プロセス外依存 (データベース、外部サービスなど) が常に正しく機能するようになっているかどうか

#### 保守のしやすさがあると何がいいか
- テスト・ケースを理解しやすくなる
- プロセス外依存が機能するよう、適切な処置がされている場合、されていない場合に比べて、迅速なフィードバックを受け取ることができる

### 理想的なテストの探求
上の4つの性質をテストに常に備えることは不可能。
実施するテストの目的を理解し、優先度を設定することが重要

### ソフトウェア・テストにおけるよく知られた概念
#### テスト・ピラミッド
- 一般的に、テスト観点がエンド・ユーザーに近づくにつれてテスト・ケースの数は増加する
- E2Eテスト、結合テスト、単体テストは特定の割合で存在するようになっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671379/c474a92c-0703-766d-5e26-37e07e230705.png)


## 第5章 モックの利用とテストの壊れやすさ
### モックとスタブの違い
#### モック
テスト対象からその依存に向かって行われる、**外部に向かうコミュニケーション (出力)** を模倣する
コマンド・クエリ分離原則でいうところの**コマンド**にあたる動作を模倣したオブジェクト
- メール送信
- ファイルへの書き込み

#### スタブ
依存からテスト対象に向かって行われる、**内部に向かうコミュニケーション (入力)** を模倣する
コマンド・クエリ原則でいうところの**クエリ**にあたる動作を模倣したオブジェクト
- メール受信
- ファイルの読み込み

コマンドクエリ分離原則について(https://bliki-ja.github.io/CommandQuerySeparation/)
> 基本的な考えは、オブジェクトのメソッドを明確に2つのカテゴリに分類するというものである。
> - 問い合わせ：結果を返し、システムの状態を変更しない（副作用がない）
> - コマンド：システムの状態を変更し、値を返さない

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671379/2f449ebf-4982-1714-cf7e-33f2105cdb96.png)

#### テスト・ダブルのバリエーション
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671379/70a965ad-0ac0-cca4-089e-23fc9539b398.png)



### 観察可能な振る舞いと実装の詳細
### モックの利用とテストの壊れやすさとの関係
### 振り返り : 単体テストの古典学派とロンドン学派の違い
## 第6章 単体テストの3つの手法
### 単体テストの3つの手法
### 単体テストの3つの手法の比較
### 関数型アーキテクチャについて
### 関数型アーキテクチャおよび出力値ベース・テストへの移行
### 関数型アーキテクチャの欠点
## 第7章 単体テストの価値を高めるリファクタリング
### リファクタリングが必要なコードの識別
### 単体テストに価値を持たせるためのリファクタリング
### プロダクション・コードの種類に基づく効果的な単体テストの作成
### コントローラにおける条件付きロジックの扱い