Teste de unidade

Em novembro de 2007, passamos a exigir que todos os novos recursos que vão para a versão master passem a ser acompanhado de um teste de unidade. Inicialmente nós limitamos este requisito ao qgis_core, e vamos estender este requisito a outras partes da base de código conforme as pessoas estão familiarizados com os procedimentos de teste de unidade explicado nas seções que se seguem.

O framework de testes do QGIS - uma visão geral

O teste de unidade é realizada utilizando uma combinação de QTestLib (a biblioteca de testes Qt) e CTest (um quadro para compilar e executar testes como parte do CMake build process). Vamos dar uma visão geral do processo antes de eu entrar em detalhes:

  • Há algum código que você deseja testar, por exemplo, uma classe ou função. Defensores do Extreme Programming sugerem que o código inda não deve ser escrito quando você começar a construir seus testes, e então conforme você implementar o seu código pode validar imediatamente cada nova parte funcional que você adicionar com o seu teste. Na prática você provavelmente terá que escrever testes para o código pré-existente no QGIS uma vez que estamos começando com um framework de testes bem depois lógica muita aplicação já foi implementado.
  • Você cria uma unidade de teste. Isso acontece sob <QGIS Source Dir>/tests/src/core no caso do core lib. O teste é basicamente um cliente que cria uma instância de uma classe e chama alguns métodos nessa classe. Ele irá verificar o retorno de cada método para garantir que corresponda ao valor esperado. Se qualquer uma das chamadas falhar, a unidade falhará.
  • Você inclui macros QtTestLib na sua classe de teste. Essa macro é processada pelo compilador de objeto meta Qt (moc) e expande sua classe de teste em uma aplicação executável.
  • Você adiciona uma seção ao CMakeLists.txt em seu diretório de testes que criará seu teste.
  • Você garante que tenha o `` ENABLE_TESTING`` ativado no ccmake / cmakesetup. Isso garantirá que seus testes sejam compilados quando você digitar make.
  • Você, opcionalmente, adiciona dados de teste a <QGIS Source Dir>/ tests / testdata se o seu teste for orientado por dados (por exemplo, precisa carregar um shapefile). Esses dados de teste devem ser tão pequenos quanto possível e, sempre que possível, você deve usar o conjunto de dados existentes já existentes. Seus testes nunca devem modificar esses dados in situ, mas sim uma cópia temporária em algum lugar, se necessário.
  • Você compila suas fontes e instala. Faça isso usando o procedimento normal `` make && (sudo) make install``.
  • Você executa seus testes. Isso normalmente é feito simplesmente fazendo `` make test`` após a etapa `` make install``, embora eu explique outras abordagens que oferecem um controle mais refinado sobre os testes em execução.

Certo com esse panorama geral em mente, vou mergulhar em um pouco de detalhe. Eu já fiz muita da configuração para você no CMake e em outros lugares na árvore de código-fonte, então tudo que você precisa fazer são os bits fáceis - escrever testes de unidade!

Criar um teste de unidade

Criar uma unidade de teste é fácil - normalmente você fará isso apenas criando um único arquivo .cpp (não é usado o arquivo .h) e implementará todos os seus métodos de teste como métodos públicos que retornam o vazio. Vou usar uma classe de teste simples para QgsRasterLayer em toda a seção que segue para ilustrar. Por convenção, nomearemos nosso teste com o mesmo nome da classe que estão testando, mas prefixado com ‘Teste’. Então nossa implementação de teste vai em um arquivo chamado testqgsrasterlayer.cpp e a própria classe será TestQgsRasterLayer. Primeiro, adicionamos nosso banner de direitos autorais padrão:

/***************************************************************************
 testqgsvectorfilewriter.cpp
 --------------------------------------
  Date : Friday, Jan 27, 2015
  Copyright: (C) 2015 by Tim Sutton
  Email: [email protected]
 ***************************************************************************
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 ***************************************************************************/

Em seguida, usamos o início das inclusões necessárias para os testes que planejamos executar. Há um especial inclui todos os testes devem ter:

