GoogleTest é um framework open-source baseado em xUnit para escrever testes em C++. GoogleTest busca atender às condições necessárias para testagem efetiva, tais como:

  • testes independentes e que podem ser repetidos: cada teste no GoogleTest é feito em um objeto diferente e, se esse teste falhar, pode ser rodado separadamente do conjunto de testes;
  • testes bem organizados na estrutura de código: no GoogleTest, é possível organizar testes por "test suites", ou conjuntos de testes, de modo que cada conjunto possa compartilhar dados/métodos e ajudar a manter um padrão de testes;
  • testes portáteis e reutilizáveis: GoogleTest roda em diversas plataformas e sistemas operacionais, não sendo dependente de um recurso específico;
  • testes que forneçam o máximo possível de informação sobre o erro: se um teste falhar, o GoogleTest pode abortar a execução desse teste e continuar com a execução dos próximos, de modo que a falha de testes não afeta a execução da rotina de testes.

Como instalar GoogleTest na sua máquina

editar

Este tutorial assume que você irá utilizar o GoogleTest em uma máquina com sistema operacional Linux, ou em uma máquina Windows com WSL2 instalado.

Para instalar o GoogleTest em seu computador, abra um terminal e digite:

sudo apt-get install libgtest-dev

Certifique-se de ter também o g++ e o cmake instalado na sua máquina para poder rodar os programas em C++:

sudo apt-get install g++

sudo apt-get install cmake

ASSERT e EXPECT

editar

Em GoogleTest, assertions checam se uma condição é verdadeira ou não. Podem retornar sucesso, falha não fatal ou falha fatal. Os macros ASSERT e EXPECT são os mais simples de serem utilizados dentro do GoogleTest. Ambos são um tipo de assertion, com a diferença de que ASSERT gera erros fatais ao falhar, interrompendo a rotina de testes, enquanto EXPECT gera erros não fatais, e não interrompem a rotina de testes.

Alguns usos de ASSERT e EXPECT podem ser visto na tabela abaixo. Para mais usos, verifique a documentação oficial do GoogleTest.

ASSERT EXPECT Explicação
ASSERT_TRUE(cond) EXPECT_TRUE(cond) Verifica se cond é verdadeira.
ASSERT_FALSE(cond) EXPECT_FALSE(cond) Verifica se cond é falsa.
ASSERT_EQ(a, b) EXPECT_EQ(a, b) Verifica se a == b.
ASSERT_NE(a, b) EXPECT_NE(a, b) Verifica se a != b.
ASSERT_GT(a, b) EXPECT_GT(a, b) Verifica se a > b.
ASSERT_GE(a, b) EXPECT_GE(a, b) Verifica se a >= b.
ASSERT_LT(a, b) EXPECT_LT(a, b) Verifica se a < b.
ASSERT_LE(a, b) EXPECT_LE(a, b) Verifica se a <= b.
ASSERT_STREQ(s1, s2) EXPECT_STREQ(s1, s2) Verifica se a string s1 == string s2.
ASSERT_STRNE(s1, s2) EXPECT_STRNE(s1, s2) Verifica se a string s1 != string s2.

Como usar GoogleTest no meu programa

editar

Para entender como habilitar o Google Test no nosso código, vamos criar primeiro um arquivo fatorial.h, que define uma função para calcular o fatorial de um número:

// fatorial.h
#ifndef FATORIAL_H
#define FATORIAL_H

int fat(int n);

#endif

Agora, vamos criar um arquivo fatorial.cpp, em que iremos implementar nossa função fatorial:

// fatorial.cpp
#include "fatorial.hpp"

