Communitygithub.com

C++ テスト

C++のテスト作成・修正、GoogleTest/CTestの設定、失敗・flakyテストの診断、カバレッジ・サニタイザの追加時にのみ使用します。

C++ テスト とは?

このスキルは、エージェントが最新のC++(C++17/20)プロジェクトでテスト中心のワークフローを効率的に実行するためのものです。特に、GoogleTestとGoogleMockを用いた単体テスト、統合テストの設計と実装、CMake/CTestによるビルド・テスト実行の設定、テストカバレッジの計測、AddressSanitizerやUndefinedBehaviorSanitizerなどのサニタイザの有効化、そしてflakyテストの診断・修正に役立ちます。TDD(Red-Green-Refactor)のサイクルに従い、依存性注入とモック/フェイクを活用してテストの独立性を保ちます。CIでのゲートや回帰テストの自動化もサポートしており、テストの信頼性と保守性を向上させます。また、libFuzzerやRapidCheckを使ったファジング・プロパティテストのオプションも提供します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/cpp-testing

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

C++ テスト (エージェントスキル)

GoogleTest/GoogleMockとCMake/CTestを使用した、最新C++(C++17/20)向けのエージェント指向テストワークフロー。

使用すべきケース

  • 新しいC++テストの作成、または既存テストの修正
  • C++コンポーネントに対する単体テスト・統合テストの設計
  • テストカバレッジ、CIゲート、回帰テストの追加
  • 一貫した実行のためのCMake/CTestワークフローの設定
  • テスト失敗やflaky動作の調査
  • メモリ/競合診断のためのサニタイザの有効化

使用すべきでないケース

  • テスト変更を伴わない新機能の実装
  • テストカバレッジや失敗に関係のない大規模リファクタリング
  • テスト回帰検証がないパフォーマンスチューニング
  • C++以外のプロジェクト、またはテスト以外のタスク

コアコンセプト

  • TDDループ: レッド→グリーン→リファクタ(最初にテスト、最小限の修正、クリーンアップ)。
  • 分離: グローバル状態よりも依存性注入とフェイクを優先。
  • テスト配置: tests/unit、tests/integration、tests/testdata。
  • モックvsフェイク: 相互作用はモック、状態動作はフェイクを使用。
  • CTestディスカバリ: gtest_discover_tests()を使用して安定したテストディスカバリ。
  • CIシグナル: 最初にサブセットを実行し、その後--output-on-failureを付けてフルスイートを実行。

TDDワークフロー

RED→GREEN→REFACTORループに従います:

  1. RED: 新しい動作を捉える失敗テストを書く
  2. GREEN: 合格するための最小限の変更を実装
  3. REFACTOR: テストがグリーンのままクリーンアップ
// tests/add_test.cpp
#include <gtest/gtest.h>

int Add(int a, int b); // Provided by production code.

TEST(AddTest, AddsTwoNumbers) { // RED
  EXPECT_EQ(Add(2, 3), 5);
}

// src/add.cpp
int Add(int a, int b) { // GREEN
  return a + b;
}

// REFACTOR: simplify/rename once tests pass

コード例

基本的な単体テスト(gtest)

// tests/calculator_test.cpp
#include <gtest/gtest.h>

int Add(int a, int b); // Provided by production code.

TEST(CalculatorTest, AddsTwoNumbers) {
    EXPECT_EQ(Add(2, 3), 5);
}

フィクスチャ(gtest)

// tests/user_store_test.cpp
// Pseudocode stub: replace UserStore/User with project types.
#include <gtest/gtest.h>
#include <memory>
#include <optional>
#include <string>

struct User { std::string name; };
class UserStore {
public:
    explicit UserStore(std::string /*path*/) {}
    void Seed(std::initializer_list<User> /*users*/) {}
    std::optional<User> Find(const std::string &/*name*/) { return User{"alice"}; }
};

class UserStoreTest : public ::testing::Test {
protected:
    void SetUp() override {
        store = std::make_unique<UserStore>(":memory:");
        store->Seed({{"alice"}, {"bob"}});
    }

    std::unique_ptr<UserStore> store;
};

TEST_F(UserStoreTest, FindsExistingUser) {
    auto user = store->Find("alice");
    ASSERT_TRUE(user.has_value());
    EXPECT_EQ(user->name, "alice");
}

モック(gmock)

// tests/notifier_test.cpp
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>

class Notifier {
public:
    virtual ~Notifier() = default;
    virtual void Send(const std::string &message) = 0;
};

class MockNotifier : public Notifier {
public:
    MOCK_METHOD(void, Send, (const std::string &message), (override));
};

class Service {
public:
    explicit Service(Notifier &notifier) : notifier_(notifier) {}
    void Publish(const std::string &message) { notifier_.Send(message); }

private:
    Notifier &notifier_;
};

TEST(ServiceTest, SendsNotifications) {
    MockNotifier notifier;
    Service service(notifier);

    EXPECT_CALL(notifier, Send("hello")).Times(1);
    service.Publish("hello");
}

CMake/CTest クイックスタート