#include <QtTest/QtTest>

Além disso, você apenas continua a implementar sua classe de acordo com o normal, obtendo os cabeçalhos necessários:

//Qt includes...
#include <QObject>
#include <QString>
#include <QObject>
#include <QApplication>
#include <QFileInfo>
#include <QDir>

//qgis includes...
#include <qgsrasterlayer.h>
#include <qgsrasterbandstats.h>
#include <qgsapplication.h>

Como estamos combinando declaração de classe e implementação em um único arquivo, a declaração de classe vem em seguida. Começamos com a documentação do doxygen. Cada caso de teste deve ser documentado adequadamente. Usamos a diretiva do dogengen ingroup para que todos os UnitTests apareçam como um módulo na documentação do Doxygen gerada. Depois disso vem uma breve descrição da unidade de teste e a classe deve herdar do QObject e incluir a macro Q_OBJECT.

/** \ingroup UnitTests
 * This is a unit test for the QgsRasterLayer class.
 */

class TestQgsRasterLayer: public QObject
{
    Q_OBJECT

Todos os nossos métodos de teste são implementados como slots privados. O framework QtTest irá chamar sequencialmente cada método de slot privado na classe de teste. Existem quatro métodos ‘especiais’ que, se implementados, serão chamados no início de unidade de teste (initTestCase), no final do teste unitário (cleanupTestCase). Antes de cada método de teste ser chamado, o método init () será chamado e depois que cada método de teste for chamado, o método cleanup () será chamado. Esses métodos são úteis, pois permitem alocar e limpar recursos antes de executar cada teste e a unidade de teste como um todo.

private slots:
  // will be called before the first testfunction is executed.
  void initTestCase();
  // will be called after the last testfunction was executed.
  void cleanupTestCase(){};
  // will be called before each testfunction is executed.
  void init(){};
  // will be called after every testfunction.
  void cleanup();

Em seguida, vêm os seus métodos de teste, os quais não devem ter parâmetros e devem ser anulados. Os métodos serão chamados em ordem de declaração. Estou implementando dois métodos aqui que ilustram dois tipos de testes. No primeiro caso, eu quero testar geralmente as várias partes da classe estão trabalhando, eu posso usar uma abordagem de teste funcional. Mais uma vez, programadores extremos recomendariam escrever esses testes antes de implementar a aula. Então, à medida que você trabalha na sua implementação de classe, você executa iterativamente seus testes de unidade. Mais e mais funções de teste devem ser concluídas com sucesso à medida que o trabalho de implementação da classe progride, e quando todo a unidade de teste passa, sua nova classe é feita e agora está completa com uma maneira repetível de validá-la.

Normalmente, seus testes de unidade cobririam apenas a API pública de sua classe e, normalmente, você não precisa escrever testes para acessadores e mutadores. Se acontecer de um acccessor ou um mutador não estar funcionando como esperado, você normalmente implementaria um teste de regressão para checar isso (veja abaixo).

//
// Functional Testing
//

/** Check if a raster is valid. */
void isValid();

// more functional tests here ...

Em seguida, implementamos nossos testes de regressão. Testes de regressão devem ser implementados para replicar as condições de um bug específico. Por exemplo, recebi recentemente um relatório por e-mail dizendo que a contagem de células por rasters estava em 1, eliminando todas as estatísticas das bandas de varredura. Eu abri um bug (ticket # 832) e, em seguida, criei um teste de regressão que replicou o bug usando um pequeno conjunto de dados de teste (10x10 raster). Em seguida, executei o teste e executei-o, verificando se ele realmente falhava (a contagem de células era 99 em vez de 100). Então eu fui consertar o bug e reran a unidade de teste e o teste de regressão passou. Eu cometi o teste de regressão junto com a correção do bug. Agora, se alguém quebrar isso no código fonte novamente no futuro, podemos identificar imediatamente que o código regrediu. Melhor ainda antes de cometer quaisquer alterações no futuro, a execução dos nossos testes garantirá que nossas alterações não tenham efeitos colaterais inesperados, como quebrar a funcionalidade existente.

Há mais um benefício nos testes de regressão - eles podem economizar seu tempo. Se você corrigiu um bug que envolvia fazer alterações na fonte e, em seguida, executar a aplicação e executar uma série de etapas complicadas para replicar o problema, será imediatamente aparente que simplesmente implementar seu teste de regressão antes de corrigir o bug permitirá que você automatize o teste para resolução de bug de uma maneira eficiente.

Para implementar seu teste de regressão, você deve seguir a convenção de nomenclatura de regressão<TicketID> para suas funções de teste. Se não houver nenhum ticket vermelho para a regressão, você deve criar um primeiro. Usar essa abordagem permite que a pessoa que está executando um teste de regressão com falha acesse facilmente e descubra mais informações.

//
// Regression Testing
//

/** This is our second test case...to check if a raster
 *  reports its dimensions properly. It is a regression test
 *  for ticket #832 which was fixed with change r7650.
 */
void regression832();

// more regression tests go here ...

Finalmente, em nossa declaração de classe de teste, você pode declarar de maneira particular quaisquer membros de dados e métodos auxiliares que seu teste de unidade possa precisar. No nosso caso, eu declararei um QgsRasterLayer * que pode ser usado por qualquer um dos nossos métodos de teste. A camada de rasterização será criada na função initTestCase (), que é executada antes de qualquer outro teste, e depois destruída usando cleanupTestCase (), que é executado após todos os testes. Ao declarar métodos auxiliares (que podem ser chamados por várias funções de teste) de forma privada, você pode garantir que eles não sejam executados automaticamente pelo executável do QTest que é criado quando compilamos nosso teste.

  private:
    // Here we have any data structures that may need to
    // be used in many test cases.
    QgsRasterLayer * mpLayer;
};

Isso termina nossa declaração de classe. A implementação é simplesmente embutida no mesmo arquivo mais abaixo. Primeiro nossas funções de inicialização e limpeza:

void TestQgsRasterLayer::initTestCase()
{
  // init QGIS's paths - true means that all path will be inited from prefix
  QString qgisPath = QCoreApplication::applicationDirPath ();
  QgsApplication::setPrefixPath(qgisPath, TRUE);
#ifdef Q_OS_LINUX
  QgsApplication::setPkgDataPath(qgisPath + "/../share/qgis");
#endif
  //create some objects that will be used in all tests...

  std::cout << "PrefixPATH: " << QgsApplication::prefixPath().toLocal8Bit().data() << std::endl;
  std::cout << "PluginPATH: " << QgsApplication::pluginPath().toLocal8Bit().data() << std::endl;
  std::cout << "PkgData PATH: " << QgsApplication::pkgDataPath().toLocal8Bit().data() << std::endl;
  std::cout << "User DB PATH: " << QgsApplication::qgisUserDbFilePath().toLocal8Bit().data() << std::endl;

  //create a raster layer that will be used in all tests...
  QString myFileName (TEST_DATA_DIR); //defined in CmakeLists.txt
  myFileName = myFileName + QDir::separator() + "tenbytenraster.asc";
  QFileInfo myRasterFileInfo ( myFileName );
  mpLayer = new QgsRasterLayer ( myRasterFileInfo.filePath(),
  myRasterFileInfo.completeBaseName() );
}

void TestQgsRasterLayer::cleanupTestCase()
{
  delete mpLayer;
}

A função init acima ilustra algumas coisas interessantes.

