C++: Testes Unitários

Última atualização: 2026-08-26

Na aula 49, aprendemos sobre otimização de desempenho.

Agora, vamos aprender sobre testes unitários — a habilidade-chave para garantir a qualidade do código.

Escrever código sem testar é como cozinhar sem provar.


1. Visão Geral de Testes Unitários

(1) 1.1 O Que São Testes Unitários?

Testes unitários envolvem testar as menores unidades testáveis (funções, classes).

Vantagens:


(2) 1.2 Escolhendo um Framework de Teste

Framework Descrição
Google Test Feito pelo Google, mais popular
Catch2 Arquivo header único, simples de usar
Boost.Test Parte das bibliotecas Boost
Doctest Similar ao Catch2, mais rápido

Recomendação: Google Test (completo) ou Catch2 (simples)



2. Introdução ao Google Test

(1) 2.1 Instalando o Google Test

Linux:

BASH
sudo apt-get install libgtest-dev

Windows: Use vcpkg ou compile do código-fonte.


(2) 2.2 Seu Primeiro Teste

Exemplo: Testando uma função de adição com Google Test (Dificuldade ⭐)

▶ Exemplo 2: Exemplo de código (Dificuldade ⭐)

TEXT 📖 Somente leitura
#include <gtest/gtest.h>

int add(int a, int b) {
 return a + b;
}

TEST(AddTest, Positive) {
 EXPECT_EQ(add(2, 3), 5);
}

TEST(AddTest, Negative) {
 EXPECT_EQ(add(-2, -3), -5);
}

int main(int argc, char** argv) {
 ::testing::InitGoogleTest(&argc, argv);
 return RUN_ALL_TESTS();
}

Saída:

TEXT 📖 Somente leitura
[==========] Running 2 tests from 1 test suite.
[  PASSED  ] 2 tests.

Resultado da execução:

TEXT 📖 Somente leitura
[==========] Running 2 tests from 1 test suite.
[ PASSED ] 2 tests.


3. Macros de Asserção

(1) 3.1 ASSERT vs EXPECT

Macro Comportamento em Caso de Falha
ASSERT_* Para o teste atual
EXPECT_* Continua executando

Recomendação: Use EXPECT_* (você pode ver mais falhas)


(2) 3.2 Asserções Comuns

Asserção Descrição
EXPECT_EQ(a, b) a == b
EXPECT_NE(a, b) a != b
EXPECT_LT(a, b) a < b
EXPECT_GT(a, b) a > b
EXPECT_TRUE(cond) cond é verdadeiro
EXPECT_FALSE(cond) cond é falso
EXPECT_THROW(statement, exception_type) Espera que uma exceção seja lançada


4. Fixtures de Teste

(1) 4.1 Por Que Precisamos de Fixtures?

Problema: Múltiplos testes precisam do mesmo código de inicialização.

Solução: Fixtures de teste (herdar de testing::Test)


(2) 4.2 Exemplo: Testando uma fila com fixtures (Dificuldade ⭐⭐)

CPP
#include <gtest/gtest.h>
#include <queue>

class QueueTest : public testing::Test {
protected:
 void SetUp() override {
 q.push(1);
 q.push(2);
 q.push(3);
 }
 
 void TearDown() override {
 // Limpeza (se necessário)
 }
 
 std::queue<int> q;
};

TEST_F(QueueTest, Size) {
 EXPECT_EQ(q.size(), 3);
}

TEST_F(QueueTest, Front) {
 EXPECT_EQ(q.front(), 1);
}

int main(int argc, char** argv) {
 ::testing::InitGoogleTest(&argc, argv);
 return RUN_ALL_TESTS();
}

Saída:

TEXT 📖 Somente leitura
(Saída do programa)


5. Desenvolvimento Orientado a Testes (TDD)

(1) 5.1 O Que É TDD?

TDD (Test-Driven Development) significa escrever testes primeiro, depois escrever o código.

Processo:

  1. Escreva um teste (ele falha)
  2. Escreva o código (ele passa)
  3. Refatore

