Testes em C++: Unit, Integration e E2E. Guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que testar em C++ não é um luxo, mas uma necessidade



Desenvolvimento em C++ é sempre um equilíbrio entre desempenho e confiabilidade. Erros de gerenciamento de memória, comportamento indefinido (UB) e dependências complexas entre módulos fazem do C++ uma das linguagens mais exigentes em relação à qualidade do código. Sem uma abordagem sistemática para testes, o projeto rapidamente se transforma em uma "caixa preta", onde corrigir um bug gera dois novos.



Neste artigo, vamos abordar três níveis principais de teste em C++: unit tests (testes unitários), integration tests (testes de integração) e e2e tests (testes ponta a ponta). Você aprenderá quais ferramentas usar, como escrever testes eficazes e como construir a pirâmide de testes para um projeto C++.



1. Testes Unitários: Verificando cada bloco



Testes unitários são a base da pirâmide de testes. Eles verificam isoladamente uma unidade lógica de código: uma função, um método de classe ou uma pequena estrutura. Em C++, os testes unitários devem ser executados rapidamente (<1 segundo para centenas de testes) e não depender de recursos externos (sistema de arquivos, rede, bancos de dados).



Ferramentas para testes unitários em C++

  • Google Test (gtest) — o framework mais popular do Google. Suporta macros de assertion, fixtures e testes parametrizados.
  • Catch2 — uma alternativa moderna com sintaxe concisa e suporte a estilo BDD.
  • Boost.Test — parte da biblioteca Boost, uma ferramenta madura com amplas possibilidades.


Exemplo de teste unitário com Google Test

Suponha que temos uma função para calcular o fatorial:



// math_utils.h#pragma onceunsigned long long factorial(unsigned int n);


// math_utils.cpp#include "math_utils.h"

unsigned long long factorial(unsigned int n) { if (n == 0) return 1; unsigned long long result = 1; for (unsigned int i = 1; i <= n; ++i) { result *= i; } return result;}


Escrevemos o teste unitário:



// test_math_utils.cpp#include <gtest/gtest.h>#include "math_utils.h"

TEST(FactorialTest, HandlesZero) { EXPECT_EQ(factorial(0), 1);}

TEST(FactorialTest, HandlesPositiveNumbers) { EXPECT_EQ(factorial(1), 1); EXPECT_EQ(factorial(5), 120); EXPECT_EQ(factorial(10), 3628800);}

TEST(FactorialTest, HandlesLargeInput) { // 20! cabe em unsigned long long EXPECT_EQ(factorial(20), 2432902008176640000ULL);}


Melhores práticas para testes unitários em C++:

  • Um teste — uma verificação. Use EXPECT_EQ para verificações suaves e ASSERT_EQ para verificações críticas.
  • Isole dependências usando mock objects (Google Mock).
  • Teste casos limite: valores zero, estouro, contêineres vazios.
  • Use TEST_F para inicialização repetitiva (fixtures).


2. Testes de Integração: Como os módulos funcionam juntos



Testes de integração verificam a interação entre vários módulos ou componentes. Em C++, isso é especialmente importante, pois erros frequentemente surgem nas interfaces: gerenciamento incorreto de memória ao passar objetos, incompatibilidade de interfaces ou problemas com multithreading.



Ao contrário dos testes unitários, os testes de integração podem trabalhar com bancos de dados reais, arquivos ou sockets de rede, mas geralmente em um ambiente de teste (por exemplo, arquivos temporários ou contêineres Docker).



Exemplo de teste de integração

Suponha que temos um módulo Logger e um módulo FileManager. Queremos verificar se os logs são escritos corretamente no arquivo.



// file_logger.h#pragma once#include <string>

class FileLogger {public: FileLogger(const std::string& filename); vo

Blogs

Book Recommendations