今回は、自動テストについて学びましょう。
プログラムの品質を保つために、プログラマがテストコードを書くことは必須事項になりつつあります。
<目次>
学習記事まとめ
テストツール
Go言語には、テストモジュールである”testing”パッケージが組み込まれています。
まずは、実際にプログラムを作成しましょう。
最初に、プロダクトコードとテストコードを格納するフォルダとファイルを用意します。
1 2 3 4 5 |
mkdir myculc # プロダクトファイル touch myculc/myculc.go # テストファイル touch myculc/myculc_test.go |
Go言語ではこのように、テスト対象のファイルと同階層にテストファイルを格納します(必須ではありません)。そして重要なのが、”XXXX_test.go“と命名する必要があります。そうしなければ、テストが実行されません。
先にプロダクトコードを記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package myculc func plus(num1, num2 int) int { return num1 + num2 } func substract(num1, num2 int) int { if num1 > num2 { return num1 - num2 } else { return num2 - num1 } } |
引数として渡した値を足し算するか、引き算するかの簡単なプログラムです。
Go言語でのテストは以下のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package myculc import "testing" // TestXXXXと命名する func TestPlus(t *testing.T) { sum := plus(10, 20) if sum != 30 { t.Error("Error") } } func TestSubstract(t *testing.T) { s := substract(20, 10) if s != 10 { t.Error("Error") } } |
関数名にもルールがあり、「TestXXXX」と命名する必要があります。
このテストを実行するために、terminal上で次のコマンドを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ ls myculc.go myculc_test.go // テスト実行 $ go test PASS ok github.com/hoge/myculc 0.008s // 詳細 $ go test -v === RUN TestPlus --- PASS: TestPlus (0.00s) === RUN TestSubstract --- PASS: TestSubstract (0.00s) PASS ok github.com/hoge/myculc 0.013s |
上記の結果は、テストがPASSしたことを表します。
ちなみに、テストが失敗した場合は次のように表示されます。
1 2 3 4 5 6 7 8 |
$ go test --- FAIL: TestPlus (0.00s) myculc_test.go:8: Error --- FAIL: TestSubstract (0.00s) myculc_test.go:15: Error FAIL exit status 1 FAIL github.com/hoge/myculc 0.008s |
Errorfメソッドでエラーメッセージ操作
fmtパッケージのErrorf関数と同様にtesting関数もErrorf関数を持っており、この関数を利用してカスタマイズしたエラーメッセージを作成できます。
arithmeticディレクトリを作成し、その中にmath.goとmath_test.goを作成してください。
1 2 3 4 5 6 7 |
// math.go package arithmetic func Add(a float64, b float64) float64 { return a + b } |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package arithmetic import ( "testing" ) func TestAdd(t *testing.T) { expect := 3.0 result := Add(1, 2) if result != expect { t.Errorf("Add(1, 2) = \"%.1f\", want \"%.1f\"", result, expect) } } |
このテストはパスします。
1 2 3 |
$ go test PASS ok github.com/hoge/arithmetic 0.010s |
expect変数の中身をテストが失敗するように変更しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package arithmetic import ( "testing" ) func TestAdd(t *testing.T) { expect := 5.0 result := Add(1, 2) if result != expect { t.Errorf("Add(1, 2) = \"%.1f\", want \"%.1f\"", result, expect) } } |
テストを実行します。
1 2 3 4 5 6 |
$ go test --- FAIL: TestAdd (0.00s) math_test.go:11: Add(1, 2) = "3.0", want "5.0" FAIL exit status 1 FAIL github.com/hoge/arithmetic 0.010s |
一目でわかりやすいエラーメッセージになりましたね。
ヘルパー関数
テストファイルに記載された関数は、先頭が”Test”になっていなければ、テストコードとは見なされません。
そのため、以下のようにヘルパー関数を実装し、一つ一つの関数の処理を簡潔に書くことが可能になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package arithmetic import ( "fmt" "testing" ) func TestAdd(t *testing.T) { expect := 5.0 result := Add(1, 2) if result != expect { t.Errorf(errorString(result, expect)) } } func errorString(result float64, expect float64) string { return fmt.Sprintf("Add(1, 2) = \"%.1f\", want \"%.1f\"", result, expect) } |
1 2 3 4 5 |
$ go test --- FAIL: TestAdd (0.00s) math_test.go:12: Add(1, 2) = "3.0", want "5.0" FAIL exit status 1 |
テスト関数を指定して実行
go test に vフラグを付与するとテスト名を取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package arithmetic import ( "fmt" "testing" ) func TestAdd(t *testing.T) { expect := 3.0 result := Add(1, 2) if result != expect { t.Errorf(errorString(result, expect)) } } func errorString(result float64, expect float64) string { return fmt.Sprintf("Add(1, 2) = \"%.1f\", want \"%.1f\"", result, expect) } |
1 2 3 4 5 |
$ go test -v === RUN TestAdd --- PASS: TestAdd (0.00s) PASS ok github.com/hoge/arithmetic 0.008s |
テスト関数名の一部を指定してテストを実行するには、runオプションを付与します。
1 2 3 4 5 6 |
$ go test -v -run Add === RUN TestAdd --- PASS: TestAdd (0.00s) PASS ok github.com/hoge/arithmetic 0.009s |
構造体(Struct)を利用する
Structを利用したテストパターンも確認しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package arithmetic import ( "fmt" "testing" ) type testData struct { a float64 b float64 want float64 } func TestAdd(t *testing.T) { tests := []testData{ testData{a: 10.0, b: 40.0, want: 50.0}, testData{a: 20.0, b: 30.0, want: 50.0}, testData{a: 30.0, b: 20.0, want: 50.0}, testData{a: 40.0, b: 10.0, want: 50.0}, } for _, test := range tests { got := Add(test.a, test.b) if got != test.want { t.Errorf(errorString(got, test.want)) } } } func errorString(result float64, expect float64) string { return fmt.Sprintf("Add(1, 2) = \"%.1f\", want \"%.1f\"", result, expect) } |
データパターンをStructに入れてfor文で回してあげれば、大量のテストパターンをテストできますね。
まとめ

最後にこの章で学んだことをまとめます。
・ go testにて、テストコードを実行する
・ テストファイル名は、”XXXX_test.go”とする
・ 必須ではないが、テストファイルはテスト対象ファイルと同一パッケージに配置する
・ テストには、Go言語の組み込みパッケージであるtesingパッケージを利用する
・ テスト関数は、TestXXXX名で開始する
・ エラーメッセージのカスタマイズには、t.Errorf関数を利用する
次回
次回は、Webアプリを作成します。
コメントを残す
コメントを投稿するにはログインしてください。