Testes em C++: frameworks e ferramentas
A qualidade do código em C++ é um fator crítico para a confiabilidade do software. Ao contrário de linguagens com memória gerenciada, erros em C++ podem levar a falhas graves, vazamentos de memória e comportamento indefinido. O sistema de testes unitários permite identificar defeitos nas fases iniciais, facilita a refatoração e documenta o comportamento das funções. Neste artigo, veremos três frameworks populares para testes em C++: Google Test, Catch2 e doctest, além de ferramentas para sua integração no processo de desenvolvimento.
Por que os testes são necessários em C++?
- Segurança durante a refatoração: os testes sinalizam imediatamente regressões.
- Documentação: testes legíveis servem como exemplos vivos de uso da API.
- Integração com CI: execução automática de testes a cada commit.
- Identificação de comportamento indefinido: testes com sanitizers (AddressSanitizer, UndefinedBehaviorSanitizer).
1. Google Test (GTest)
O framework mais popular do Google. Suporta o estilo xUnit, um rico conjunto de macros de asserções, registro automático de testes, mocks (através do Google Mock) e testes parametrizados.
Instalação (via CMake FetchContent)
# CMakeLists.txtinclude(FetchContent)FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1)FetchContent_MakeAvailable(googletest)
add_executable(my_tests test.cpp)target_link_libraries(my_tests GTest::gtest_main)Exemplo de teste
#include <gtest/gtest.h>
int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n - 1);}
TEST(FactorialTest, HandlesZeroInput) { EXPECT_EQ(factorial(0), 1);}
TEST(FactorialTest, HandlesPositiveInput) { EXPECT_EQ(factorial(5), 120); EXPECT_GT(factorial(3), 5);}
int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}TEST()— macro para definir um caso de teste.EXPECT_EQ— verificação de igualdade (não fatal).ASSERT_*— verificações fatais (interrompem o teste em caso de falha).
2. Catch2
Framework moderno com foco em legibilidade e simplicidade. Suporta o estilo BDD (Given-When-Then), seções (divisão de testes em cenários aninhados) e geração de dados aleatórios. Não requer herança de classes base.
Instalação (single-header ou via vcpkg)
# vcpkgvcpkg install catch2
# CMakefind_package(Catch2 REQUIRED)target_link_libraries(my_tests Catch2::Catch2)Exemplo de teste
#define CATCH_CONFIG_MAIN#include <catch2/catch.hpp>
int add(int a, int b) { return a + b; }
TEST_CASE("Addition works", "[math]") { REQUIRE(add(2, 2) == 4); CHECK(add(-1, 1) == 0);
SECTION("With zero") { REQUIRE(add(0, 5) == 5); }}
TEST_CASE("String concatenation", "[string]") { std::string result = std::string("Hello ") + "World"; CHECK(result == "Hello World");}TEST_CASE— declaração de teste com nome e tags.REQUIRE— verificação fatal.CHECK— verificação não fatal.SECTION— cenário aninhado (cada seção é executada a partir do estado comum).
3. Doctest
Alternativa leve e rápida. Inspirado no Catch2, mas compila de 2 a 5 vezes mais rápido. Destinado a projetos onde a velocidade de compilação é importante. Suporta arquivo de cabeçalho (header-only), macros CHECK e REQUIRE, além de saída em formato XML.
Instalação (he
Também na biblioteca
Autorização e Autenticação em Java: Spring Security e JWT
Socket.io para JavaScript (Node.js): guia completo com exemplos
Trabalhando com XML em Rust: bibliotecas roxmltree, quick-xml e serde-xml-rs
Cliente OAuth para Java: ScribeJava e Spring Security OAuth2
Cliente Elasticsearch para Node.js: @elastic/elasticsearch