  1. Eu precisava estabelecer manualmente o caminho de dados da aplicação QGIS para que recursos como srs.db pudessem ser localizados corretamente.
  2. Em segundo lugar, este é um teste orientado por dados, então precisamos fornecer uma maneira de localizar genericamente o arquivo `` tenbytenraster.asc``. Isto foi conseguido usando o compilador de definir `` TEST_DATA_PATH``. A definição é criada no arquivo de configuração `` CMakeLists.txt`` em <QGIS Source Root>/ tests/CMakeLists.txt e está disponível para todos os testes unitários do QGIS. Se você precisar de dados de teste para o seu teste, envie-o sob <QGIS Source Root>/tests /testdata. Você deve apenas confirmar conjunto de dados muito pequenos aqui. Se o seu teste precisar modificar os dados do teste, ele deverá fazer uma cópia primeiro.

O Qt também fornece alguns outros mecanismos interessantes para testes baseados em dados, portanto, se você estiver interessado em saber mais sobre o assunto, consulte a documentação do Qt.

Em seguida, vamos ver nosso teste funcional. O teste isValid () simplesmente verifica se a camada raster foi carregada corretamente no initTestCase. QVERIFY é uma macro Qt que você pode usar para avaliar uma condição de teste. Existem outras macros de uso que o Qt fornece para uso em seus testes, incluindo:

