Golangでテストコードを書く少年のお話

Jan 22, 2019   #Golang 

はじめに

お仕事でGolangのテストコードを書くことになったのでお勉強しました。
テスト対象は以下のプログラムです。

毎朝のルーティンを明文化し、以下の処理をしています。

  • 降水確率40%以上なら傘を装備する。
  • 冬、もしくは最低気温が5度以下ならコートを装備する。

以下の通り、4つの命令と2つの条件分岐で構成されています。

種別 やってること
命令 持ち物を入れるカバンを用意
条件分岐 降水確率による判定
命令 カバンに傘を入れる
条件分岐 季節、最低気温による判定
命令 カバンにコートを入れる
命令 カバンを持ち出す

テストの種類

カバレッジとはテストの網羅率のことを指しています。
「どのパターンのテストを行えば、必要な範囲のテストが完了したのか?」の指標となります。
「必要な範囲」については、C0カバレッジ、C1カバレッジ、C2カバレッジ…とカバレッジの種類によって異なります。

それぞのカバレッジについて簡単に説明していきます。
※C3以降もありますが、よく使われるのはC2までみたいなので、今回は省略します。

C0カバレッジ(命令網羅)

すべての命令を最低1回は実行する、というテストケースを満たせばカバレッジが100%になります。
以下のパターンを実行すれば、すべての命令を実行することができるので、C0カバレッジ100%になります。
「降水確率が50%、季節は冬、最低気温12度。」

C1カバレッジ(分岐網羅)

すべて条件分岐の組み合わせを通る、というテストケースを満たせばカバレッジが100%になります。
今回はTrue/Falseの分岐が2つあるので4パターンの組み合わせでテストを行う必要があります。

パターン 具体例
パターン1 True True 降水確率が50%、季節は冬、最低気温12度。
パターン2 True False 降水確率が50%、季節は春、最低気温12度。
パターン3 False True 降水確率が20%、季節は冬、最低気温12度。
パターン4 False False 降水確率が20%、季節は春、最低気温12度。

具体的には以下のパラメータでテストをやればOKです。

C2カバレッジ(条件網羅率)

すべての条件の組み合わせを通る、というテストケースを満たせばカバレッジが100%になります。
C1カバレッジと似ていますが、C1カバレッジは条件分岐の結果をすべて通ればOKですが、C2カバレッジではすべての条件の結果を通る必要があります。
今回のケースだと、「冬か?」と「最低気温が5度以下か?」という2つの条件のそれぞれに対してTrue/Falseの組み合わせを試す必要があります。

そのため、④の条件分岐を2つに分割し、以下のパターンのテストが必要になります。

パターン ④-1 ④-2 具体例
パターン1 True True True 降水確率が20%、季節は冬、最低気温2度。
パターン2 True True False 降水確率が20%、季節は冬、最低気温12度。
パターン3 True False True 降水確率が20%、季節は春、最低気温2度。
パターン4 True False False 降水確率が20%、季節は春、最低気温12度。
パターン5 False True True 降水確率が50%、季節は冬、最低気温2度。
パターン6 False True False 降水確率が50%、季節は冬、最低気温12度。
パターン7 False False False 降水確率が50%、季節は春、最低気温2度。
パターン8 False False True 降水確率が50%、季節は春、最低気温12度。

具体的には以下のパラメータでテストをやればOKです。

テストコード

それぞれのカバレッジでのパターンも把握したので、さっそくテストコードを書いていきます。
Golangには標準でテスト用のパッケージが用意されているのでそれを使います。

C0カバレッジ100%のコードは以下の通りです。
単純にテスト対象の関数を呼び出して、想定通りの結果が返ってくるか、を見ています。

C1カバレッジ100%のコードは以下の通りです。
テストパターンが増えたので、テストの入力、想定される出力、実際の出力をまとめた構造体の配列を用意して、繰り返し処理をしています。

C2カバレッジ100%のコードは以下の通りです。
こちらはC1カバレッジと同じ構造ですね。パターンだけ増やしました。

カバレッジ

go testでは -coverオプションでカバレッジを確認することもできます。

$ go test -cover -run  TestEquipmentC0
PASS
coverage: 100.0% of statements
ok      github.com/foresukecom/go_test  0.005s

$ go test -cover -run  TestEquipmentC1
PASS
coverage: 100.0% of statements
ok      github.com/foresukecom/go_test  0.005s

$ go test -cover -run  TestEquipmentC2
PASS
coverage: 100.0% of statements
ok      github.com/foresukecom/go_test  0.005s

各テストコードを確認したところ、全コードでカバレッジが100%になりました。C0のカバレッジが確認できるようです。
C1、C2カバレッジも確認できるといいんですが、オプションとかを見た感じだとなさそうです…
なにかC1、C2カバレッジが確認しやすいツールがあれば教えてください。

その他

Life is Strange: Before the Stormをクリアしました。
Life is Strangeの前日譚ということで、結末はある程度わかっていたので余計に辛いものがありました。 前作と同様に、プレイヤーに大きな選択を強いてくるのですが、プレッシャーに耐えきれず、腕立て伏せをして気を落ち着かせてから改めてプレイしたことはいい思い出です。
クロエ、マックス、レイチェル…みな尊い😇

前作に引続き音楽もよかったので、在宅中はよくスマートスピーカーで再生し続けています。