Communitygithub.com

testing-cpp

Utilizar únicamente al escribir, actualizar, corregir pruebas C++, configurar GoogleTest/CTest, diagnosticar fallos o pruebas inestables, o añadir cobertura/sanitizadores.

¿Qué es testing-cpp?

Esta habilidad proporciona un flujo de trabajo de pruebas completo para C++ moderno (C++17/20) utilizando GoogleTest/GoogleMock con CMake/CTest. Es útil para desarrolladores que necesitan escribir pruebas unitarias y de integración, configurar procesos de construcción y ejecución de pruebas, diagnosticar fallos o pruebas inestables (flaky), y habilitar sanitizadores de memoria y carreras. Soporta las plataformas de agente populares (Claude Code, Cursor, Codex) y se basa en un flujo TDD (rojo → verde → refactorizar). Incluye ejemplos detallados de código C++ con pruebas, fixtures, mocks, configuración de CMake/CTest, cobertura y sanitizadores. La guía también cubre prácticas recomendadas, trampas comunes y alternativas como Catch2 o doctest.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Pruebas C++ (Habilidad de Agente)

Flujo de trabajo de pruebas orientado a agentes para C++ moderno (C++17/20) usando GoogleTest/GoogleMock con CMake/CTest.

Cuándo Usar

  • Escribir nuevas pruebas C++ o corregir pruebas existentes
  • Diseñar cobertura de pruebas unitarias/integración para componentes C++
  • Añadir cobertura de pruebas, compuertas de CI o protección contra regresiones
  • Configurar flujos de trabajo de CMake/CTest para una ejecución consistente
  • Investigar fallos de pruebas o comportamiento inestable (flaky)
  • Habilitar sanitizadores para diagnósticos de memoria/carreras

Cuándo NO Usar

  • Implementar nuevas funcionalidades sin cambios en las pruebas
  • Refactorizaciones a gran escala no relacionadas con cobertura o fallos de pruebas
  • Ajustes de rendimiento sin regresiones de prueba que validar
  • Proyectos no C++ o tareas que no sean de pruebas

Conceptos Clave

  • Bucle TDD: rojo → verde → refactorizar (primero pruebas, corrección mínima, luego limpieza).
  • Aislamiento: preferir inyección de dependencias y simulaciones ligeras (fakes) sobre estado global.
  • Estructura de pruebas: tests/unit, tests/integration, tests/testdata.
  • Mocks vs fakes: mock para interacciones, fake para comportamiento con estado.
  • Descubrimiento CTest: usar gtest_discover_tests() para un descubrimiento estable de pruebas.
  • Señal de CI: ejecutar un subconjunto primero, luego la suite completa con --output-on-failure.

Flujo de Trabajo TDD

Sigue el bucle ROJO → VERDE → REFACTORIZAR:

  1. ROJO: escribe una prueba que falle y capture el nuevo comportamiento
  2. VERDE: implementa el cambio más pequeño para que pase
  3. REFACTORIZAR: limpia mientras las pruebas siguen en verde
// tests/add_test.cpp
#include <gtest/gtest.h>

int Add(int a, int b); // Proporcionado por el código de producción.

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

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

// REFACTORIZAR: simplificar/renombrar una vez que las pruebas pasen

Ejemplos de Código

Prueba Unitaria Básica (gtest)

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

int Add(int a, int b); // Proporcionado por el código de producción.

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

Fixture (gtest)

// tests/user_store_test.cpp
// Pseudocódigo de ejemplo: reemplazar UserStore/User con tipos del proyecto.
#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");
}

Inicio Rápido con CMake/CTest

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

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
# Preferir versiones bloqueadas del proyecto. Si se usa una etiqueta, usar una versión fija según la política del proyecto.
set(GTEST_VERSION v1.17.0) # Ajustar a la política del proyecto.
FetchContent_Declare(
  googletest
  # Google Test framework (repositorio oficial)
  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

Ejecutar Pruebas

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

Depurar Fallos

  1. Vuelve a ejecutar la prueba individual que falla con el filtro de gtest.
  2. Añade registros (logging) localizados alrededor de la aserción que falla.
  3. Vuelve a ejecutar con sanitizadores habilitados.
  4. Expande a la suite completa una vez que se corrija la causa raíz.

Cobertura

Preferir configuraciones a nivel de objetivo en lugar de banderas globales.

option(ENABLE_COVERAGE "Habilitar banderas de cobertura" 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

Sanitizadores

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

Barreras para Pruebas Inestables (Flaky)

  • Nunca usar sleep para sincronización; usar variables de condición o cerrojos (latches).
  • Hacer que los directorios temporales sean únicos por prueba y siempre limpiarlos.
  • Evitar tiempo real, red o dependencias del sistema de archivos en pruebas unitarias.
  • Usar semillas deterministas para entradas aleatorias.

Mejores Prácticas

HACER

  • Mantener las pruebas deterministas y aisladas
  • Preferir inyección de dependencias sobre variables globales
  • Usar ASSERT_* para precondiciones, EXPECT_* para múltiples verificaciones
  • Separar pruebas unitarias vs. integración en etiquetas o directorios de CTest
  • Ejecutar sanitizadores en CI para detección de memoria y carreras

NO HACER

  • No depender de tiempo real o red en pruebas unitarias
  • No usar sleeps como sincronización cuando se pueda usar una variable de condición
  • No hacer mock en exceso para objetos de valor simples
  • No usar comparaciones de cadenas frágiles para registros no críticos

Errores Comunes

  • Usar rutas temporales fijas → Generar directorios temporales únicos por prueba y limpiarlos.
  • Confiar en el tiempo de reloj de pared → Inyectar un reloj o usar fuentes de tiempo falsas.
  • Pruebas de concurrencia inestables → Usar variables de condición/cerrojos y esperas acotadas.
  • Estado global oculto → Restablecer el estado global en fixtures o eliminar variables globales.
  • Exceso de mocks → Preferir fakes para comportamiento con estado y solo mockear interacciones.
  • Ejecuciones faltantes de sanitizadores → Añadir compilaciones con ASan/UBSan/TSan en CI.
  • Cobertura solo en compilaciones de depuración → Asegurar que los objetivos de cobertura usen banderas consistentes.

Apéndice Opcional: Fuzzing / Pruebas de Propiedades

Usar solo si el proyecto ya admite LLVM/libFuzzer o una biblioteca de pruebas de propiedades.

  • libFuzzer: mejor para funciones puras con E/S mínima.
  • RapidCheck: pruebas basadas en propiedades para validar invariantes.

Arnés mínimo de libFuzzer (pseudocódigo: reemplazar 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); // función del proyecto
    return 0;
}

Alternativas a GoogleTest

  • Catch2: solo cabeceras, comparadores expresivos
  • doctest: ligero, sobrecarga de compilación mínima

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 relacionados