# CMakeLists.txt (excerpt)
cmake_minimum_required(VERSION 3.20)
project(example LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
# Prefer project-locked versions. If using a tag, use a pinned version per project policy.
set(GTEST_VERSION v1.17.0) # Adjust to project policy.
FetchContent_Declare(
  googletest
  # Google Test framework (official repository)
  URL https://github.com/google/googletest/archive/refs/tags/${GTEST_VERSION}.zip
)
FetchContent_MakeAvailable(googletest)

add_executable(example_tests
  tests/calculator_test.cpp
  src/calculator.cpp
)
target_link_libraries(example_tests GTest::gtest GTest::gmock GTest::gtest_main)

enable_testing()
include(GoogleTest)
gtest_discover_tests(example_tests)
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j
ctest --test-dir build --output-on-failure

テストの実行

ctest --test-dir build --output-on-failure
ctest --test-dir build -R ClampTest
ctest --test-dir build -R "UserStoreTest.*" --output-on-failure
./build/example_tests --gtest_filter=ClampTest.*
./build/example_tests --gtest_filter=UserStoreTest.FindsExistingUser

失敗のデバッグ

  1. gtestフィルタで単一の失敗テストを再実行します。
  2. 失敗しているアサーションの周囲にスコープ付きログを追加します。
  3. サニタイザを有効にして再実行します。
  4. 根本原因が修正されたら、フルスイートに拡張します。

カバレッジ

グローバルフラグではなく、ターゲットレベルの設定を推奨します。

option(ENABLE_COVERAGE "Enable coverage flags" OFF)

if(ENABLE_COVERAGE)
  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
    target_compile_options(example_tests PRIVATE --coverage)
    target_link_options(example_tests PRIVATE --coverage)
  elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    target_compile_options(example_tests PRIVATE -fprofile-instr-generate -fcoverage-mapping)
    target_link_options(example_tests PRIVATE -fprofile-instr-generate)
  endif()
endif()

GCC + gcov + lcov:

cmake -S . -B build-cov -DENABLE_COVERAGE=ON
cmake --build build-cov -j
ctest --test-dir build-cov
lcov --capture --directory build-cov --output-file coverage.info
lcov --remove coverage.info '/usr/*' --output-file coverage.info
genhtml coverage.info --output-directory coverage

Clang + llvm-cov:

cmake -S . -B build-llvm -DENABLE_COVERAGE=ON -DCMAKE_CXX_COMPILER=clang++
cmake --build build-llvm -j
LLVM_PROFILE_FILE="build-llvm/default.profraw" ctest --test-dir build-llvm
llvm-profdata merge -sparse build-llvm/default.profraw -o build-llvm/default.profdata
llvm-cov report build-llvm/example_tests -instr-profile=build-llvm/default.profdata

サニタイザ

option(ENABLE_ASAN "Enable AddressSanitizer" OFF)
option(ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer" OFF)
option(ENABLE_TSAN "Enable ThreadSanitizer" OFF)

if(ENABLE_ASAN)
  add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
  add_link_options(-fsanitize=address)
endif()
if(ENABLE_UBSAN)
  add_compile_options(-fsanitize=undefined -fno-omit-frame-pointer)
  add_link_options(-fsanitize=undefined)
endif()
if(ENABLE_TSAN)
  add_compile_options(-fsanitize=thread)
  add_link_options(-fsanitize=thread)
endif()

Flakyテストのガードレール

  • 同期にsleepを決して使用しない。条件変数またはラッチを使用すること。
  • テストごとに一時ディレクトリを一意にし、常にクリーンアップすること。
  • 単体テストでは、実時間、ネットワーク、ファイルシステムへの依存を避けること。
  • ランダム入力には決定論的なシードを使用すること。

ベストプラクティス

すべきこと

  • テストを決定論的かつ分離して維持する
  • グローバルよりも依存性注入を優先する
  • 前提条件にはASSERT_*を、複数チェックにはEXPECT_*を使用する
  • 単体テストと統合テストをCTestラベルまたはディレクトリで分離する
  • CIでサニタイザを実行してメモリと競合を検出する

すべきでないこと

  • 単体テストで実時間やネットワークに依存しない
  • 条件変数が使える場合にスリープを同期に使用しない
  • 単純な値オブジェクトを過剰にモックしない
  • 重要でないログに対して脆弱な文字列マッチングを使用しない

よくある落とし穴

  • 固定の一時パスを使用する → テストごとに一意の一時ディレクトリを生成し、クリーンアップする。
  • 実時間に依存する → クロックを注入するか、疑似時刻ソースを使用する。
  • Flakyな並行テスト → 条件変数/ラッチと制限付き待機を使用する。
  • 隠れたグローバル状態 → フィクスチャでグローバル状態をリセットするか、グローバルを削除する。
  • 過剰なモック → 状態動作にはフェイクを優先し、相互作用のみをモックする。
  • サニタイザ実行の欠落 → CIにASan/UBSan/TSanビルドを追加する。
  • デバッグ専用ビルドのカバレッジ → カバレッジターゲットが一貫したフラグを使用することを確認する。

オプション付録: ファジング / プロパティテスト

プロジェクトがすでにLLVM/libFuzzerまたはプロパティテストライブラリをサポートしている場合のみ使用します。

  • libFuzzer: I/Oが最小限の純粋関数に最適。
  • RapidCheck: 不変条件を検証するプロパティベースのテスト。

最小限のlibFuzzerハーネス(疑似コード: ParseConfigをプロジェクトのものに置き換え):

#include <cstddef>
#include <cstdint>
#include <string>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    std::string input(reinterpret_cast<const char *>(data), size);
    // ParseConfig(input); // project function
    return 0;
}

GoogleTestの代替

  • Catch2: ヘッダのみ、表現力豊かなマッチャ
  • doctest: 軽量、最小限のコンパイルオーバーヘッド

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

関連スキル