Communitygithub.com

test-cpp

À utiliser uniquement lors de l'écriture, de la mise à jour ou de la correction de tests C++, de la configuration de GoogleTest/CTest, du diagnostic de tests défaillants ou instables, ou de l'ajout de couverture et de sanitizers.

Qu'est-ce que test-cpp ?

Cette compétence définit un workflow de test pour le C++ moderne (C++17/20) avec GoogleTest/GoogleMock et CMake/CTest, spécifiquement conçu pour les agents d'IA. Elle guide l'agent à travers les étapes d'écriture de nouveaux tests, de correction de tests existants, de configuration de la couverture, et de diagnostic des échecs. La compétence met l'accent sur le cycle TDD (rouge → vert → refactor), l'isolation par injection de dépendances, et la séparation des tests unitaires et d'intégration. Elle fournit des exemples concrets de code (tests unitaires, fixtures, mocks), des configurations CMake/CTest, ainsi que des instructions détaillées pour l'exécution des tests, le débogage des échecs, la couverture de code avec gcov/lcov et llvm-cov, l'activation des sanitizers (ASan, UBSan, TSan), et la gestion des tests instables. La compétence inclut également des bonnes pratiques, des pièges courants, et une annexe optionnelle sur le fuzzing avec libFuzzer et les tests par propriétés avec RapidCheck. Elle s'applique à des projets utilisant GoogleTest avec CMake, quel que soit l'environnement CI.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Tests C++ (Compétence pour Agent)

Workflow de test orienté agent pour le C++ moderne (C++17/20) utilisant GoogleTest/GoogleMock avec CMake/CTest.

Quand utiliser

  • Écrire de nouveaux tests C++ ou corriger des tests existants
  • Concevoir la couverture de tests unitaires/d'intégration pour des composants C++
  • Ajouter de la couverture de test, un gating CI ou une protection contre les régressions
  • Configurer des workflows CMake/CTest pour une exécution cohérente
  • Enquêter sur des échecs de test ou des comportements instables
  • Activer les sanitizers pour le diagnostic mémoire/race

Quand NE PAS utiliser

  • Implémenter de nouvelles fonctionnalités produit sans modifications de test
  • Refontes à grande échelle non liées à la couverture ou aux échecs de test
  • Réglage des performances sans régressions de test à valider
  • Projets non C++ ou tâches non liées aux tests

Concepts clés

  • Boucle TDD : rouge → vert → refactor (tests d'abord, correction minimale, puis nettoyage).
  • Isolation : privilégier l'injection de dépendances et les fakes plutôt que l'état global.
  • Disposition des tests : tests/unit, tests/integration, tests/testdata.
  • Mocks vs fakes : mock pour les interactions, fake pour le comportement avec état.
  • Découverte CTest : utiliser gtest_discover_tests() pour une découverte stable des tests.
  • Signal CI : exécuter d'abord un sous-ensemble, puis la suite complète avec --output-on-failure.

Workflow TDD

Suivez la boucle ROUGE → VERT → REFACTOR :

  1. ROUGE : écrire un test échouant qui capture le nouveau comportement
  2. VERT : implémenter le plus petit changement pour réussir
  3. REFACTOR : nettoyer pendant que les tests restent verts
// tests/add_test.cpp
#include <gtest/gtest.h>

int Add(int a, int b); // Fourni par le code de production.

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

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

// REFACTOR : simplifier/renommer une fois les tests passés

Exemples de code

Test unitaire basique (gtest)

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

int Add(int a, int b); // Fourni par le code de production.

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

Fixture (gtest)

// tests/user_store_test.cpp
// Stub de pseudocode : remplacer UserStore/User par les types du projet.
#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");
}

Mock (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");
}

Démarrage rapide CMake/CTest

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

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
# Privilégier les versions verrouillées par projet. Si une balise est utilisée,
# utiliser une version figée conformément à la politique du projet.
set(GTEST_VERSION v1.17.0) # Ajuster à la politique du projet.
FetchContent_Declare(
  googletest
  # Framework de test Google (dépôt officiel)
  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

Exécuter les tests

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

Déboguer les échecs

  1. Réexécuter le seul test qui échoue avec le filtre gtest.
  2. Ajouter des logs ciblés autour de l'assertion qui échoue.
  3. Réexécuter avec les sanitizers activés.
  4. Étendre à la suite complète une fois la cause racine corrigée.

Couverture

Privilégier les paramètres au niveau de la cible plutôt que les drapeaux globaux.

option(ENABLE_COVERAGE "Activer les drapeaux de couverture" 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

Sanitizers

option(ENABLE_ASAN "Activer AddressSanitizer" OFF)
option(ENABLE_UBSAN "Activer UndefinedBehaviorSanitizer" OFF)
option(ENABLE_TSAN "Activer 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()

Garde-fous pour les tests instables

  • Ne jamais utiliser sleep pour la synchronisation ; utiliser des variables de condition ou des barrières.
  • Rendre les répertoires temporaires uniques par test et toujours les nettoyer.
  • Éviter le temps réel, le réseau ou les dépendances système de fichiers dans les tests unitaires.
  • Utiliser des graines déterministes pour les entrées aléatoires.

Bonnes pratiques

À FAIRE

  • Maintenir les tests déterministes et isolés
  • Privilégier l'injection de dépendances plutôt que les variables globales
  • Utiliser ASSERT_* pour les préconditions, EXPECT_* pour les vérifications multiples
  • Séparer les tests unitaires et d'intégration dans les étiquettes ou répertoires CTest
  • Exécuter les sanitizers dans le CI pour la détection mémoire et de race

À NE PAS FAIRE

  • Ne pas dépendre du temps réel ou du réseau dans les tests unitaires
  • Ne pas utiliser de sleep comme synchronisation quand une variable de condition peut être utilisée
  • Ne pas sur-mocker des objets de valeur simples
  • Ne pas utiliser de correspondance de chaîne fragile pour des logs non critiques

Pièges courants

  • Utilisation de chemins temporaires fixes → Générer des répertoires temporaires uniques par test et les nettoyer.
  • Dépendance à l'horloge murale → Injecter une horloge ou utiliser des sources de temps factices.
  • Tests de concurrence instables → Utiliser des variables de condition/barrières et des attentes bornées.
  • État global caché → Réinitialiser l'état global dans les fixtures ou supprimer les globaux.
  • Sur-mock → Privilégier les fakes pour le comportement avec état et ne mocker que les interactions.
  • Absence d'exécution des sanitizers → Ajouter des builds ASan/UBSan/TSan dans le CI.
  • Couverture sur des builds debug uniquement → S'assurer que les cibles de couverture utilisent des drapeaux cohérents.

Annexe optionnelle : Fuzzing / Tests par propriétés

À utiliser uniquement si le projet supporte déjà LLVM/libFuzzer ou une bibliothèque de tests par propriétés.

  • libFuzzer : meilleur pour les fonctions pures avec un minimum d'E/S.
  • RapidCheck : tests basés sur les propriétés pour valider les invariants.

Harness minimal libFuzzer (pseudocode : remplacer 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); // fonction du projet
    return 0;
}

Alternatives à GoogleTest

  • Catch2 : header-only, matchers expressifs
  • doctest : léger, surcharge de compilation minimale

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.

Skills associés