Google Test + gcover

Google Test + gcover Una lista de recetas

J. Daniel Garcia

Grupo ARCOS Universidad Carlos III de Madrid

19 de noviembre de 2016

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 1/68 Google Test + gcover

Aviso

c Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivar 4.0 Internacional. b Debes dar crédito en la obra en la forma especificada por el autor o licenciante. e El licenciante permite copiar, distribuir y comunicar pú- blicamente la obra. A cambio, esta obra no puede ser utilizada con fines comerciales — a menos que se ob- tenga el permiso expreso del licenciante. d El licenciante permite copiar, distribuir, transmitir y co- municar públicamente solamente copias inalteradas de la obra – no obras derivadas basadas en ella.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 2/68 Google Test + gcover

ARCOS@uc3m

UC3M: Una universidad joven, internacional y orientada a la investigación. ARCOS: Un grupo de investigación aplicada. Líneas: Computación de altas prestaciones, Big data, Sistemas Ciberfísicos, y Modelos de programación para la mejora de las aplicaciones Mejorando las aplicaciones: REPARA: Reengineering and Enabling Performance and poweR of Applications. Financiado por Comisión Europea (FP7). RePhrase: REfactoring Parallel Heterogeneous Resource Aware Applications. Financiado por Comisión Europea (H2020). Normalización: ISO/IEC JTC/SC22/WG21. Comité ISO C++. cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 3/68 Google Test + gcover

¿Te interesa C++?

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 4/68 Google Test + gcover Pruebas básicas

1 Pruebas básicas

2 Determinando la cobertura

3 Más pruebas unitarias

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 5/68 Google Test + gcover Pruebas básicas Introducción

1 Pruebas básicas Introducción Ejemplo 1: vectint Usando CMake Mis primeras pruebas

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 6/68 Google Test + gcover Pruebas básicas Introducción Ejemplos

Puedes obtener todos los ejemplos en:

https://github.com/jdgarciauc3m/gtesttalk

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 7/68 Google Test + gcover Pruebas básicas Introducción ¿Qué es Google Test?

Es una biblioteca para realizar pruebas unitarias en C++.

Características: Un framework tipo xUnit. Descubrimiento de tests. Variedad de aserciones. Aserciones definidas por el usuario. Death tests. Fallos fatales y no fatales. Tests parametrizados por valor. Tests parametrizados por tipo. Múltiples opciones de ejecución. Generación de informes en XML.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 8/68 Google Test + gcover Pruebas básicas Introducción Uso

Plataformas: Mac OS X Windows Cygwin MinGW Windows Mobile Symbian

Algunos proyectos que lo usan: Proyecto . Familia de compiladores LLVM. . OpenCV.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 9/68 Google Test + gcover Pruebas básicas Introducción Principios

1 Las pruebas deberían ser independientes y repetibles. 2 Las pruebas deberían poder estar bien estructuradas. 3 Las pruebas deberían ser portables y reusables. 4 Ante un fallo en una prueba se debería poder obtener la máxima información. 5 No debería ser necesario escribir código innecesario para pruebas. 6 Las pruebas deberían ser rápidas.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 10/68 Google Test + gcover Pruebas básicas Introducción ¿Como obtener GTest?

Repositorio en GitHub. https://github.com/google/googletest

Se puede obtener como paquete (Ubuntu/Linux). Paquete: libgtest-dev. Importante: No instala binarios, solamente fuentes.

$ apt-get install libgtest-dev $ cd /usr/src/gtest $ sudo mkdir build $ cd build $ sudo cmake.. $ sudo make $ sudo cp *.a/usr/lib

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 11/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint

1 Pruebas básicas Introducción Ejemplo 1: vectint Usando CMake Mis primeras pruebas

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 12/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Un vector de enteros

Comencemos con una clase sencilla Un vector de enteros con comportamiento mínimo: Un vector de enteros con tamaño (size()) y capacidad (capacity()). Versión mínima que soporte copia y movimiento. Acceso operator[]. Modificación de capacidad (reserve()). Modificación de tamaño (resize()).

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 13/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Interfaz

