A03 - Criando e executando testes com o CTest

Questão

  • Como podemos lidar com o estágio de testes do nosso projeto com CMake?

Objetivos

  • Aprenda a produzir executáveis de teste com CMake.

  • Aprenda a executar seus testes através do CTest.

O teste é uma atividade essencial no ciclo de desenvolvimento. Um conjunto de testes bem projetado irá ajudá-lo a detectar bugs e também pode facilitar a integração de novos desenvolvedores.

_images/ctest.svg

O CTest faz parte do conjunto de programas CMake. É um executor de testes. Você pode definir um conjunto de testes, executá-los e gerar relatórios através dele.

Nesta atividade, vamos analisar como usar o CTest para definir e executar nossos testes.

Adicionando testes ao seu projeto

No CMake e CTest, um teste é qualquer comando retornando um código de saída. Não importa como o comando é emitido ou executado: pode ser um executável C++ ou um script Python. Contanto que a execução retorne um código de saída zero ou não-zero, o CMake poderá classificar se o teste foi bem sucedido ou se falhou, respectivamente.

Existem duas etapas para integrar seu sistema de compilação CMake com a ferramenta CTest:

  1. Chamar o comando enable_testing a qual não requer argumentos.

  2. Adicionar testes com o comando add_test.

Exercício 6: Executando os testes através de um script shell

Qualquer comando pode ser usado para executar testes. Neste exercício, vamos estender o código cmake anterior para testar o executável principal dentro de um script de shell. Use o projeto base localizado na pasta source/code/day-1/06_bash-ctest.

  1. Encontre o executável bash apropriado para executar test.sh. Você deve usar o comando find_program do CMake.

    find_program(BASH_EXECUTABLE NAMES bash REQUIRED)
    

    A variável BASH_EXECUTABLE será o programa shell.

  2. Adicione outra invocação de add_test que será equivalente a executar:

    $ ./test.sh sum_up
    

    Sugestões:

    • Use a localização absoluta de test.sh.

    • Você pode usar a sintaxe gerador de expressão para dar a localização do executável: $<TARGET_FILE:sum_up>.

  3. Construa o projeto e execute o CTest.

Uma solução está na subpasta solution.

Exercício 7: Executando os testes através de um script Python

É muito mais comum hoje em dia usar python, em vez de scripts de shell. Neste exercício, adicionaremos mais dois testes ao nosso projeto. Esses novos testes executarão o programa principal por meio de um script Python. Use o projeto base localizado na pasta source/code/day-1/07_python-ctest.

#. Encontre o intérprete Python para executar test.py. Você deve usar o comando find_package do CMake:

find_package(Python REQUIRED)

O intérprete estará disponível na variável Python_EXECUTABLE.

  1. Adicione outra invocação de add_test que será equivalente a executar:

    $ python test.py --executable sum_up
    

    Sugestões:

    • Use a localização absoluta de test.py.

    • Você pode usar a sintaxe gerador de expressão para dar a localização do executável:$<TARGET_FILE:sum_up>.

  2. O script test.py aceita o comando por linha de argumento --short. Adicione outro teste que use essa opção no comando.

  3. Construa o projeto e corra o CTest.

Uma solução está na subpasta solution.

A interface de linha de comando do CTest

Propriedades do teste: rótulos, tempo limite e custo

Quando você usa add_test, Você dá um nome único para cada teste. Como nós vimos, Você pode usar esses nomes para filtrar quais testes serão executados na suíte. Isso pode ser extremamente valioso quando a suíte de teste é muito grande e você precisará verificar apenas um subconjuntos dos testes. No entanto, o mecanismo de nomenclatura não permite que os testes sejam agrupados facilmente. Poderíamos, em princípio, adicionar um sufixo a todos os testes em um determinado grupo e depois filtrá-los com um regex apropriado, mas e se tivéssemos vários grupos para os quais os testes pudessem pertencer. Esta é uma situação muito comum na prática! Felizmente, podemos definir propriedades noson testes e os rótulos (labels) estão entre os propriedades disponíveis.

Exercício 8: Definir etiquetas em testes

Vamos executar alguns testes usando Python e queremos agrupá-los em duas categorias:

  • quick para testes com um tempo de execução muito curto.

  • long para testes de benchmarking com um tempo de execução mais longo.

Use o projeto base localizado na pasta source/code/day-1/08_ctest-labels.

  1. Encontre o interpretador Python:

    find_package(Python REQUIRED)
    

    O interpretador estará disponível na variável Python_EXECUTABLE.

  2. Enable testing.

  3. Adicione os seis testes da pasta test. Dê a cada um deles um nome único.

  4. Use set_tests_properties para definir rótulos para os testes:

    • feature-a.py, feature-b.py, e feature-c.py devem ser do grupo quick.

    • feature-d.py, benchmark-a.py, e benchmark-b.py devem ser do grupo long.

  5. Verifique se tudo funciona como esperado

Uma solução está na subpasta solution.

Entre as muitas propriedades que podem ser definidas em testes, gostaríamos de destacar as seguintes:

  • WILL_FAIL. O CTest marcará os testes como OK quando o comando correspondente retorna com um código de saída diferente de zero. Use esta propriedade para testar falhas esperadas.

  • COST. Na primeira vez que você executa seus testes, o CTest arazenará o tempo de execução de cada um.

    Desta forma, as execuções subseqüentes do conjunto de testes começarão a partir dos testes com maiores tempo de execução.

  • TIMEOUT. Alguns testes podem ser executados por um longo período: você pode definir um tempo limite explícito se quiser ser mais ou menos tolerante das variações de tempo na execução

Exercícios 9, 10, 11: Mais propriedades!

Vamos brincar com as propriedades que acabamos de introduzir.

Use o projeto base localizado na pasta source/code/day-1/09_ctest-will-fail.

  1. Crie um projeto sem uma linguagem.

  2. Encontre o interpretador Python.

  3. Habilite testing.

  4. Adicione script de teste test.py.

Tente executar os testes e observe o que acontece. Agora defina a propriedade WILL_FAIL para verdade e observe o que muda ao executar os testes.

Uma solução está na subpasta solution.

Para obter uma lista completa de propriedades que podem ser definidas faça:

$ cmake --help-properties

ou visite a documentação cmake online.

Keypoints

  • Qualquer comando pode ser definido como um teste no cmake.

  • Os testes podem ser executados através do CTest.