  • QCOMPARE (real, esperado)
  • QEXPECT_FAIL (índice de dados, comentário, modo)
  • QFAIL (mensagem)
  • QFETCH (tipo, nome)
  • QFETCH (tipo, nome)
  • QTEST (atual, testElement)
  • QTEST_APPLESS_MAIN (TestClass)
  • QTEST_MAIN ( TestClass )
  • QTEST_NOOP_MAIN ()
  • QVERIFY2 (condição, mensagem)
  • QVERIFY ( condição )
  • QWARN ( menssagem )

Algumas dessas macros são úteis apenas quando se usa o framework Qt para testes baseados em dados (veja os documentos do Qt para mais detalhes).

void TestQgsRasterLayer::isValid()
{
  QVERIFY ( mpLayer->isValid() );
}

Normalmente, seus testes funcionais cobririam toda a gama de funcionalidades da API pública de suas classes, sempre que viável. Com nossos testes funcionais fora do caminho, podemos ver nosso exemplo de teste de regressão.

Como o problema no bug # 832 é uma contagem de célula incorreta, escrever nosso teste é simplesmente uma questão de usar QVERIFY para checar se a contagem de célula atende ao valor esperado:

void TestQgsRasterLayer::regression832()
{
  QVERIFY ( mpLayer->getRasterXDim() == 10 );
  QVERIFY ( mpLayer->getRasterYDim() == 10 );
  // regression check for ticket #832
  // note getRasterBandStats call is base 1
  QVERIFY ( mpLayer->getRasterBandStats(1).elementCountInt == 100 );
}

Com todas as funções da unidade de teste implementadas, há uma última coisa que precisamos adicionar à nossa classe de teste:

QTEST_MAIN(TestQgsRasterLayer)
#include "testqgsrasterlayer.moc"

O propósito destas duas linhas é sinalizar ao moc de Qt que ele é um QtTest (ele irá gerar um método principal que por sua vez chama cada função de teste. A última linha é a inclusão para as fontes geradas pelo MOC. Você deve substituir ‘testqgsrasterlayer’ com o nome da sua classe em minúsculas.

Adicionando sua unidade de teste ao CMakeLists.txt

Adicionar sua Unidade de teste ao sistema de compilação é simplesmente uma questão de editar o CMakeLists.txt no diretório de teste, clonar um dos blocos de teste existentes e, em seguida, substituir o nome da classe de teste nele. Por exemplo:

# QgsRasterLayer test
ADD_QGIS_TEST(rasterlayertest testqgsrasterlayer.cpp)

A macro ADD_QGIS_TEST explicada

Eu vou executar essas linhas brevemente para explicar o que eles fazem, mas se você não estiver interessado, apenas faça o passo explicado na seção e seção acima.

MACRO (ADD_QGIS_TEST testname testsrc)
SET(qgis_${testname}_SRCS ${testsrc} ${util_SRCS})
SET(qgis_${testname}_MOC_CPPS ${testsrc})
QT4_WRAP_CPP(qgis_${testname}_MOC_SRCS ${qgis_${testname}_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_${testname}moc ALL DEPENDS ${qgis_${testname}_MOC_SRCS})
ADD_EXECUTABLE(qgis_${testname} ${qgis_${testname}_SRCS})
ADD_DEPENDENCIES(qgis_${testname} qgis_${testname}moc)
TARGET_LINK_LIBRARIES(qgis_${testname} ${QT_LIBRARIES} qgis_core)
SET_TARGET_PROPERTIES(qgis_${testname}
PROPERTIES
# skip the full RPATH for the build tree
SKIP_BUILD_RPATHTRUE
# when building, use the install RPATH already
# (so it doesn't need to relink when installing)
BUILD_WITH_INSTALL_RPATH TRUE
# the RPATH to be used when installing
INSTALL_RPATH ${QGIS_LIB_DIR}
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
INSTALL_RPATH_USE_LINK_PATH true)
IF (APPLE)
# For Mac OS X, the executable must be at the root of the bundle's executable folder
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/qgis_${testname})
ELSE (APPLE)
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/bin/qgis_${testname})
ENDIF (APPLE)
ENDMACRO (ADD_QGIS_TEST)

Vamos olhar um pouco mais detalhadamente nas linhas individuais. Primeiro definimos a lista de fontes para o nosso teste. Já que temos apenas um arquivo fonte (seguindo a metodologia que descrevi acima onde a declaração e definição de classe estão no mesmo arquivo) é uma simples declaração:

SET(qgis_${testname}_SRCS ${testsrc} ${util_SRCS})

Como nossa classe de teste precisa ser executada através do compilador de objeto meta Qt (moc), precisamos fornecer algumas linhas para que isso aconteça também:

SET(qgis_${testname}_MOC_CPPS ${testsrc})
QT4_WRAP_CPP(qgis_${testname}_MOC_SRCS ${qgis_${testname}_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_${testname}moc ALL DEPENDS ${qgis_${testname}_MOC_SRCS})

Em seguida, dizemos ao cmake que ele deve criar um executável a partir da classe de teste. Lembre-se, na seção anterior sobre a última linha da implementação da classe, incluí as saídas moc diretamente em nossa classe de teste, de modo que ela forneça (entre outras coisas) um método main para que a classe possa ser compilada como executável:

ADD_EXECUTABLE(qgis_${testname} ${qgis_${testname}_SRCS})
ADD_DEPENDENCIES(qgis_${testname} qgis_${testname}moc)

Em seguida, precisamos especificar as dependências da biblioteca. No momento, as classes foram implementadas com uma dependência QT_LIBRARIES pega-tudo, mas eu estarei trabalhando para substituir isso com as bibliotecas Qt específicas que cada classe precisa apenas. É claro que você também precisa se vincular às bibliotecas qgis relevantes, conforme exigido pela sua unidade de teste.

TARGET_LINK_LIBRARIES(qgis_${testname} ${QT_LIBRARIES} qgis_core)

Em seguida eu digo ao cmake para instalar os testes no mesmo lugar que os próprios binários qgis. Isso é algo que pretendo remover no futuro, para que os testes possam ser executados diretamente de dentro da árvore de origem.

SET_TARGET_PROPERTIES(qgis_${testname}
PROPERTIES
# skip the full RPATH for the build tree
SKIP_BUILD_RPATHTRUE
# when building, use the install RPATH already
# (so it doesn't need to relink when installing)
BUILD_WITH_INSTALL_RPATH TRUE
# the RPATH to be used when installing
INSTALL_RPATH ${QGIS_LIB_DIR}
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
INSTALL_RPATH_USE_LINK_PATH true)
IF (APPLE)
# For Mac OS X, the executable must be at the root of the bundle's executable folder
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/qgis_${testname})
ELSE (APPLE)
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/bin/qgis_${testname})
ENDIF (APPLE)

