GoogleTest / Catch2 入門 — C++ ユニットテスト
C++ のユニットテストは GoogleTest(GTest) と Catch2 が事実上の双璧。GTest は Google 製で豊富な機能、Catch2 はヘッダオンリーで気軽。タブで切り替えながら両方の最短入門を。
GT-1. 最小テスト
math_test.cpp
#include <gtest/gtest.h>
#include "math.h"
TEST(MathTest, Add) {
EXPECT_EQ(add(2, 3), 5);
EXPECT_EQ(add(-1, 1), 0);
}
TEST(MathTest, DivZero) {
EXPECT_THROW(divide(1, 0), std::invalid_argument);
}
// main は不要。GTest 側が提供。
GT-2. 主要マクロ
| マクロ | 意味 |
EXPECT_EQ(a,b) | a==b(失敗しても続行) |
ASSERT_EQ(a,b) | a==b(失敗で即中断) |
EXPECT_TRUE(x) / EXPECT_FALSE(x) | boolean |
EXPECT_NEAR(a,b,e) | 浮動小数の誤差許容 |
EXPECT_THROW(expr, T) | 例外 T を投げるか |
EXPECT_NO_THROW(expr) | 投げないこと |
GT-3. CMake で入れる(FetchContent)
CMakeLists.txt
include(FetchContent)
FetchContent_Declare(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0)
FetchContent_MakeAvailable(googletest)
enable_testing()
add_executable(math_test math_test.cpp math.cpp)
target_link_libraries(math_test PRIVATE GTest::gtest_main)
include(GoogleTest)
gtest_discover_tests(math_test)
$ cmake -S . -B build && cmake --build build
$ ctest --test-dir build --output-on-failure
GT-4. Fixture(共通セットアップ)
fixture.cpp
class DbTest : public ::testing::Test {
protected:
void SetUp() override { db.connect("test"); }
void TearDown() override { db.close(); }
Database db;
};
TEST_F(DbTest, Insert) {
db.insert("alice");
EXPECT_EQ(db.count(), 1);
}
GT-5. GMock でモック
mock.cpp
#include <gmock/gmock.h>
class MockDb : public IDatabase {
public:
MOCK_METHOD(bool, insert, (std::string), (override));
MOCK_METHOD(int, count, (), (const, override));
};
using ::testing::Return;
using ::testing::_;
TEST(Service, HandlesDbFail) {
MockDb m;
EXPECT_CALL(m, insert(_)).WillOnce(Return(false));
UserService svc(m);
EXPECT_FALSE(svc.register_user("alice"));
}
C2-1. 最小テスト
math_test.cpp
#define CATCH_CONFIG_MAIN
#include <catch2/catch_test_macros.hpp>
#include "math.h"
TEST_CASE("add works", "[math]") {
REQUIRE(add(2, 3) == 5);
REQUIRE(add(-1, 1) == 0);
}
TEST_CASE("divide by zero") {
REQUIRE_THROWS_AS(divide(1, 0), std::invalid_argument);
}
C2-2. 主要マクロ
| マクロ | 意味 |
REQUIRE(expr) | 条件満たさなければ中断 |
CHECK(expr) | 条件満たさなくても継続 |
REQUIRE_THROWS_AS(e, T) | T を投げるか |
REQUIRE_THAT(v, Matcher) | matcher を使った柔軟な比較 |
SECTION(name) | テスト内のサブケース |
SECTION — BDD スタイル
section.cpp
TEST_CASE("vector basic") {
std::vector<int> v{1,2,3};
SECTION("size is 3") { REQUIRE(v.size() == 3); }
SECTION("push_back") {
v.push_back(4);
REQUIRE(v.back() == 4);
}
}
// SECTION ごとに v が再初期化される
C2-3. CMake で入れる
CMakeLists.txt
include(FetchContent)
FetchContent_Declare(Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.5.2)
FetchContent_MakeAvailable(Catch2)
add_executable(tests math_test.cpp)
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)
include(CTest)
include(Catch)
catch_discover_tests(tests)
どちらを選ぶか?
| GoogleTest | Catch2 |
| 導入 | CMake 経由 | ヘッダオンリー可 |
| モック | GMock 同梱 | trompeloeil などを追加 |
| 学習コスト | やや多い | 少ない |
| パラメータ化 | ◎ 機能豊富 | ◯ GENERATE |
| 出力 | 標準的 | 色付きで見やすい |
判断基準: 「Google 系エコシステム(gRPC, protobuf, abseil)」なら GTest、小規模・個人プロジェクト・BDD 志向なら Catch2。どちらも十分実用的。