単体テストの効率化を考える(17)
テストドライバを実装してみる
(シングルポインタの場合)

どもです。

久しぶりの「単体テストの効率化」シリーズのエントリです。

だいぶ前の投稿ですが、テストドライバを実装してみるというエントリを書きました。
このエントリで例として取り上げたテスト対象関数は、引数の型が全て非ポインタでした。
そこで今回は、引数にポインタを持つテスト対象関数のテストドライバの実装を考えてみます。

1. 単体テストの環境

今回のエントリでは、以下の環境で作業を行います。

単体テストの実行環境
項目 内容
OS Windows10 Pro(22H2)
CPU i7-8700
メモリ 16GB
IDE Visual Studio Commnuity 2022
version 17.3.6
テストフレームワーク google test
(今回のエントリではバージョンは影響なし)

2. 引数にポインタを持つ関数のテストドライバ 其の1

まず、以下のような関数について考えます。

int sample_function(int* arg) {
	int ret_val = 0;
	if (NULL == arg) {
		ret_val = -1;
	}
	else {
		ret_val = (*arg) * (*arg);
	}

	return ret_val;
}

C言語標準のPOW()関数を、仰々しくした関数になります。

この関数をテストする際のテストドライバは、以下のように書くことができます。

void test_driver()
{
	int arg = 10;
	int result = sample_function(&arg);

	ASSERT_EQ(100, result);
}

また、異常系のテストとして引数が「NULL」の場合には、テストドライバは以下のように書けます。

void test_driver()
{
	int result = sample_function(NULL);

	ASSERT_EQ(-1, result);
}

これらのテストドライバの実装は、それぞれ確認したい内容がテストできているため、適切であると考えます。

3. 引数にポインタを持つ関数のテストドライバ 其の2

次に、以下のようにポインタの指す先が配列になっている関数について考えます。

int sample_function(int* arg) {
	int ret_val = 0;
	if (NULL == arg) {
		ret_val = -1;
	}
	else {
		ret_val = (*arg)
			* (*arg + 1)
			* (*arg + 2)
			* (*arg + 3);
	}

	return ret_val;
}

引数で指定されたポインタの指す領域4つ分の領域に格納された値の積を求める関数になります。

この関数をテストする際のテストドライバは、例えば以下のように書くことができます。

void test_driver()
{
    int arg2[] = { 1, 2, 3, 4 };
    result = sample_function(arg2);

	ASSERT_EQ(24, result);
}

引数にNULLが指定された場合のテストについては、先述のコードと同じなので省略します。

其の1のテストドライバの比較して、関数へ引数を渡す際のコードが少し違っていることが分かります。
これはC言語のポインタ、配列を理解していれば違和感のない実装かと思います。

3. 引数にポインタを持つ関数のテストドライバ 其の3

最後に、テスト対象関数の中でポインタが指す領域(実体)の内容を書き換える場合を考えます。
具体的なコードは、以下の通りです。

int sample_function(int* arg) {
	int ret_val = 0;
	if (NULL == arg) {
		ret_val = -1;
	}
	else {
		*arg = 1;
		*(arg + 1) = 2;
		*(arg + 2) = 3;
		*(arg + 3) = 4;

		ret_val = 0;
	}
	return ret_val;
}

引数で指定された領域の4つ分の領域に対して、1~4の値を先頭から順番に設定します。

関数の内容もポインタの実体を書き換える処理もテキトーすぎますが、そこはご容赦ください。

そして、この関数のテストドライバ、以下のように書くことができます。

void test_driver()
{
    int arg2[] = { 0 };
    result = sample_function(arg2);

	ASSERT_EQ(0, result);
	ASSERT_EQ(1, arg[0]);
	ASSERT_EQ(2, arg[1]);
	ASSERT_EQ(3, arg[2]);
	ASSERT_EQ(4, arg[3]);
}

前のテストドライバと異なるのは、ポインタの実体、配列の初期値、および確認する内容です。
それ以外は、同じです。

4. まとめ

今回のエントリでは、引数にシングルポインタを持つ関数のテストドライバの書き方について書きました。
基本的には今回挙げたように、

  • ポインタが配列ではない場合は、関数に渡す変数の前に「&」を付与する。

    sample_function(&arg);
  • ポインタが配列の場合には、変数をそのまま渡す。

    sample_function(arg);

と書くのが良いかと思います。

ではっ!