単体テストの意義

## はじめに
配属後1カ月が経ち、研修時の備忘録として当該記事を作成することにしました。今回は単体テストについて述べていきます。
文系出身、SE経験も足りなさすぎるので誤った情報を載せる可能性が高いです。すべてを鵜呑みにせず、あくまで参考程度に受け止めてください。また間違いがあれば、ぜひコメントにて教えていただけますとハッピーです。

## 目次
1. 単体テストとは
    1-1. どういうことをするの？
    1-2. どの辺でやるの？
    1-3. どうやってやるの？
1. ホワイトボックステストについて
1. 単体テスト計画書/仕様書
1. 終わりに

## 1. 単体テストとは
### 1-1. どういうことをするの？
単体テストとは、以下の通りです。
> 関数や手続きといった最小単位のプログラムを単体で動かしてみて、内部設計書通りに動作するかどうかを確かめる工程

つまり、いきなりシステム全体をテストしてバグが発生したってどこが問題なのか分からないんだから、細かいところから（バグが発生する可能性を）潰していけということです。

例えば、文字列変換ツールで下のクラスを作りました。
　*・a→Aに変換するUpperクラス*
　*・文字列を読み込むTextReaderクラス*
　*・変換ツールを動かすConvertSystemクラス*
したがって単体テストにおけるテスト対象は、上の3つのクラスになります。もちろん、これはあくまで参考なので、実際の文字列変換ツールはもっと多くのクラスが存在します。

<font color="lightgray">クラス名に英語をつけてあげなきゃいけないのって大変ですよね。しかしこの命名規則にも理由があります。外国人スタッフとの協同や、オフショア開発を考慮しているからです。英語を使わなければならないのは癪ですが、これも社会人としての責務なので頑張りましょうね。</font>
<br>

### 1-2. どの辺でやるの？
ソースコードレビュー後に行います。
しかしレビューは前提ではないです。企業に勤めてる社会的マジョリティな会社員SEはレビューが必須でしょうが、一人でシステム作ってる方もいると思うので。

<font color="lightgray">でも一人で作っていてもレビュアーが自分のこともあるのか。逆にマジョリティSEでテスト前にレビューしないこともあるのか。どういうとき？</font>
<br>

### 1-3. どうやってやるの？
単体テストでは、主に「**ホワイトボックステスト**」というテスト形式を採用しています。このテストは**プログラムの内部構造がわかっていることを前提としたテスト**です。中身が透けて見えているということで、私は「千里眼テスト」と呼んでいます。

話は逸れますが、「ブラックボックステスト」というのもあります。これは上記のテストと真逆で、プログラムの内部構造を考慮しないテスト形式です。詳細は別の記事に書くかもしれないですが、今のところ予定が無いです。

さて、ホワイトボックステストのメリットは、なんといっても**プログラムを網羅的にテストできる**ことです。千里眼を持っている人でも、過去・現在・未来すべてが視える人はそうそういないのに、ホワイトボックステストはそれができちゃうという優れもの。<font color="lightgray">視る対象が異なるので難易度も違うでしょうが。</font>ちなみに「これぐらいのプログラムをテスト実施したよ～」という範囲を**網羅率**(あるいはカバレッジ)といいます。
デメリットは、プログラムが複雑になればなるほどテストデータの作成も難しくなることです。おそらく鼠算式的に分岐が増えるのでしょう。
<br>

## 2. ホワイトボックステストについて
繰り返しますが、このテストは**プログラムを網羅的にテスト**するためのものです。その視点は**開発者側**になります。しかし何のとっかかりも無しに、すべての分岐を通るようなテストデータの作成は難しいものです。
そこで「フローグラフ」という図法を使います。フローグラフとは以下の通りです。
>プログラムの処理を示したフローチャートを基に、処理の流れを探し出し、それを満たすようなデータを探し出す方法

