9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Cでtable-driven testを書く

Posted at

はじめに

Goが推奨するtable-driven testが、Cでも記述できるのに気づきました。

Goのtable-driven test

Goのテストは、table-driven testが推奨されています。テスト対象に与えるデータ入力と期待値のペアを1つのテストケースとして扱い、期待値と実測値の一覧を表のように表します。

たとえばgcd()メソッドのテストをtable-drivenで書くなら、次のようになります。

gcd_test.go
func TestGcd(t *testing.T) {
	cases := []struct {
		a, b int
		z    int
	}{
		{12, 8, 4},
		{3, 7, 1},
	}

	for _, c := range cases {
		if gcd(c.a, c.b) != c.z {
			t.Errorf("expected gcd(%v,%v) == %v\n", c.a, c.b, c.z)
		}
	}

}

Goはstructの定義と変数の初期化を同時に書くことができます。テストケースの初期化はstruct literal syntax{}で、容易かつ型安全に初期化できます。コードはテストデータのみに集中できるので、非常に読みやすいです。

Cのtable-driven test

Cで同じくgcd()のテストをtable-drivenに記述してみました。Cでも構造体宣言と変数の初期化が同時に行えます。そして初期化はstruct literal syntax{}で型安全に行うことができます。

gcd_test.c
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

int test_gcd() {
	struct {
		int a, b;
		int z;
	} cases[] = {
		{12, 8, 4},
		{3, 7, 1},
	};

	for (int i = 0; i < ARRAY_SIZE(cases); ++i) {
		if (gcd(cases[i].a, cases[i].b) != cases[i].z) {
			printf("expected gcd(%d,%d) == %d\n", cases[i].a, cases[i].b, cases[i].z);
		}
	}
}

Goと比較しても、記述量や可読性に大きな差がなく、C言語でtable-driven testを記述できました。

おわりに

Goは簡単なCとよく言われますが、Goの文化をCに輸入するのもよいですね。

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?