Finalmente, o acima usa `` ADD_TEST`` para registrar o teste com cmake / ctest. Aqui é onde a melhor mágica acontece - nós registramos a classe com o ctest. Se você se lembrar do panorama que dei no começo desta seção, estamos usando o QtTest e o CTest juntos. Para recapitular, o QtTest adiciona um método principal à sua unidade de teste e lida com seus métodos de teste dentro da classe. Ele também fornece algumas macros como `` QVERIFY`` que você pode usar para testar a falha dos testes usando condições. A saída de um teste de unidade do QtTest é um executável que você pode executar a partir da linha de comando. No entanto, quando você tem um conjunto de testes e deseja executar cada executável por vez e integrar melhor os testes em execução no processo de criação, o CTest é o que usamos.

Construindo sua Unidade de teste

Para construir a unidade de teste você precisa apenas certificar-se de que `` ENABLE_TESTS = true`` na configuração do cmake. Existem duas maneiras de fazer isso:

  1. Executar `` ccmake ..`` (ou `` cmakesetup ..`` no windows) e defina interativamente o sinalizador `` ENABLE_TESTS`` para `` ON``.
  2. Adicione um sinalizador de linha de comando para cmake, e. `` cmake -DENABLE_TESTS = true ..``

Além disso, basta construir o QGIS conforme o normal e os testes também devem ser compilados.

