Series: go-testing
Tags: Go Golang

Go でテストを書いてみる サブテスト編

Go の testing パッケージでサブテストを書いてみる。

開発環境

  • go version go1.16.5 linux/amd64

本文

前回 の続きでサブテストを書いてみる。

リファレンス: 公式ドキュメント

公式ドキュメントに書いてある通り

func TestFoo(t *testing.T) {
    // <setup code>
    t.Run("A=1", func(t *testing.T) { ... })
    t.Run("A=2", func(t *testing.T) { ... })
    t.Run("B=1", func(t *testing.T) { ... })
    // <tear-down code>
}

というように書くとサブテストを定義することができる。

前回のサンプルにした禁則処理のコードだが、行末禁則文字と分離禁則文字も考慮するようにしたのでサブテストを用いてテストを書き直してみた。

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package kinsoku

import (
	"reflect"
	"strings"
	"testing"
)

type tcase struct {
	in   string
	want []string
}

func TestExecKinsoku(t *testing.T) {
	width := 10

	t.Run("行頭禁則文字", func(t *testing.T) {
		cases := []tcase{
			{
				in:   "あいうえお、かきくけこ。",
				want: []string{"あいうえ", "お、かきく", "けこ。"},
			},
			{
				in:   "あお、〕:,゠ㇷ!.。かきくけこ",
				want: []string{"あ", "お、〕:,゠", "ㇷ!.。かき", "くけこ"},
			},
		}

		assertKinsoku(t, width, cases)
	})
	t.Run("行末禁則文字", func(t *testing.T) {
		cases := []tcase{
			{
				in:   "「はい」「いいえ」",
				want: []string{"「はい」", "「いいえ」"},
			},
			{
				in:   "あお([{〔“〘«《かきくけこ",
				want: []string{"あお(", "[{〔“〘«", "《かきくけ", "こ"},
			},
		}

		assertKinsoku(t, width, cases)
	})
	t.Run("分離禁則文字", func(t *testing.T) {
		cases := []tcase{
			{
				in:   "人口は約125,36万人",
				want: []string{"人口は約", "125,36万人"},
			},
			{
				in:   "Lorem ipsum dolor sit amet",
				want: []string{"Lorem ", "ipsum ", "dolor sit ", "amet"},
			},
		}

		assertKinsoku(t, width, cases)
	})
}

func assertKinsoku(t *testing.T, width int, cases []tcase) {
	for _, c := range cases {
		got := ExecKinsoku(width, c.in)
		if !reflect.DeepEqual(got, c.want) {
			t.Errorf("got:\n%v\n\nwant:\n%v", strings.Join(got[:], "\n"), strings.Join(c.want[:], "\n"))
		}
	}
}

わかりやすいように詳細な出力をしながら実行してみる。

全テスト実行

$ go test ./internal/pkg/kinsoku/ -run '' -v
=== RUN   TestExecKinsoku
=== RUN   TestExecKinsoku/行頭禁則文字
=== RUN   TestExecKinsoku/行末禁則文字
=== RUN   TestExecKinsoku/分離禁則文字
--- PASS: TestExecKinsoku (0.00s)
    --- PASS: TestExecKinsoku/行頭禁則文字 (0.00s)
    --- PASS: TestExecKinsoku/行末禁則文字 (0.00s)
    --- PASS: TestExecKinsoku/分離禁則文字 (0.00s)
PASS
ok      github.com/k1350/ogpgen/internal/pkg/kinsoku    0.002s

Foo とつく関数のテストを実行(今回はそのようなテストは無いので何も実行しない)

$ go test ./internal/pkg/kinsoku/ -run 'Foo' -v
testing: warning: no tests to run
PASS
ok      github.com/k1350/ogpgen/internal/pkg/kinsoku    0.002s [no tests to run]

ExecKinsoku とつく関数の「行」とつくサブテストを実行

$ go test ./internal/pkg/kinsoku/ -run 'ExecKinsoku/行' -v
=== RUN   TestExecKinsoku
=== RUN   TestExecKinsoku/行頭禁則文字
=== RUN   TestExecKinsoku/行末禁則文字
--- PASS: TestExecKinsoku (0.00s)
    --- PASS: TestExecKinsoku/行頭禁則文字 (0.00s)
    --- PASS: TestExecKinsoku/行末禁則文字 (0.00s)
PASS
ok      github.com/k1350/ogpgen/internal/pkg/kinsoku    0.002s

ExecKinsoku とつく関数の「行頭禁則文字」とつくサブテストを実行

$ go test ./internal/pkg/kinsoku/ -run 'ExecKinsoku/行頭禁則文字' -v
=== RUN   TestExecKinsoku
=== RUN   TestExecKinsoku/行頭禁則文字
--- PASS: TestExecKinsoku (0.00s)
    --- PASS: TestExecKinsoku/行頭禁則文字 (0.00s)
PASS
ok      github.com/k1350/ogpgen/internal/pkg/kinsoku    0.002s

感想

ベンチマークを書いたりしないのなら大体もう事足りると思うのだが、モックやスタブをどうするかが testing パッケージの公式ドキュメントからは読み取れないので気になっている。

ただ今作っている物は DB に接続することもないので、今後書く必要に迫られたときに調べることにする。