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: Linux Mac OS X Windows Cygwin MinGW Windows Mobile Symbian
Algunos proyectos que lo usan: Proyecto Chromium. Familia de compiladores LLVM. Protocol Buffers. 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
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 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 files 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 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 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 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