Communitygithub.com

cpp-testing (Testes C++)

Use apenas ao escrever/atualizar/corrigir testes C++, configurar GoogleTest/CTest, diagnosticar falhas ou testes instáveis, ou adicionar cobertura/sanitizadores.

O que é cpp-testing (Testes C++)?

Esta habilidade fornece um fluxo de trabalho de testes orientado a agentes para C++ moderno (C++17/20) usando GoogleTest/GoogleMock com CMake/CTest. Ela guia o desenvolvedor através do ciclo TDD (vermelho → verde → refatorar), com ênfase em isolamento, injeção de dependência e o layout padrão de diretórios de teste. Inclui exemplos de código para testes de unidade básicos, fixtures, mocks e configuração CMake/CTest, bem como práticas para executar testes, depurar falhas, adicionar cobertura com gcov/lcov ou llvm-cov e habilitar sanitizadores (ASan, UBSan, TSan). Também aborda diretrizes para evitar testes instáveis, práticas recomendadas e armadilhas comuns, além de um apêndice opcional sobre fuzzing (libFuzzer) e teste de propriedades (RapidCheck). A habilidade é projetada para agentes que precisam escrever, manter ou corrigir testes C++ de forma consistente e confiável, garantindo que o agente siga as convenções e práticas estabelecidas pela comunidade C++ moderna.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Testes C++ (Habilidade para Agente)

Fluxo de Trabalho de Testes orientado a agente para C++ moderno (C++17/20) usando GoogleTest/GoogleMock com CMake/CTest.

Quando Usar

  • Escrever novos testes C++ ou corrigir testes existentes
  • Projetar cobertura de testes unitários/integração para componentes C++
  • Adicionar cobertura de testes, portão de CI ou proteção contra regressões
  • Configurar fluxos de trabalho CMake/CTest para execução consistente
  • Investigar falhas de teste ou comportamento instável
  • Habilitar sanitizadores para diagnóstico de memória/condições de corrida

Quando NÃO Usar

  • Implementar novos recursos de produto sem alterações nos testes
  • Refatorações de grande escala não relacionadas à cobertura ou falhas de teste
  • Ajustes de desempenho sem regressões de teste para validar
  • Projetos que não são C++ ou tarefas que não são de teste

Conceitos Centrais

  • Ciclo TDD: vermelho → verde → refatorar (testes primeiro, correção mínima, depois limpeza).
  • Isolamento: preferir injeção de dependência e fakes em vez de estado global.
  • Layout de teste: tests/unit, tests/integration, tests/testdata.
  • Mocks vs fakes: usar mock para interações, fake para comportamento com estado.
  • Descoberta CTest: usar gtest_discover_tests() para descoberta estável de testes.
  • Sinalização CI: executar um subconjunto primeiro, depois a suíte completa com --output-on-failure.

Fluxo de Trabalho TDD

Siga o ciclo VERMELHO → VERDE → REFATORAR:

  1. VERMELHO: escreva um teste que falhe e capture o novo comportamento
  2. VERDE: implemente a menor alteração para passar
  3. REFATORAR: limpe enquanto os testes permanecem verdes
// tests/add_test.cpp
#include <gtest/gtest.h>

int Add(int a, int b); // Fornecido pelo código de produção.

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

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

// REFATORAR: simplificar/renomear assim que os testes passarem

Exemplos de Código

Teste de Unidade Básico (gtest)

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

int Add(int a, int b); // Fornecido pelo código de produção.

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

Fixture (gtest)

// tests/user_store_test.cpp
// Stub de pseudocódigo: substituir UserStore/User pelos tipos do projeto.
#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");
}

Início Rápido com CMake/CTest

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

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
# Prefira versões bloqueadas pelo projeto. Se usar uma tag, use uma versão fixa conforme a política do projeto.
set(GTEST_VERSION v1.17.0) # Ajuste conforme a política do projeto.
FetchContent_Declare(
  googletest
  # Google Test framework (repositório 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

Executando Testes

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

Depurando Falhas

  1. Execute novamente o único teste que falhou com o filtro gtest.
  2. Adicione logs com escopo ao redor da asserção que falhou.
  3. Execute novamente com sanitizadores habilitados.
  4. Expanda para a suíte completa assim que a causa raiz for corrigida.

Cobertura

Prefira configurações no nível do alvo em vez de flags globais.

option(ENABLE_COVERAGE "Habilitar flags 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()

Diretrizes para Testes Instáveis

  • Nunca use sleep para sincronização; use variáveis de condição ou latches.
  • Crie diretórios temporários exclusivos por teste e sempre os limpe.
  • Evite tempo real, rede ou dependências do sistema de arquivos em testes unitários.
  • Use sementes determinísticas para entradas aleatórias.

Melhores Práticas

FAÇA

  • Mantenha os testes determinísticos e isolados
  • Prefira injeção de dependência em vez de globais
  • Use ASSERT_* para pré-condições, EXPECT_* para múltiplas verificações
  • Separe testes unitários vs integração em rótulos ou diretórios do CTest
  • Execute sanitizadores no CI para detecção de memória e condições de corrida

NÃO FAÇA

  • Não dependa de tempo real ou rede em testes unitários
  • Não use sleeps como sincronização quando uma variável de condição puder ser usada
  • Não exagere no uso de mocks para objetos de valor simples
  • Não use correspondência de strings frágil para logs não críticos

Armadilhas Comuns

  • Usar caminhos temporários fixos → Gere diretórios temporários exclusivos por teste e os limpe.
  • Depender do tempo de relógio de parede → Injete um relógio ou use fontes de tempo falsas.
  • Testes de concorrência instáveis → Use variáveis de condição/latches e esperas limitadas.
  • Estado global oculto → Redefina o estado global em fixtures ou remova globais.
  • Exagero de mocks → Prefira fakes para comportamento com estado e faça mock apenas de interações.
  • Falta de execução de sanitizadores → Adicione builds ASan/UBSan/TSan no CI.
  • Cobertura apenas em builds de depuração → Certifique-se de que os alvos de cobertura usem flags consistentes.

Apêndice Opcional: Fuzzing / Teste de Propriedades

Use apenas se o projeto já suporta LLVM/libFuzzer ou uma biblioteca de teste de propriedades.

  • libFuzzer: melhor para funções puras com E/S mínima.
  • RapidCheck: testes baseados em propriedades para validar invariantes.

Harness mínimo para libFuzzer (pseudocódigo: substitua 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); // função do projeto
    return 0;
}

Alternativas ao GoogleTest

  • Catch2: apenas cabeçalho, matchers expressivos
  • doctest: leve, sobrecarga mínima de compilação

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.

Habilidades Relacionadas