GAIO CLUB

2024年07月16日

Google Test 1 – Google Testのカバレッジ計測を試してみた #2

Google Test
Google Testのカバレジ計測を試してみた
前回お話ししたように、Google Testはテストドライバーを作る環境を提供しています。
今回は、Google Testを使ってテストドライバーをどのように書いて動かすのか、見て行こうと思います。
使用しているGoogle Testのバージョンは、1.14.0 です。

アサーション

Google Testではアサーションというマクロを使用してテスト結果の確認を行います。マクロ内にテスト対象関数の呼び出しを記述することも可能です。

アサーションを使うには、コンパイル時にGoogle Testが提供するインクルードファイルgtest.hを使用し、リンク時にはライブラリlibgtestを指定します。

アサーションには多くの種類がありますが、例えば関数を実行して戻り値をチェックするのであれば、以下のように記述することができます。
アサーション
EXPECT_LT(0,function3_2(5));      // 0が、関数function3_2(5)の戻り値未満であることを期待している
このアサーションをテストドライバーに記述します。
異なる引数で同じ関数を複数回呼出して評価することもできます。
戻り値だけでなく、グローバル変数glb3の値も確認する場合は、もう一つアサーションを記述します。
EXPECT_EQ(25,glb3);      // 25 == glb3 であることを期待している

テストドライバー

テストドライバーもGoogle Testが提供するマクロを使って記述します。
TEST(テストケース名, テスト名) { アサーション記述などのテストコード }
テストケース名とテスト名にはC++で有効な識別子を使用可能ですが、アンダースコア(_)は使えません。
先の2つのアサーションを指定するなら、このような記述になります。
TEST(Func32,TEST1) { 
  EXPECT_LT(0,function3_2(5));	// 0が、関数function3_2(5) 戻り値未満であること
  EXPECT_EQ(25,glb3);	// 25 == glb3 になっていること
  }

テスト結果

上記のテストドライバーを使ってテストが正しく終わった時には、以下の出力表示があります。
[----------] 1 test from Func32
[ RUN      ] Func32.TEST1
[       OK ] Func32.TEST1 (0 ms)
[----------] 1 test from Func32 (0 ms total)
もし、EXPECT_EQ(25,glb3)のアサーションが失敗した時は、このようになります(EXPECT_EQ(5,glb3) に変えています)。
[----------] 1 test from Func32
[ RUN      ] Func32.TEST1
sample.cpp:30: Failure
Expected equality of these values:
  5
  glb3
    Which is: 25
	
[  FAILED  ] Func32.TEST1 (0 ms)
[----------] 1 test from Func32 (0 ms total)
赤字にした個所は失敗の情報です。
変数glb3の値に5を期待していたが結果は25だった。ということですね。
そして失敗したのは、sample.cppの30行目に書いたアサーションであることを指しています。
最初のアサーション、EXPECT_LT(0,function3_2(5))が失敗した時はこうなります(function3_2の引数を変えています)。
[----------] 1 test from Func32
[ RUN      ] Func32.TEST1
sample.cpp:35: Failure
Expected: (0) < (function3_2(-5)), actual: 0 vs 0

[  FAILED  ] Func32.TEST1 (0 ms)
[----------] 1 test from Func32 (0 ms total)
赤字の部分では、function3_2(-5)の戻り値が0以上になることを期待していたが、0だったことを示しています。

アサーションマクロにはEXPECT_EQ(expected, actual) のように期待値を書く位置を指定しているものがあります。テスト失敗時のメッセージはこの順序を想定したメッセージになっているので、使用時にはマニュアルを確認し、合わせておいた方が良いでしょう。

テストの実行

本コラムで使ったソースをお見せします。
テストターゲット関数にはあまり意味がありません。
同一テストケース内に同じテスト名を使用できないので、テスト名を変えています。
#include <gtest/gtest.h>
int glb3;
// Test Target : function3_2	// テストターゲット関数
int function3_2(int a){
    if ( a > 0 )
    {
       glb3 = a*a;
       return a;
    }
    else
       return 0;
}
int main(int argc, char **argv)	// main関数
{
    // Initialize for Google Test
    ::testing::InitGoogleTest(&argc, argv);	// コマンドフラグを使用することができる
    // Test All
    return RUN_ALL_TESTS();	// 全てのテストが動作する
}

// Test for OK 
TEST(Func32, TEST1){	// テストケース名(Func32):テスト名(TEST1)
    EXPECT_LT(0, function3_2(5));
    EXPECT_EQ(5*5, glb3);
}

// Test for NG 1
TEST(Func32, TEST2){ 	// テストケース名(Func32):テスト名(TEST2)
    EXPECT_LT(0, function3_2(5));
    EXPECT_EQ(5, glb3);
}

// Test for NG 2
TEST(Func32, TEST3){ 	// テストケース名(Func32):テスト名(TEST3)
    EXPECT_LT(0, function3_2(-5));
    EXPECT_EQ(5*5, glb3);
}
RUN_ALL_TESTS()により、全てのテストが動作します(リンクされたバイナリ内の全テスト)。
main関数がありますが、無くても構いません。
libgtestに加えてlibgtest_mainライブラリもリンクすれば、libgtest_main内のmainが有効になります。
テストターゲットとドライバーを同じファイルに書く必要はありません。

このソースプログラムをコンパイルして実行すればテストが動きます。実行結果は以下の通りです。
[==========] Running 3 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 3 tests from Func32
[ RUN      ] Func32.TEST1
[       OK ] Func32.TEST1 (0 ms)
[ RUN      ] Func32.TEST2
sample.cpp:30: Failure
Expected equality of these values:
  5
  glb3
    Which is: 25

[  FAILED  ] Func32.TEST2 (0 ms)
[ RUN      ] Func32.TEST3
sample.cpp:35: Failure
Expected: (0) < (function3_2(-5)), actual: 0 vs 0

[  FAILED  ] Func32.TEST3 (0 ms)
[----------] 3 tests from Func32 (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 2 tests, listed below:
[  FAILED  ] Func32.TEST2
[  FAILED  ] Func32.TEST3

 2 FAILED TESTS
赤字にした部分を見ると、3つのテストのうち、2つが失敗していることがわかります。

Google Test資産を活かした車載品質テストの効率化を実現
「QTE(Quality Town for Embedded grade)」

「QTE」は、ユーザ環境で作成したGoogleTest資産を活用し、機能安全(ISO 26262)で求められるマイコンターゲットオブジェクト実行とカバレッジ計測が可能です。また、テストエビデンス及びレポートを自動出力し、テストエビデンスの作成も効率化します。

筆者紹介

浅野 昌尚(あさの まさなお)

ガイオ・テクノロジー株式会社

開発1部 QTXグループ

1980年代から30年以上にわたり汎用構造のCコンパイラ開発に従事し、その間に8ビットマイコンからRISC・VLIW・画像処理プロセッサまで、さまざまなCPU向けのクロスCコンパイラを開発。

人気のコラム

最新のコラム