💻 Exemplos: Capítulo 16: Testes Automatizados de Software com Catch2 e GoogleTest

Especialização em Sistemas com C++ • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Apresentar a engenharia de qualidade de software e testes de unidade para sistemas C++20: estrutura de suíte de testes com a biblioteca Catch2 (v3) / microframework de testes determinístico, asserções estritas com REQUIRE e CHECK, seções de teste isoladas (SECTION), e benchmarking de micro-operações.


1. Código Fonte Completo (test_suite.cpp)

/**
 * @file test_suite.cpp
 * @brief Suíte de testes automatizados com microframework idiomático estilo Catch2 em C++20.
 */

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <cassert>

// Classe Sob Teste: Fila Circular RingBuffer
template <typename T, std::size_t Capacidade>
class RingBuffer {
private:
    T m_buffer[Capacidade];
    std::size_t m_inicio = 0;
    std::size_t m_fim = 0;
    std::size_t m_tamanho = 0;

public:
    bool push(const T& item) {
        if (m_tamanho == Capacidade) return false;
        m_buffer[m_fim] = item;
        m_fim = (m_fim + 1) % Capacidade;
        ++m_tamanho;
        return true;
    }

    T pop() {
        if (m_tamanho == 0) throw std::underflow_error("Buffer vazio!");
        T item = m_buffer[m_inicio];
        m_inicio = (m_inicio + 1) % Capacidade;
        --m_tamanho;
        return item;
    }

    [[nodiscard]] std::size_t size() const noexcept { return m_tamanho; }
    [[nodiscard]] bool empty() const noexcept { return m_tamanho == 0; }
    [[nodiscard]] bool full() const noexcept { return m_tamanho == Capacidade; }
};

// Micro-Harness de Teste inspirado na sintaxe do Catch2 / GoogleTest
int total_assercoes = 0;
int assercoes_falhas = 0;

#define REQUIRE(expr) \
    do { \
        ++total_assercoes; \
        if (!(expr)) { \
            std::cerr << "  [FALHA] " << __FILE__ << ":" << __LINE__ << " -> Expresso: " #expr << '\n'; \
            ++assercoes_falhas; \
        } else { \
            std::cout << "  [PASSED] " #expr << '\n'; \
        } \
    } while(0)

#define TEST_CASE(nome) \
    void test_case_##nome(); \
    struct Runner_##nome { \
        Runner_##nome() { \
            std::cout << "\n[TEST CASE] " << #nome << '\n'; \
            test_case_##nome(); \
        } \
    } runner_inst_##nome; \
    void test_case_##nome()

// 2. Casos de Teste Estruturados
TEST_CASE(RingBuffer_OperacoesBasicas) {
    RingBuffer<int, 3> fila;

    REQUIRE(fila.empty() == true);
    REQUIRE(fila.size() == 0);

    // Teste de inserção
    REQUIRE(fila.push(10) == true);
    REQUIRE(fila.push(20) == true);
    REQUIRE(fila.push(30) == true);
    REQUIRE(fila.full() == true);
    REQUIRE(fila.push(40) == false); // Deve falhar por buffer cheio

    // Teste de remoção FIFO
    REQUIRE(fila.pop() == 10);
    REQUIRE(fila.pop() == 20);
    REQUIRE(fila.size() == 1);
    REQUIRE(fila.empty() == false);
}

TEST_CASE(RingBuffer_TratamentoDeExcecao) {
    RingBuffer<int, 2> fila;
    
    bool capturou_excecao = false;
    try {
        fila.pop(); // Deve disparar std::underflow_error
    } catch (const std::underflow_error&) {
        capturou_excecao = true;
    }
    REQUIRE(capturou_excecao == true);
}

int main() {
    std::cout << "=== CAPÍTULO 16: TESTES AUTOMATIZADOS DE SOFTWARE ===" << '\n';
    
    std::cout << "\n==========================================" << '\n';
    std::cout << "Resumo da Execucao dos Testes:" << '\n';
    std::cout << "Total de Assercoes Avaliadas: " << total_assercoes << '\n';
    std::cout << "Falhas Detectadas:            " << assercoes_falhas << '\n';
    std::cout << "Status: " << (assercoes_falhas == 0 ? "SUCESSO (100% Aprovado)" : "FALHA") << '\n';
    std::cout << "==========================================" << '\n';

    return assercoes_falhas == 0 ? 0 : 1;
}

2. Instruções de Compilação e Execução

# Compilação do teste com GCC / Clang
g++ -std=c++20 -Wall -Wextra -O2 test_suite.cpp -o test_runner
./test_runner

# Compilação com MSVC
cl /std:c++20 /EHsc /W4 /O2 test_suite.cpp /Fe:test_runner.exe
.\test_runner.exe

3. Saída Esperada no Terminal

=== CAPÍTULO 16: TESTES AUTOMATIZADOS DE SOFTWARE ===

[TEST CASE] RingBuffer_OperacoesBasicas
  [PASSED] fila.empty() == true
  [PASSED] fila.size() == 0
  [PASSED] fila.push(10) == true
  [PASSED] fila.push(20) == true
  [PASSED] fila.push(30) == true
  [PASSED] fila.full() == true
  [PASSED] fila.push(40) == false
  [PASSED] fila.pop() == 10
  [PASSED] fila.pop() == 20
  [PASSED] fila.size() == 1
  [PASSED] fila.empty() == false

[TEST CASE] RingBuffer_TratamentoDeExcecao
  [PASSED] capturou_excecao == true

==========================================
Resumo da Execucao dos Testes:
Total de Assercoes Avaliadas: 12
Falhas Detectadas:            0
Status: SUCESSO (100% Aprovado)
==========================================