Uilian Ries
Teste Unitário com GTest e Catch
● Motivação
● Por que usar teste unitário?
● Projetos
● Gtest
○ Sobre o projeto
○ Formas de instalar
○ Exemplo
○ Prós e Contras
● Catch
○ Sobre o projeto
○ Formas de instalar
○ Exemplo
○ Prós e Contras
● Comparativo GTest x Catch
● Uso na Khomp ?
● Referências
AGENDA
● Falta de testes unitários nos projetos da Khomp
● Experiências e resultados positivos em projetos anteriores
● Aderência da comunidade aos projetos GTest e Catch
● “Test Your Software, or Your Users Will”, The Pragmatic Programmer
MOTIVAÇÃO
● Clarifica a cobertura de código
○ Unit Test + Code Coverage
● Valida a compreensão sobre o código
○ Testes podem servir como exemplo
○ Quem escreve o teste precisa compreender a API
○ Descrição das features testadas
● Ratifica novas modificações
○ Teste de regressão
○ Previne build quebrado em produção
POR QUE USAR TESTE UNITÁRIO?
PROJETOS PARA C++
● CppUnit
● Boost Test
● Google Test
● Aeryn
● Cute
● Fructose
● Catch
Lista com projetos para C++
Google Test - Google C++ Test Framework
● https://github.com/google/googletest
● Licença BSD-3
● ~55 Contribuidores
● ~406 issues
● ~178 Pull Requests
● Multiplataforma
● Utilizado pelos projetos LLVM, OpenCV, Protobuf
● Integração nativa com CMake >=3.1
● Geração de relatório XML (integração Jenkins)
Google Test
Formas de instalar
# apt-get install libgtest-dev cmake
# cd /usr/src/gtest
# cmake CMakeLists.txt
# cmake --build .
# cmake --build . --target install # Ops!
# cp *.a /usr/local/lib
- Versão estável, porém antiga
- Possui apenas os fontes
# git clone https://github.com/google/googletest.git
# cd googletest
# cmake CMakeLists.txt
# cmake --build .
# cmake --build . --target install
+ Versão estável e atualizada
- Possui apenas os fontes
$ conan install gtest/1.8.0@lasote/stable
+ Versão estável e atualizada
+ Possui binário por plataforma
+ Possui os fontes, se necessário
Google Test
Exemplo
#include <gtest/gtest.h>
int Factorial( int number ) {
return number > 1 ? Factorial(number-1)*number : 1;
}
TEST(FactorialTest, Positive) {
EXPECT_EQ(1, Factorial(1));
EXPECT_TRUE(2 = Factorial(2));
EXPECT_NOT_EQ(42, Factorial(3));
EXPECT_FALSE(40320 != Factorial(8));
}
class TestString: public ::testing::test {
public:
void SetUp( ) { string_.Assign("Hello"); }
void TearDown( ) {
string_.Clear();
ASSERT_TRUE(string_.Empty())
}
MyString string_;
};
TEST_F(TestString, EraseString) {
ASSERT_EQ("Hello", string_.Get());
}
Google Test
Formas de construir
Google Test
Formas de construir
MANUAL
$ gcc test.cpp -lpthread -lgtest -lgtest_main
● Pthread é dependencia do GTest
● gtest_main fornece a função main()
Google Test
Formas de construir
CMAKE >=3.0.2
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(foo foo.cpp)
target_link_libraries(foo ${GTEST_BOTH_LIBRARIES})
Google Test
Formas de construir
CMAKE >=3.0.2
enable_testing()
add_executable(Foo foo.cpp)
add_test(test-foo foo)
OU
GTEST_ADD_TESTS(foo foo.cpp)
Google Test
Formas de construir
CONAN
# conanfile.txt
[requires]
gtest/1.8.0@lasote/stable
[generators]
cmake
# CMakeLists.txt
add_executable(foo foo.cpp)
target_link_libraries(foo ${CONAN_LIBS})
Google Test
Formas de construir
OUTPUT - ASCIINEMA
Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from TestingEncryption
[ RUN ] TestingEncryption.cipher
[ OK ] TestingEncryption.cipher (2 ms)
[----------] 1 test from TestingEncryption (2 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (2 ms total)
[ PASSED ] 1 test.
Google Test
Formas de construir
Google Test
Prós e contras
Google Test
Formas de construir
● Prós
○ Gama de plugins (jenkins, clion, CDT, cmake)
○ Saída XML (jenkins)
○ Google Mock
○ Gamma de assert (ASSERT_…)
○ Portabilidade
○ Boa opção para TDD
● Contras
○ Valgrind falso-positivos
Catch - C++ Automated Test Cases in Headers
● https://github.com/philsquared/Catch
● Licença BSL-1.0
● ~89 Contribuidores
● ~108 Issues
● ~20 Pull Requests
● Header only
● Utilizado pelos projetos Trompeloeil, ChaiScript
● Integração nativa com CLion
● Uso em TDD e BDD
Catch
Formas de instalar
# apt-get install catch
- Versão estável, porém antiga
# wget
https://github.com/philsquared/Catch/releases/download/
v1.9.6/catch.hpp -O /usr/local/include/catch.hpp
+ Versão estável e atualizada
$ conan install Catch/1.9.5@uilianries/stable
+ Versão estável e atualizada
Catch
Exemplo
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
unsigned int Factorial( unsigned int number ) {
return number > 1 ? Factorial(number-1)*number : 1;
}
TEST_CASE( "Factorials are computed", "[factorial]" ) {
REQUIRE( Factorial(0) == 1 );
REQUIRE( Factorial(1) == 1 );
REQUIRE( Factorial(2) == 2 );
REQUIRE( Factorial(3) == 6 );
REQUIRE( Factorial(10) == 3628800 );
}
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
SECTION( "resizing bigger changes size and capacity" ) {
v.resize( 10 );
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
v.clear();
}
Set Up
Tear Down
SCENARIO( "vectors can be sized and resized", "[vector]" ) {
GIVEN( "A vector with some items" ) {
std::vector<int> v( 5 );
REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 5 );
WHEN( "the size is increased" ) {
v.resize( 10 );
THEN( "the size and capacity change" ) {
REQUIRE( v.size() == 10 );
REQUIRE( v.capacity() >= 10 );
}
}
Catch
Formas de construir
Google Test
Formas de construir
MANUAL
$ gcc test.cpp
● CATCH_CONFIG_MAIN deve ser declarado somente uma vez
Google Test
Formas de construir
CONAN
# conanfile.txt
[requires]
Catch/1.9.5@uilianries/stable
[generators]
cmake
# CMakeLists.txt
enable_testing()
add_executable(foo foo.cpp)
add_test(test-foo foo)
Google Test
Formas de construir
OUTPUT - ASCIINEMA
------------------------------------------------------------------------------
Scenario: vectors can be sized and resized
Given: A vector with some items
When: the size is increased
Then: the size and capacity change
...............................................................................
PASSED:
REQUIRE( v.size() == 10 )
with expansion:
10 == 10
Google Test
Formas de construir
Catch
Prós e contras
Google Test
Formas de construir
● Prós
○ Gama de plugins (Jenkins, CLion, CMake)
○ Saída JUnit (Jenkins)
○ Gamma de assert (ASSERT_…)
○ Decomposição de expressão
○ Boa opção para TDD e BDD
● Contras
○ Não possui Mock
○ Incremento de tempo durante build (~3 seg)
Comparativo GTest x Catch
GTEST
● Largamente utilizada
● Multíplos tipos de assert
● Compila até no GCC-4.1
● Gera report XML
CATCH
● Header Only
● TDD e BDD
● Gera report JUnit
● Compila até no GCC-4.1
REFERÊNCIAS
● Exploring the C++ Unit Testing Framework Jungle
● A quick introduction to the Google C++ Testing Framework
● Test your project with Google Test
● Testing C++ With A New Catch
● CppCon 2015: Phil Nash “Test Driven C++ with Catch”
Dúvidas?
Perguntas?
Curiosidades?

Testes Unitários com GTest e Catch

  • 1.
    Uilian Ries Teste Unitáriocom GTest e Catch
  • 2.
    ● Motivação ● Porque usar teste unitário? ● Projetos ● Gtest ○ Sobre o projeto ○ Formas de instalar ○ Exemplo ○ Prós e Contras ● Catch ○ Sobre o projeto ○ Formas de instalar ○ Exemplo ○ Prós e Contras ● Comparativo GTest x Catch ● Uso na Khomp ? ● Referências AGENDA
  • 3.
    ● Falta detestes unitários nos projetos da Khomp ● Experiências e resultados positivos em projetos anteriores ● Aderência da comunidade aos projetos GTest e Catch ● “Test Your Software, or Your Users Will”, The Pragmatic Programmer MOTIVAÇÃO
  • 4.
    ● Clarifica acobertura de código ○ Unit Test + Code Coverage ● Valida a compreensão sobre o código ○ Testes podem servir como exemplo ○ Quem escreve o teste precisa compreender a API ○ Descrição das features testadas ● Ratifica novas modificações ○ Teste de regressão ○ Previne build quebrado em produção POR QUE USAR TESTE UNITÁRIO?
  • 5.
    PROJETOS PARA C++ ●CppUnit ● Boost Test ● Google Test ● Aeryn ● Cute ● Fructose ● Catch Lista com projetos para C++
  • 6.
    Google Test -Google C++ Test Framework ● https://github.com/google/googletest ● Licença BSD-3 ● ~55 Contribuidores ● ~406 issues ● ~178 Pull Requests ● Multiplataforma ● Utilizado pelos projetos LLVM, OpenCV, Protobuf ● Integração nativa com CMake >=3.1 ● Geração de relatório XML (integração Jenkins)
  • 7.
  • 8.
    # apt-get installlibgtest-dev cmake # cd /usr/src/gtest # cmake CMakeLists.txt # cmake --build . # cmake --build . --target install # Ops! # cp *.a /usr/local/lib - Versão estável, porém antiga - Possui apenas os fontes
  • 9.
    # git clonehttps://github.com/google/googletest.git # cd googletest # cmake CMakeLists.txt # cmake --build . # cmake --build . --target install + Versão estável e atualizada - Possui apenas os fontes
  • 10.
    $ conan installgtest/1.8.0@lasote/stable + Versão estável e atualizada + Possui binário por plataforma + Possui os fontes, se necessário
  • 11.
  • 12.
    #include <gtest/gtest.h> int Factorial(int number ) { return number > 1 ? Factorial(number-1)*number : 1; } TEST(FactorialTest, Positive) { EXPECT_EQ(1, Factorial(1)); EXPECT_TRUE(2 = Factorial(2)); EXPECT_NOT_EQ(42, Factorial(3)); EXPECT_FALSE(40320 != Factorial(8)); }
  • 13.
    class TestString: public::testing::test { public: void SetUp( ) { string_.Assign("Hello"); } void TearDown( ) { string_.Clear(); ASSERT_TRUE(string_.Empty()) } MyString string_; }; TEST_F(TestString, EraseString) { ASSERT_EQ("Hello", string_.Get()); }
  • 14.
  • 15.
    Google Test Formas deconstruir MANUAL $ gcc test.cpp -lpthread -lgtest -lgtest_main ● Pthread é dependencia do GTest ● gtest_main fornece a função main()
  • 16.
    Google Test Formas deconstruir CMAKE >=3.0.2 find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) add_executable(foo foo.cpp) target_link_libraries(foo ${GTEST_BOTH_LIBRARIES})
  • 17.
    Google Test Formas deconstruir CMAKE >=3.0.2 enable_testing() add_executable(Foo foo.cpp) add_test(test-foo foo) OU GTEST_ADD_TESTS(foo foo.cpp)
  • 18.
    Google Test Formas deconstruir CONAN # conanfile.txt [requires] gtest/1.8.0@lasote/stable [generators] cmake # CMakeLists.txt add_executable(foo foo.cpp) target_link_libraries(foo ${CONAN_LIBS})
  • 19.
    Google Test Formas deconstruir OUTPUT - ASCIINEMA Running main() from gtest_main.cc [==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 test from TestingEncryption [ RUN ] TestingEncryption.cipher [ OK ] TestingEncryption.cipher (2 ms) [----------] 1 test from TestingEncryption (2 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (2 ms total) [ PASSED ] 1 test.
  • 20.
    Google Test Formas deconstruir Google Test Prós e contras
  • 21.
    Google Test Formas deconstruir ● Prós ○ Gama de plugins (jenkins, clion, CDT, cmake) ○ Saída XML (jenkins) ○ Google Mock ○ Gamma de assert (ASSERT_…) ○ Portabilidade ○ Boa opção para TDD ● Contras ○ Valgrind falso-positivos
  • 22.
    Catch - C++Automated Test Cases in Headers ● https://github.com/philsquared/Catch ● Licença BSL-1.0 ● ~89 Contribuidores ● ~108 Issues ● ~20 Pull Requests ● Header only ● Utilizado pelos projetos Trompeloeil, ChaiScript ● Integração nativa com CLion ● Uso em TDD e BDD
  • 23.
  • 24.
    # apt-get installcatch - Versão estável, porém antiga
  • 25.
    # wget https://github.com/philsquared/Catch/releases/download/ v1.9.6/catch.hpp -O/usr/local/include/catch.hpp + Versão estável e atualizada
  • 26.
    $ conan installCatch/1.9.5@uilianries/stable + Versão estável e atualizada
  • 27.
  • 28.
    #define CATCH_CONFIG_MAIN #include <catch.hpp> unsignedint Factorial( unsigned int number ) { return number > 1 ? Factorial(number-1)*number : 1; } TEST_CASE( "Factorials are computed", "[factorial]" ) { REQUIRE( Factorial(0) == 1 ); REQUIRE( Factorial(1) == 1 ); REQUIRE( Factorial(2) == 2 ); REQUIRE( Factorial(3) == 6 ); REQUIRE( Factorial(10) == 3628800 ); }
  • 29.
    #define CATCH_CONFIG_MAIN #include <catch.hpp> TEST_CASE("vectors can be sized and resized", "[vector]" ) { std::vector<int> v( 5 ); REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 5 ); SECTION( "resizing bigger changes size and capacity" ) { v.resize( 10 ); REQUIRE( v.size() == 10 ); REQUIRE( v.capacity() >= 10 ); } v.clear(); } Set Up Tear Down
  • 30.
    SCENARIO( "vectors canbe sized and resized", "[vector]" ) { GIVEN( "A vector with some items" ) { std::vector<int> v( 5 ); REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 5 ); WHEN( "the size is increased" ) { v.resize( 10 ); THEN( "the size and capacity change" ) { REQUIRE( v.size() == 10 ); REQUIRE( v.capacity() >= 10 ); } }
  • 31.
  • 32.
    Google Test Formas deconstruir MANUAL $ gcc test.cpp ● CATCH_CONFIG_MAIN deve ser declarado somente uma vez
  • 33.
    Google Test Formas deconstruir CONAN # conanfile.txt [requires] Catch/1.9.5@uilianries/stable [generators] cmake # CMakeLists.txt enable_testing() add_executable(foo foo.cpp) add_test(test-foo foo)
  • 34.
    Google Test Formas deconstruir OUTPUT - ASCIINEMA ------------------------------------------------------------------------------ Scenario: vectors can be sized and resized Given: A vector with some items When: the size is increased Then: the size and capacity change ............................................................................... PASSED: REQUIRE( v.size() == 10 ) with expansion: 10 == 10
  • 35.
    Google Test Formas deconstruir Catch Prós e contras
  • 36.
    Google Test Formas deconstruir ● Prós ○ Gama de plugins (Jenkins, CLion, CMake) ○ Saída JUnit (Jenkins) ○ Gamma de assert (ASSERT_…) ○ Decomposição de expressão ○ Boa opção para TDD e BDD ● Contras ○ Não possui Mock ○ Incremento de tempo durante build (~3 seg)
  • 37.
  • 38.
    GTEST ● Largamente utilizada ●Multíplos tipos de assert ● Compila até no GCC-4.1 ● Gera report XML CATCH ● Header Only ● TDD e BDD ● Gera report JUnit ● Compila até no GCC-4.1
  • 39.
    REFERÊNCIAS ● Exploring theC++ Unit Testing Framework Jungle ● A quick introduction to the Google C++ Testing Framework ● Test your project with Google Test ● Testing C++ With A New Catch ● CppCon 2015: Phil Nash “Test Driven C++ with Catch”
  • 40.