include/vectint.h

#ifndef DCL_VECTINT_H #define DCL_VECTINT_H

#include

namespace dcl{ // Dummy Container Library

class vectint{ public: vectint(): capacity_{0}, size_{0}, buffer_{ nullptr} {} vectint( int n);

vectint( const vectint&v); vectint& operator=(const vectint&v);

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 14/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Interfaz

include/vectint.h

int & operator[](int i){ return buffer_[i];} int operator[](int i) const { return buffer_[i];}

int capacity() const { return capacity_;} int size() const { return size_;}

void reserve(int n); void resize( int n);

friend std:: ostream& operator<<(std::ostream& os, const vectint&v);

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 15/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Interfaz

include/vectint.h

private: int capacity_; int size_; std:: unique_ptr< int[]> buffer_; };

} // end dcl namespace

#endif

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 16/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Implementación

src/vectint.cpp

#include "vectint.h" #include #include

namespace dcl{

vectint :: vectint( int n): capacity_{n}, size_{n}, buffer_{std:: make_unique< int[]>(n)} {}

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 17/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Implementación

src/vectint.cpp

vectint:: vectint( const vectint&v): capacity_{v.capacity_}, size_{v.size_}, buffer_{std:: make_unique< int[]>(size_)} { std:: copy_n(v.buffer_.get(),v.size_, buffer_.get()); }

vectint& vectint:: operator=(const vectint&v){ buffer_= std:: make_unique< int[]>(v.size_); capacity_=v.capacity_; size_=v.size_; std:: copy_n(v.buffer_.get(),v.size_, buffer_.get()); return ∗this; }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 18/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Implementación

src/vectint.cpp

void vectint:: resize( int n) { if (n>capacity_) reserve(n); if (n>size_){ std:: fill_n(buffer_.get()+size_, buffer_.get()+n, 0); } size_=n; }

void vectint:: reserve( int n) { if (n <= capacity_) return; auto buf= std:: make_unique< int[]>(n); std:: copy_n(buffer_.get(), size_, buf.get()); capacity_=n; }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 19/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Implementación

src/vectint.cpp

std:: ostream& operator<<(std::ostream& os, const vectint&v) { std:: copy(v.buffer_.get(),v.buffer_.get()+v.size_, std:: ostream_iterator< int>{os,""}); return os; }

} // Namespace

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 20/68 Google Test + gcover Pruebas básicas Ejemplo 1: vectint Programa de prueba

samples/main1.cpp samples/main1.cpp

#include "vectint.h" #include cout <<"v:" <

vectintw{v}; return 0; w[1] = 3; } w.resize(4);

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 21/68 Google Test + gcover Pruebas básicas Usando CMake

1 Pruebas básicas Introducción Ejemplo 1: vectint Usando CMake Mis primeras pruebas

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 22/68 Google Test + gcover Pruebas básicas Usando CMake ¿Qué es CMake

Es un conjunto de herramientas que permite construir, probar y empaquetar software. A partir de un proyecto CMake se pueden generar scripts de construcción para cada plataforma. Generadores: Makefiles (Unix, Borland, MinGW, NMake). Ninja. Visual Studio. Xcode. Varios IDE: CodeBlocks, CodeLite, EclipseCDT, KDevelop. IDE con soporte nativo: CLion, Visual Studio 2017 RC1.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 23/68 Google Test + gcover Pruebas básicas Usando CMake CMake raíz

CMakeLists.txt

cmake_minimum_required(VERSION 3.0) set(PROJECT_NAME_STR vectint) project(${PROJECT_NAME_STR})

# Local project include directory include_directories("${CMAKE_SOURCE_DIR}/include")

# Build binary directory set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

set(WARNFLAGS "-Wall -Wextra -Wno-deprecated -Werror -pedantic -pedantic-errors")

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") list(APPEND CMAKE_CXX_FLAGS "-std=c++14 -stdlib=libstdc++ ${WARNFLAGS}") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") list(APPEND CMAKE_CXX_FLAGS "${WARNFLAGS}") else() message(FATAL_ERROR "Unsupported compiler") endif()