Execute seus testes

A maneira mais simples de executar os testes é como parte do seu processo de criação normal:

make && make install && make test

O comando make test invocará o CTest, o qual executará cada teste registrado usando a diretiva CMake ADD_TEST descrita acima. A saída típica do teste do make ficará assim:

Running tests...
Start processing tests
Test project /Users/tim/dev/cpp/qgis/build
## 13 Testing qgis_applicationtest***Exception: Other
## 23 Testing qgis_filewritertest *** Passed
## 33 Testing qgis_rasterlayertest*** Passed

## 0 tests passed, 3 tests failed out of 3

The following tests FAILED:
## 1- qgis_applicationtest (OTHER_FAULT)
Errors while running CTest
make: *** [test] Error 8

Se um teste falhar, você poderá usar o comando ctest para examinar mais de perto por que ele falhou. Use a opção `` -R`` para especificar um regex cujos testes você deseja executar e `` -V`` para obter uma saída detalhada:

$ ctest -R appl -V

Start processing tests
Test project /Users/tim/dev/cpp/qgis/build
Constructing a list of tests
Done constructing a list of tests
Changing directory into /Users/tim/dev/cpp/qgis/build/tests/src/core
## 13 Testing qgis_applicationtest
Test command: /Users/tim/dev/cpp/qgis/build/tests/src/core/qgis_applicationtest
********* Start testing of TestQgsApplication *********
Config: Using QTest library 4.3.0, Qt 4.3.0
PASS : TestQgsApplication::initTestCase()
PrefixPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/../
PluginPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//lib/qgis
PkgData PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis
User DB PATH: /Users/tim/.qgis/qgis.db
PASS : TestQgsApplication::getPaths()
PrefixPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/../
PluginPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//lib/qgis
PkgData PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis
User DB PATH: /Users/tim/.qgis/qgis.db
QDEBUG : TestQgsApplication::checkTheme() Checking if a theme icon exists:
QDEBUG : TestQgsApplication::checkTheme()
/Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis/themes/default//mIconProjectionDisabled.png
FAIL!: TestQgsApplication::checkTheme() '!myPixmap.isNull()' returned FALSE. ()
Loc: [/Users/tim/dev/cpp/qgis/tests/src/core/testqgsapplication.cpp(59)]
PASS : TestQgsApplication::cleanupTestCase()
Totals: 3 passed, 1 failed, 0 skipped
********* Finished testing of TestQgsApplication *********
-- Process completed
***Failed

## 0 tests passed, 1 tests failed out of 1

The following tests FAILED:
## 1- qgis_applicationtest (Failed)
Errors while running CTest

Bem, isso conclui essa seção sobre como escrever testes de unidade no QGIS. Esperamos que você tenha o hábito de escrever teste para testar novas funcionalidades e checar regressões. Alguns aspectos do sistema de teste (em particular as partes do CMakeLists.txt) ainda estão sendo trabalhados para que a estrutura de teste funcione de uma maneira verdadeiramente de plataforma. Eu irei atualizar este documento conforme as coisas progridem.