(2) 5.2 Exemplo: TDD para uma Pilha (Dificuldade ⭐⭐⭐)

TEXT 📖 Somente leitura
// 1. Escreva o teste primeiro
TEST(StackTest, PushAndPop) {
 Stackint s;
 s.push(42);
 EXPECT_EQ(s.pop(), 42);
}

// 2. Depois escreva o código
template<typename T>
class Stack {
 std::vectorT data;
public:
 void push(const T& x) { data.push_back(x); }
 T pop() { T x = data.back(); data.pop_back(); return x; }
};

Saída:

TEXT 📖 Somente leitura
(Saída do programa)


6. Prática: Testando uma Classe Student

▶ Exemplo 1: Teste completo (Dificuldade ⭐⭐⭐)

CPP
#include <gtest/gtest.h>
#include <string>

class Student {
 std::string name;
 int age;
 
public:
 Student(const std::string& name, int age) : name(name), age(age) {}
 
 std::string getName() const { return name; }
 int getAge() const { return age; }
};

TEST(StudentTest, Constructor) {
 Student s("Zhang San", 20);
 EXPECT_EQ(s.getName(), "Zhang San");
 EXPECT_EQ(s.getAge(), 20);
}

int main(int argc, char** argv) {
 ::testing::InitGoogleTest(&argc, argv);
 return RUN_ALL_TESTS();
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
(Saída do programa)

▶ Exemplo 3: Teste unitário simples (Dificuldade ⭐)

CPP
#include <iostream>
#include <cassert>

// Funções sendo testadas
int multiply(int a, int b) {
    return a * b;
}

bool isPositive(int n) {
    return n > 0;
}

int main() {
    // Testar multiply
    assert(multiply(2, 3) == 6);
    assert(multiply(-2, 3) == -6);
    assert(multiply(0, 5) == 0);
    std::cout << "multiply Test passed" << std::endl;

    // Testar isPositive
    assert(isPositive(5) == true);
    assert(isPositive(-1) == false);
    assert(isPositive(0) == false);
    std::cout << "isPositive Test passed" << std::endl;

    std::cout << "All tests passed!" << std::endl;
    return 0;
}
▶ Experimente

Saída:

TEXT 📖 Somente leitura
multiply Test passed
isPositive Test passed
All tests passed!

❓ Perguntas Frequentes

P: Testes unitários podem encontrar todos os bugs? R: Não. Testes unitários só podem encontrar tipos conhecidos de erros. Você também precisa de testes de integração e testes de sistema.


P: O código de teste deve ser enviado junto com o código de produção? R: Não. O código de teste é tipicamente usado apenas durante o desenvolvimento.


P: Como testo funções privadas? R: - Método 1: Teste a interface pública (teste indireto) - Método 2: Use FRIEND_TEST para expor membros privados - Método 3: Refatore extraindo funções privadas em uma classe separada


📖 Resumo

Ponto-Chave Resumo
Teste unitário Testar as menores unidades
Google Test Framework de teste C++ mais popular
Macros de asserção EXPECT_* e ASSERT_*
Fixtures de teste Compartilhar código de inicialização
TDD Escrever testes primeiro, depois código

📝 Exercícios

  1. Básico (Dificuldade ⭐): Escreva uma função add(a, b) e crie 3 casos de teste com Google Test: adição de positivos, adição de negativos, adição de zeros.

  2. Intermediário (Dificuldade ⭐⭐): Escreva uma função isPalindrome que verifica se uma string é um palíndromo. Escreva pelo menos 5 casos de teste cobrindo entradas normais, de borda e especiais.

  3. Desafio (Dificuldade ⭐⭐⭐): Escreva testes unitários completos para uma classe "Conta Bancária" (com métodos depositar/sacar/getBalance). Teste depósitos/saques normais, rejeição de saque acima do saldo e segurança de thread (se aplicável).



Próxima aula: Prática — Sistema de Gerenciamento de Contatos (#51)

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%