#Process subdirectories add_subdirectory(src) add_subdirectory(samples) cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 24/68 Google Test + gcover Pruebas básicas Usando CMake CMake para src

src/CMakeLists.txt

add_library(dcl vectint.cpp)

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 25/68 Google Test + gcover Pruebas básicas Usando CMake CMake para samples

samples/CMakeLists.txt

add_executable(test1 main1.cpp) target_link_libraries(test1 dcl)

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 26/68 Google Test + gcover Pruebas básicas Usando CMake Construyendo con CMake

jdgarcia@gavilan:~/vector1$ mkdir build jdgarcia@gavilan:~/vector1$ cd build/ jdgarcia@gavilan:~/vector1/build$ cmake.. -- TheC compiler identification is GNU 6.2.0 -- The CXX compiler identification is GNU 6.2.0 -- Check for workingC compiler:/usr/bin/cc -- Check for workingC compiler:/usr/bin/cc-- works -- DetectingC compiler ABI info -- DetectingC compiler ABI info- done -- Check for working CXX compiler:/usr/bin/c++ -- Check for working CXX compiler:/usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info- done -- Configuring done -- Generating done -- Build have been written to:/home/jdgarcia/vector1/build

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 27/68 Google Test + gcover Pruebas básicas Usando CMake ¿Y si quiero elegir el compilador?

jdgarcia@gavilan:~//vector1/build$ cmake..-DCMAKE_CXX_COMPILER=clang++ - DCMAKE_C_COMPILER=clang -- Configuring done You have changed variables that require your cache to be deleted. Configure will be re-run and you may have to reset some variables. The following variables have changed: CMAKE_C_COMPILER= clang CMAKE_CXX_COMPILER= clang++

-- TheC compiler identification is Clang 3.8.0 -- The CXX compiler identification is Clang 3.8.0 -- Check for workingC compiler:/usr/bin/clang -- Check for workingC compiler:/usr/bin/clang-- works -- DetectingC compiler ABI info -- DetectingC compiler ABI info- done -- Check for working CXX compiler:/usr/bin/clang++ -- Check for working CXX compiler:/usr/bin/clang++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info- done -- Configuring done -- Generating done -- Build files have been written to:/home/jdgarcia//vector1/build

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 28/68 Google Test + gcover Pruebas básicas Usando CMake Proceso de compilación

jdgarcia@gavilan:~/vector1/build$ make Scanning dependencies of target dcl [ 50 %] Building CXX object src/CMakeFiles/dcl.dir/vectint.cpp.o Linking CXX static library libdcl.a [ 50 %] Built target dcl Scanning dependencies of target test1 [100 %] Building CXX object samples/CMakeFiles/test1.dir/main1.cpp.o Linking CXX executable ../test1 [100 %] Built target test1

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 29/68 Google Test + gcover Pruebas básicas Mis primeras pruebas

1 Pruebas básicas Introducción Ejemplo 1: vectint Usando CMake Mis primeras pruebas

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 30/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Casos de pruebas y pruebas

En GTest podemos definir pruebas y agruparlas en casos de prueba. Hacemos uso de la macro TEST. Caso de prueba (test case): Prueba elemental. Prueba: Cada una de las pruebas de un caso de prueba.

Realización de comprobaciones: EXPECT_EQ: Comprobación no fatal. ASSERT_EQ: Comprobación no fatal.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 31/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Probando la construcción

utest/vectint_constructor.cpp

#include "vectint.h" #include

TEST(vectint_constructor, empty) { dcl:: vectintv; EXPECT_EQ(0,v.size()); EXPECT_EQ(0,v.capacity()); }

TEST(vectint_constructor, sized) { dcl:: vectintv{10}; EXPECT_EQ(10,v.size()); EXPECT_EQ(10,v.capacity()); } cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 32/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Ejecutando las pruebas

jdgarcia@gavilan:~/vector2/build$./vectint_utest Running main() from gtest_main.cc [======] Running2 tests from1 test case. [------] Global test environment set-up. [------] 2 tests from vectint_constructor [ RUN] vectint_constructor.empty [OK] vectint_constructor.empty (0 ms) [ RUN] vectint_constructor.sized [OK] vectint_constructor.sized (0 ms) [------] 2 tests from vectint_constructor (0 ms total)