とはいえ、新人の頃に任される単体テスト設計はそれほど複雑なものでないと思います。そういう時は普通に、すべての分岐を通るようなパターンを考えるで大丈夫です。

では、すべての分岐を通るようなパターンを考えるにはどうするのか。ホワイトボックステストには、4つの網羅基準が存在するので、それらを使いましょう。ここではとりあえず簡単な説明をします。

- **命令網羅**
　すべての処理（命令）を最低1回は通す。
- **判定条件網羅**
　すべての分岐を最低1回は通す。
- **条件網羅**
　個々の条件を最低1回は満たす。
- **複数条件網羅**
　想定される条件の組み合わせをすべて網羅する。
<br>

あるいは、フローグラフ図を使うのも良いかもしれません。
> フローグラフ図とは、フローチャートを基に、処理の流れを探し出し、それを満たすようなデータを探し出す方法

> フローチャート中のひし形、長方形、終了をそれぞれ円として描き、描いた円をフローチャートと同じ流れになるよう、矢印で結びます。また、フローチャートの各処理には便宜上の番号を振り、対応する円の中にフローチャートの番号を記述します。こうしてできあがった円と矢印の集まりがフローグラフです。（図5.3）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3855337/b6a5dd2f-86b9-9de8-6531-761b1035ceda.png)

以上より、プログラムを網羅的にテストするためには3つのルート、すなわち3つのテストデータが必要ということがわかります。3つのテストデータに対してテストを行えば、少なくともテスト漏れする処理はないでしょう。
<font color="lightgray">と、ここまで説明しましたが、個人的にはフローチャートが描ければ十分だと思っています。というのも、処理の数や分岐点が分かっていれば、わざわざフローグラフ図を書かなくともテストデータの目星はつけられるはずだからです。しかし人の数だけ方法は生まれるもの。自分に適した方法を見つけてみてください。</font>

<br>

## 3. 単体テスト計画書/仕様書
さて、テストデータの作成まできました。このテストデータは、期待される結果、具体的なテスト方法などを添えて「単体テスト計画書/仕様書」に整理しておきます。なお、スラッシュをつけたのは表記ゆれをカバーするためです。個々人のプロジェクトで呼称が異なりますが、「単体テストをどうやって、どのように行うのかについて記した書類」という意味では同じです。
単体テスト計画書のレイアウトは様々ですが、おおよそ以下のように作られます。
| No. | 分類 | 条件 | 確認内容/期待値 | 実施日 | 実施者 | 確認結果 | 確認者 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|  001 |  正常　|  〇〇 | 〇〇  |  -- | -- |  〇〇 |  --|
|  002 |  異常  |  ×× |   ××| --  |  -- | ××  |  -- |

- **分類**
    プロジェクトによりますが、私は「正常＝システムが普通に動く」「異常＝エラーになる」パターンで書いています。
- **条件**
    テストケースをするにあたっての前提条件で、「～の場合」で終わるような文言が多いです。
- **確認内容/期待値**
    上の条件を踏まえて、どういう結果になるのか/なってほしいのかを書きます。
- **確認結果**
    テストを実施したときの結果を書きます。これはエビデンス（証跡）として別で作成することもあります。

<br>

## 4. 終わりに
この記事では単体テストについて書き出してみました。新人が作成する単体テストケースについて、最低限知っておいたほうが良いことを書いたつもりです。長々と書きましたが、覚えていてほしいのは**単体テストはプログラムを網羅的にテストする**ことです。
後々バグが見つかったとき、バグの原因が、そもそもソースコードを正しく書けていなかったとか。本来は単体テストで見つかるようなバグだったけど、テスト漏れしていて気づけなかったとか。プロジェクトが進めば進むほど、手戻りの数も増えますし、費やす時間も増えます。
単体テストは、書き出すテストケースが比較的多いです。我々は人間ですので、しらみ潰しにテストケースを考えないといけません。その際のとっかかりとしてフローチャートやフローグラフ図を活用してみると良いでしょう。