int fat(int n) {
    if (n == 0 || n == 1) 
        return 1; 
    return n * fat(n - 1);

Por fim, vamos criar um arquivo fat_teste.cpp para escrever nossos testes e nossa main. Mas antes de escrever nosso arquivo de testes, vamos listar alguns casos de teste interessantes:

  • n = 0?
  • n = 1?
  • n = 2?
  • n = 5?

Note também que os testes são escritos no seguinte padrão:

TEST (<conjunto-de-teste>, <nome-do-teste>) {
    // cada linha deve ter apenas uma chamada de ASSERT... ou EXPECT...
}

Implementando esses casos de testes, nosso arquivo fat_teste.cpp vai ficar assim:

// fat_test.cpp
#include <gtest/gtest.h>
#include "fatorial.h"

// n = 0?
TEST (FatTest, nIguala0) {
    EXPECT_EQ(1, fat(0));
}

// n = 1?
TEST (FatTest, nIguala1) {
    EXPECT_EQ(1, fat(1));
}

// n = 2?
TEST (FatTest, nIguala2) {
    EXPECT_EQ(2, fat(2));
}

// n = 5?
TEST (FatTest, nIguala5) {
    EXPECT_EQ(120, fat(5));
}

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

Como podemos observar no código, para usar o GoogleTest, nosso arquivo de teste deve:

  • incluir a biblioteca do GoogleTest na primeira linha do arquivo;
#include <gtest/gtest.h>
  • declarar a função main da seguinte forma:
int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Após escrever nosso arquivo de testes, devemos compilar nosso programa usando as flags -lgtest -lpthread, da seguinte forma:

g++ -o fat_test fat_test.cpp fatorial.cpp -lgtest -lpthread

ATENÇÃO! Note que se seu programa de testes utilizar mais de um arquivo .cpp/.h, o arquivo .cpp deve ser passado no comando de compilação e deve ser feito o include do arquivo .h nas primeiras linhas de código do arquivo de testes.

Após compilar, vamos finalmente executar nosso programa de testes:

./fat_test

E o output em nosso terminal deverá ser parecido com isso, o que significa que todos os testes tiveram sucesso:

lume@LUME:~/mac350/tutorial$ ./fat_test
[==========] Running 4 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 4 tests from FatTest
[ RUN      ] FatTest.nIguala0         # RUN indica que o teste está sendo executado
[       OK ] FatTest.nIguala0 (0 ms)  # OK indica que o teste teve sucesso
[ RUN      ] FatTest.nIguala1
[       OK ] FatTest.nIguala1 (0 ms)
[ RUN      ] FatTest.nIguala2
[       OK ] FatTest.nIguala2 (0 ms)
[ RUN      ] FatTest.nIguala5
[       OK ] FatTest.nIguala5 (0 ms)
[----------] 4 tests from FatTest (0 ms total)

[----------] Global test environment tear-down
[==========] 4 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 4 tests.                 # status final da rotina de testes
lume@LUME:~/mac350/tutorial$

Falha em testes

editar

Para provar ainda mais a robustez de um sistema, às vezes é recomendado escrever testes cujo resultado deve ser sempre uma falha, ou seja, que irão falhar propositalmente. Por exemplo, sabemos que fatorial de 4 é 24, mas vamos escrever um teste que espere que fat(4) devolva 23:

// n = 0?
TEST (FatTest, nIguala4) {
    EXPECT_EQ(23, fat(4));
}

Após compilar e executar o programa de testes novamente, temos o seguinte resultado:

lume@LUME:~/mac350/tutorial$ ./fat_test
[==========] Running 5 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 5 tests from FatTest
[ RUN      ] FatTest.nIguala0
[       OK ] FatTest.nIguala0 (0 ms)
[ RUN      ] FatTest.nIguala1
[       OK ] FatTest.nIguala1 (0 ms)
[ RUN      ] FatTest.nIguala2
[       OK ] FatTest.nIguala2 (0 ms)
[ RUN      ] FatTest.nIguala4
fat_test.cpp:22: Failure                               # as proximas 5 linhas demonstram que
Expected equality of these values:                     # o teste nIguala4 falhou, bem como o
  23                                                   # valor de retorno e o valor esperado
  fat(4)
    Which is: 24
[  FAILED  ] FatTest.nIguala4 (22 ms)      
[ RUN      ] FatTest.nIguala5                          # note que a rotina de testes continua 
[       OK ] FatTest.nIguala5 (0 ms)                   # mesmo apos uma falha -> falha nao fatal
[----------] 5 tests from FatTest (22 ms total)

[----------] Global test environment tear-down
[==========] 5 tests from 1 test suite ran. (22 ms total)
[  PASSED  ] 4 tests.                                 # ao fim da rotina de testes, eh indicado                    
[  FAILED  ] 1 test, listed below:                    # o numero de testes com sucesso, o numero de
[  FAILED  ] FatTest.nIguala4                         # testes que falharam e o nome dos testes que
 1 FAILED TEST                                        # falharam
lume@LUME:~/mac350/tutorial$