[------] Global test environment tear-down [======] 2 tests from1 test case ran. (0 ms total) [ PASSED]2 tests.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 33/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Comprobando la copia

utest/vectint_copy.cpp utest/vectint_copy.cpp

#include "vectint.h" TEST(vectint_copy, copy_assign) #include { dcl:: vectintv{4}; TEST(vectint_copy, copy_construct) v[0] = 1;v[3] = 42; { dcl:: vectintw{10}; dcl:: vectintv{4}; w=v; v[0] = 1;v[3] = 42; EXPECT_EQ(4,w.size()); dcl:: vectintw{v}; EXPECT_EQ(4,w.capacity()); EXPECT_EQ(4,w.size()); EXPECT_EQ(1,w[0]); EXPECT_EQ(4,w.capacity()); EXPECT_EQ(0,w[1]); EXPECT_EQ(1,w[0]); EXPECT_EQ(0,w[2]); EXPECT_EQ(0,w[1]); EXPECT_EQ(42,w[3]); EXPECT_EQ(0,w[2]); } EXPECT_EQ(42,w[3]); } cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 34/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Configurando la compilación de las pruebas

utest/CMakeLists.txt

find_package(GTest REQUIRED)

set(CMAKE_BUILD_TYPE "Debug")

set(PROJECT_TEST_NAME ${PROJECT_NAME_STR}_utest) file(GLOB TEST_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../src/*.cpp)

include_directories(${GTEST_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include) add_executable(${PROJECT_TEST_NAME} ${TEST_SRC_FILES}) target_link_libraries(${PROJECT_TEST_NAME} ${GTEST_BOTH_LIBRARIES} ${GTEST_MAIN_LIBRARY} ${GTEST_LIBRARY})

GTEST_ADD_TESTS(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_TEST_NAME} "" ${TEST_SRC_FILES})

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 35/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Integrando las pruebas en CMake

Basta añadir una invocación a enable_testing() antes de incluir el directorio de tests.

CMakeLists.txt

#... enable_testing() add_subdirectory(utest)

Se genera nuevo objetivo para ejecutar las pruebas make test. ctest. cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 36/68 Google Test + gcover Pruebas básicas Mis primeras pruebas Ejecutando las pruebas

jdgarcia@gavilan:~/github-repos/examples/gtesttalk/vector2/ build$ make test Running tests... Test project/home/jdgarcia/github-repos/examples/gtesttalk/ vector2/build Start 1: vectint_copy.copy_construct 1/4 Test #1: vectint_copy.copy_construct ...... Passed 0.00 sec Start 2: vectint_copy.copy_assign 2/4 Test #2: vectint_copy.copy_assign ...... Passed 0.00 sec Start 3: vectint_constructor.empty 3/4 Test #3: vectint_constructor.empty ...... Passed 0.00 sec Start 4: vectint_constructor.sized 4/4 Test #4: vectint_constructor.sized ...... Passed 0.00 sec

100 % tests passed, 0 tests failed out of4

Total Test time(real) = 0.01 sec

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 37/68 Google Test + gcover Determinando la cobertura

1 Pruebas básicas

2 Determinando la cobertura

3 Más pruebas unitarias

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 38/68 Google Test + gcover Determinando la cobertura

Pasos previos

¿Qué necesitamos al compilar? Compilar con información de depuración. Flag -g: Configuraciones Debug o RelWithDebInfo. Flag de compilación para medición de cobertura: Flag - -coverage. Enlace con biblioteca de cobertura: Biblioteca libgcov.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 39/68 Google Test + gcover Determinando la cobertura

Configurando la compilación

utest/CMakeLists.txt

find_package(GTest REQUIRED)

set(CMAKE_BUILD_TYPE "Debug") add_compile_options(--coverage)

set(PROJECT_TEST_NAME ${PROJECT_NAME_STR}_utest) file(GLOB TEST_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../src/*.cpp)

include_directories(${GTEST_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/include) add_executable(${PROJECT_TEST_NAME} ${TEST_SRC_FILES}) target_link_libraries(${PROJECT_TEST_NAME} ${GTEST_BOTH_LIBRARIES} ${GTEST_MAIN_LIBRARY} ${GTEST_LIBRARY} gcov pthread )

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 40/68 Google Test + gcover Determinando la cobertura

Herramientas

gcov: Herramienta básica de anotación de cobertura. Genera una copia anotada del código fuente con contadores de frecuencia. lcov: Fron-end para generación de información gráfica a partir de gcov. Genera información adicional incluyendo navegación. genhtml: Genera una vista HTML a partir de los archivos de datos de lcov. Generación efectiva de páginas HTML navegables.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 41/68 Google Test + gcover Determinando la cobertura

Configurando la generación

utest/CMakeLists.txt

find_program(LCOV_CMD lcov) find_program(GENHTML_CMD genhtml)

ADD_CUSTOM_TARGET(coverage ${LCOV_CMD} --directory. --zerocounters COMMAND ${PROJECT_TEST_NAME} COMMAND ${LCOV_CMD} --directory. --capture --output-file mycov.info COMMAND ${LCOV_CMD} --remove mycov.info ’/usr/*’ ’utest/*’ --output-file mycov.info.cleaned COMMAND ${GENHTML_CMD} -o mycov mycov.info.cleaned --legend -s COMMAND ${CMAKE_COMMAND}-E remove mycov.info mycov.info.cleaned WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Computing coverage and generating report" )

ADD_CUSTOM_COMMAND(TARGET coverage POST_BUILD COMMAND google-chrome ./mycov/index.html& )

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 42/68 Google Test + gcover Determinando la cobertura

Informe generado

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 43/68 Google Test + gcover Determinando la cobertura

Informe generado

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 44/68 Google Test + gcover Determinando la cobertura

Informe generado

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 45/68 Google Test + gcover Más pruebas unitarias

1 Pruebas básicas

2 Determinando la cobertura

3 Más pruebas unitarias

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 46/68 Google Test + gcover Más pruebas unitarias Test Fixtures

3 Más pruebas unitarias Test Fixtures Completando las pruebas Probando la entrada salida

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 47/68 Google Test + gcover Más pruebas unitarias Test Fixtures ¿Qué es un Fixture?

Es un caso de prueba que tiene una misma configuración de objetos. Permite evitar escribir código repetitivo para configurar pruebas. ¿Cómo? Definir una clase con el nombre del caso derivando de ::testing::Test. Hacer datos miembros los objetos que deben ser visibles desde las pruebas. Definir constructor y/o destructor. Alternativamente SetUp() y/o TearDown(). Usar la macro TEST_F en vez de TEST.

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 48/68 Google Test + gcover Más pruebas unitarias Test Fixtures Mi primer Fixture

vectint_copy

#include "vectint.h" #include

class vectint_copy: public :: testing:: Test{ protected: vectint_copy(){ v[0] = 1; v[3] = 42; }

dcl:: vectintv{4}; };

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 49/68 Google Test + gcover Más pruebas unitarias Test Fixtures Mi primer Fixture

vectint_copy vectint_copy

TEST_F(vectint_copy, copy_construct) TEST_F(vectint_copy, copy_construct) { { dcl:: vectintw{v}; dcl:: vectintw{v}; EXPECT_EQ(4,w.size()); EXPECT_EQ(4,w.size()); EXPECT_EQ(4,w.capacity()); EXPECT_EQ(4,w.capacity()); EXPECT_EQ(1,w[0]); EXPECT_EQ(1,w[0]); EXPECT_EQ(0,w[1]); EXPECT_EQ(0,w[1]); EXPECT_EQ(0,w[2]); EXPECT_EQ(0,w[2]); EXPECT_EQ(42,w[3]); EXPECT_EQ(42,w[3]); } }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 50/68 Google Test + gcover Más pruebas unitarias Completando las pruebas

3 Más pruebas unitarias Test Fixtures Completando las pruebas Probando la entrada salida

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 51/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Probando el tamaño y la capacidad

utest/vectint_sizing.cpp utest/vectint_sizing.cpp

#include "vectint.h" bool vectint_sizing:: content_ok() #include const { for (int i=0;i<4;++i) { class vectint_sizing: public :: testing:: Test{ if (v[i ] !=i+1) return false; protected: } vectint_sizing(){ for (int i=4;i

bool content_ok() const;

dcl:: vectintv{4}; }; cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 52/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Probando la capacidad

utest/vectint_sizing.cpp

TEST_F(vectint_sizing, reserve_grow) { v.reserve(50); EXPECT_EQ(4,v.size()); EXPECT_EQ(50,v.capacity()); EXPECT_TRUE(content_ok()); }

TEST_F(vectint_sizing, reserve_shrink) { v.reserve(2); EXPECT_EQ(4,v.size()); EXPECT_EQ(4,v.capacity()); EXPECT_TRUE(content_ok()); }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 53/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Probando el tamaño

utest/vectint_sizing.cpp

TEST_F(vectint_sizing, resize_grow_over_capacity) { v.reserve(6); v.resize(8) ; EXPECT_EQ(8,v.size()); EXPECT_EQ(8,v.capacity()); EXPECT_TRUE(content_ok()); }

TEST_F(vectint_sizing, resize_grow_under_capacity) { v.reserve(6); v.resize(5) ; EXPECT_EQ(5,v.size()); EXPECT_EQ(6,v.capacity()); EXPECT_TRUE(content_ok()); } cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 54/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Probando el tamaño

utest/vectint_sizing.cpp

TEST_F(vectint_sizing, resize_shrink) { v.reserve(6); v.resize(2) ; EXPECT_EQ(2,v.size()); EXPECT_EQ(6,v.capacity()); EXPECT_EQ(1,v[0]); EXPECT_EQ(2,v[1]); }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 55/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Probando el tamaño

utest/vectint_sizing.cpp

TEST_F(vectint_sizing, resize_grow_over_capacity) { v.reserve(6); v.resize(8) ; EXPECT_EQ(8,v.size()); EXPECT_EQ(8,v.capacity()); EXPECT_TRUE(content_ok()); }

TEST_F(vectint_sizing, resize_grow_under_capacity) { v.reserve(6); v.resize(5) ; EXPECT_EQ(5,v.size()); EXPECT_EQ(6,v.capacity()); EXPECT_TRUE(content_ok()); } cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 56/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Ejecutando las pruebas

jdgarcia@gavilan:~/vector4/build\$ ctest Test project/home/jdgarcia/bitbucket-repos/charlas-es/codemotion-16-gtest/examples/ vector4/build Start 1: vectint_sizing.reserve_grow 1/9 Test #1: vectint_sizing.reserve_grow ...... Passed 0.00 sec Start 2: vectint_sizing.reserve_shrink 2/9 Test #2: vectint_sizing.reserve_shrink ...... Passed 0.00 sec Start 3: vectint_sizing.resize_grow_over_capacity 3/9 Test #3: vectint_sizing.resize_grow_over_capacity ....***Exception: SegFault 0.10 sec Start 4: vectint_sizing.resize_grow_under_capacity 4/9 Test #4: vectint_sizing.resize_grow_under_capacity ...***Exception: SegFault 0.10 sec Start 5: vectint_sizing.resize_shrink 5/9 Test #5: vectint_sizing.resize_shrink ...... Passed 0.00 sec Start 6: vectint_copy.copy_construct 6/9 Test #6: vectint_copy.copy_construct ...... Passed 0.00 sec Start 7: vectint_copy.copy_assign 7/9 Test #7: vectint_copy.copy_assign ...... Passed 0.00 sec Start 8: vectint_constructor.empty 8/9 Test #8: vectint_constructor.empty ...... Passed 0.00 sec Start 9: vectint_constructor.sized 9/9 Test #9: vectint_constructor.sized ...... Passed 0.00 sec

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 57/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Ejecutando las pruebas

78 % tests passed, 2 tests failed out of9

Total Test time(real) = 0.21 sec

The following tests FAILED: 3 - vectint_sizing.resize_grow_over_capacity(SEGFAULT) 4 - vectint_sizing.resize_grow_under_capacity(SEGFAULT) Errors while running CTest

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 58/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Ejecutando un caso específico

Se puede seleccionar un caso específico. Opción - -gtest_filter="vectint_sizing.*"

jdgarcia@gavilan:~/vector4/build$./vectint_utest--gtest_filter="vectint_sizing. *" Running main() from gtest_main.cc Note: Google Test filter= vectint_sizing. * [======] Running5 tests from1 test case. [------] Global test environment set-up. [------] 5 tests from vectint_sizing [ RUN] vectint_sizing.reserve_grow [OK] vectint_sizing.reserve_grow (0 ms) [ RUN] vectint_sizing.reserve_shrink [OK] vectint_sizing.reserve_shrink (0 ms) [ RUN] vectint_sizing.resize_grow_over_capacity Violación de segmento(‘core’ generado)

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 59/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Ejecutando una prueba específica

Se puede seleccionar una prueba específica. Opción -- gtest_filter="vectint_sizing.resize_grow_over_capacity"

jdgarcia@gavilan:~/vector4/build$./vectint_utest--gtest_filter="vectint_sizing. resize_grow_over_capacity" Running main() from gtest_main.cc Note: Google Test filter= vectint_sizing.resize_grow_over_capacity [======] Running1 test from1 test case. [------] Global test environment set-up. [------] 1 test from vectint_sizing [ RUN] vectint_sizing.resize_grow_over_capacity Violación de segmento(‘core’ generado)

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 60/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Error en resize()

resize()

void vectint:: resize( int n) { if (n>capacity_) reserve(n); if (n>size_){ std:: fill_n(buffer_.get()+size_, buffer_.get()+n, 0); } size_=n; }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 61/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Corrigiendo resize()

resize()

void vectint:: resize( int n) { if (n>capacity_) reserve(n); if (n>size_){ std:: fill_n(buffer_.get()+size_,n − size_, 0); } size_=n; }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 62/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Error en reserve()

reserve()

void vectint:: reserve( int n) { if (n <= capacity_) return; auto buf= std:: make_unique< int[]>(n); std:: copy_n(buffer_.get(), size_, buf.get()); capacity_=n; }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 63/68 Google Test + gcover Más pruebas unitarias Completando las pruebas Corrigiendo reserve()

reserve()

void vectint:: reserve( int n) { if (n <= capacity_) return; auto buf= std:: make_unique< int[]>(n); std:: copy_n(buffer_.get(), size_, buf.get()); std:: swap(buf, buffer_); capacity_=n; }

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 64/68 Google Test + gcover Más pruebas unitarias Probando la entrada salida

3 Más pruebas unitarias Test Fixtures Completando las pruebas Probando la entrada salida

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 65/68 Google Test + gcover Más pruebas unitarias Probando la entrada salida Probando flujos

Los flujos están organizados en una jerarquía de clases. std::ostringstream es un std::ostream.

vectint_io.cpp

#include "vectint.h" #include #include

TEST(vectint_io, empty) { dcl:: vectintv{5}; for (int i=0;i<5;++i) { v[i]=i+1; } std:: ostringstream os; os <

Recuerda todavía queda sitio para venir a using std::cpp 2016. http://www.usingstdcpp.org.

Podéis seguirme en Twitter. @jdgarciauc3m. @usingstdcpp.

Visitad mi página Web. https://www.arcos.inf.uc3m.es/wp/jdgarcia.

Y por favor: ¡¡¡Dadme feedback!!!

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 67/68 Google Test + gcover Más pruebas unitarias Probando la entrada salida

Google Test + gcover Una lista de recetas

J. Daniel Garcia

Grupo ARCOS Universidad Carlos III de Madrid

19 de noviembre de 2016

cbed – J. Daniel Garcia – ARCOS@UC3M ([email protected]) – Twitter: @jdgarciauc3m 68/68