Communitygithub.com

Pruebas de C++

Úselo únicamente al escribir, actualizar o corregir pruebas de C++, configurar GoogleTest/CTest, diagnosticar pruebas fallidas o inestables, o agregar cobertura/sanitizadores.

¿Qué es Pruebas de C++?

Este skill proporciona un flujo de trabajo de pruebas orientado a agentes para C++ moderno (C++17/20) utilizando GoogleTest/GoogleMock con CMake/CTest. Es útil cuando se escriben nuevas pruebas, se corrigen pruebas existentes, se diseña cobertura de pruebas unitarias/de integración, se configura la ejecución de pruebas con CMake/CTest, se investigan fallos o pruebas inestables, o se habilitan sanitizadores (ASan, UBSan, TSan) para diagnóstico de memoria/condiciones de carrera. El skill enfatiza el ciclo TDD (rojo → verde → refactorizar), el aislamiento mediante inyección de dependencias, la separación de pruebas unitarias y de integración, y el uso de mocks (GoogleMock) para verificar interacciones. También incluye configuraciones de cobertura (gcov/lcov para GCC, llvm-cov para Clang), guardarraíles para pruebas inestables y un apéndice opcional sobre fuzzing con libFuzzer. Funciona con cualquier proyecto C++ que use CMake y GoogleTest, y asume que el agente tiene acceso al sistema de archivos y al intérprete de comandos para ejecutar CMake, compilar y lanzar ctest.

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

Preguntar en tu IA favorita

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

Documentación

Pruebas de C++ (Skill para Agente)

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

Cuándo Usarlo

  • Escribir nuevas pruebas de C++ o corregir pruebas existentes
  • Diseñar cobertura de pruebas unitarias/integración para componentes C++
  • Agregar cobertura de pruebas, puertas CI o protección contra regresiones
  • Configurar flujos de trabajo CMake/CTest para ejecución consistente
  • Investigar fallos de pruebas o comportamiento inestable
  • Habilitar sanitizadores para diagnóstico de memoria/condiciones de carrera

Cuándo NO Usarlo

  • Implementar nuevas características del producto sin cambios en las pruebas
  • Refactorizaciones a gran escala no relacionadas con cobertura o fallos
  • Ajustes de rendimiento sin regresiones de prueba que validar
  • Proyectos que no son C++ o tareas que no son de prueba

Conceptos Clave

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

Flujo de Trabajo TDD

Siga el ciclo ROJO → VERDE → REFACTORIZAR:

  1. ROJO: escribir una prueba que falle que capture el nuevo comportamiento
  2. VERDE: implementar el cambio más pequeño para que pase
  3. REFACTORIZAR: limpiar mientras las pruebas sigan 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 stub: 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 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
  # Framework Google Test (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. Vuelva a ejecutar la prueba individual que falla con el filtro gtest.
  2. Agregue registros con ámbito alrededor de la aserción que falla.
  3. Vuelva a ejecutar con sanitizadores habilitados.
  4. Expanda a la suite completa una vez corregida la causa raíz.

Cobertura

Prefiera 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()

Guardarraíles para Pruebas Inestables

  • Nunca usar sleep para sincronización; usar variables de condición o barreras.
  • 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 globales
  • Usar ASSERT_* para precondiciones, EXPECT_* para múltiples verificaciones
  • Separar pruebas unitarias vs de integración en etiquetas o directorios CTest
  • Ejecutar sanitizadores en CI para detección de memoria y condiciones de carrera

NO HACER

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

Errores Comunes

  • Usar rutas temporales fijas → Generar directorios temporales únicos por prueba y limpiarlos.
  • Depender del tiempo de reloj de pared → Inyectar un reloj o usar fuentes de tiempo falsas.
  • Pruebas de concurrencia inestables → Usar variables de condición/barreras y esperas acotadas.
  • Estado global oculto → Restablecer estado global en fixtures o eliminar globales.
  • Over mocking → Preferir falsos para comportamiento con estado y solo mockear interacciones.
  • Falta de ejecuciones de sanitizadores → Agregar compilaciones 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 Basadas en Propiedades

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

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

Arnes 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 cabecera, 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/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

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.

Skills relacionados