Setup and Use of Unit Test Environment gtest, mockcpp, LCOV
This article is mainly used to record individual learning, and also to provide reference for those who have the same needs.
Example source github:https://github.com/904221150/gtest_sample
1. Introduction to the environment
The software tools used to set up the unit test environment in this paper are:
1.1 gtest
gtest is a cross-platform (Liunx, Mac OS X, Windows, Cygwin, Windows CE and
Symbian)C++ Unit Test Framework, released by google Inc. gtest is generated for writing C++ tests on different platforms. It provides rich assertions, fatal and non-fatal judgments, parameterization, death tests, and so on.
1.2 mockcpp
Mockcpp is a C/C++ oriented mock framework. It specifies (or simulates) the behavior of the function, checks the incoming parameters, sets the outgoing parameters, and specifies the return value of the function.
1.3 LCOV
lcov is a front-end graphical display tool for GCC test coverage. It collects multiple source files by
Code override information for rows, functions, and branches (the gcda, gcno files are generated after the program executes, the links above say) and the collected information is generated into HTML pages.
Generating HTML requires the use of the genhtml command as explained below.
2. Environment Building
2.1 gtest Environment Setup
git clone https://github.com/google/googletest cd googletest/ mkdir mybuild cd mybuild cmake ../ make sudo cp lib/libg*.a /usr/lib sudo cp -rf ../googletest/include/gtest /usr/include/gtest sudo cp -rf ../googlemock/include/gmock /usr/include/gmock
2.2 mockcpp environment setup
Mockcpp download link: http://code.google.com/p/mockcpp , based on the latest version 2.6
Modify build_install.sh file
#Original File #!/bin/bash # build and install install_dir=/home/jelly/Programming/cpp-ut-project/cpp-ut-project/tools/mockcpp function build() { mkdir $1 2>/dev/null cd $1 cmake -DCMAKE_INSTALL_PREFIX=$install_dir $2 make install } build ../../build_mockcpp_to_install ../mockcpp/mockcpp cd ../mockcpp/mockcpp #Modified #!/bin/bash # build and install mkdir mockcpp install_dir=../mockcpp function build() { mkdir $1 2>/dev/null cd $1 cmake -DCMAKE_INSTALL_PREFIX=$install_dir $2 make install } build build .. cd ../mockcpp
Execute Command
./build_install.sh cd mockcpp sudo cp lib/libmockcpp.a /usr/lib sudo cp -rf include/mockcpp /usr/include/mockcpp
2.3 LCOV Environment Setup
Execute Command
git clone https://github.com/linux-test-project/lcov.git cd lcov/ make install
3. Examples of unit tests
This example aims to unit test fun
File directory
|--gtest | | | +--gtest.cpp |--inc | | | +--fun.h |--result | | | +(Coverage results) |--src | | | +--fun.c |--app.c |--makefile
app.c Apply the principal function
#include <stdio.h> #include"fun.h" int main() { printf("fun return %d\n", fun(1)); return 0; }
fun.c
#include<stdio.h> #include"fun.h" int fun(int x) { int i = 0; i = fun_inside(1); return i > 0; } int fun_inside(int x) { printf("enter fun_inside\n"); return x - 1; }
fun.h
#ifndef __FUN_H__ #define __FUN_H__ int fun(int x); int fun_inside(int x); #endif
gtest.cpp unit test cases
#include<iostream> #include<gtest/gtest.h> #include<mockcpp/mockcpp.hpp> #include"fun.h" using namespace std; class TestF : public testing::Test{ public: virtual void SetUp() { printf("fun start test\n"); } virtual void TearDown() { printf("fun end test\n"); } }; TEST_F(TestF, fun1) { int ret = 0; MOCKER(fun_inside) .stubs() .with(any()) .will(returnValue(2)); ret = fun(1); EXPECT_EQ(1, ret); } class FooEnvironment : public testing::Environment{ public: virtual void SetUp() { std::cout << "Foo FooEnvironment SetUP" << std::endl; } virtual void TearDown() { std::cout << "Foo FooEnvironment TearDown" << std::endl; } }; int main(int argc, char** argv) { testing::AddGlobalTestEnvironment(new FooEnvironment); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
The main test is in TEST_ In the F(TestF, fun1) function, TEST_F provides a function for gtest that performs unit tests. The first parameter, TestF, inherits test::Test, which aims to provide a generic initialization call function and a generic end call function for the unit test. The second parameter is the test name. The output can be seen in the output section below. EXPECT_EQ provides a comparison function for gtests, where the output of fun(1) is compared to 1.
For more information about gtest, consult the relevant information by yourself.
MOCKER provides a piling function for mockcpp, where fun_inside piling
.stubs()//unlimited number of piling function calls
.with(any())//means that the piling function can be called with any input
.will(returnValue(2);// Fun_ Inside returns 2 after being piled
More detailed use of mockcpp allows you to query relevant data yourself
Makefile (makefile is not written well here, temporary output is in the. / directory)
objdir = obj srcdir = src SRC_PATH = . \ src OBJ_PATH = obj GTEST_PATH = gtest SRC = $(foreach dir, $(SRC_PATH), $(wildcard $(dir)/*.c)) OBJ = $(patsubst $(srcdir)/%.c, $(objdir)/%.o, $(SRC)) SRC_GTEST_PATH = gtest \ src SRC_GTEST = $(foreach dir, $(SRC_GTEST_PATH), $(wildcard $(dir)/*.c)) SRC_GTEST += $(foreach dir, $(SRC_GTEST_PATH), $(wildcard $(dir)/*.cpp)) CC = gcc CXX = g++ INCLUDES = -Iinc LIBS = -lgtest \ -lpthread \ -lgtest_main \ -lmockcpp CFLAGS = -g -Wall -O0 CTESTFLAGS = -fprofile-arcs \ -ftest-coverage target = my_gtest all : $(target) my_app : $(SRC) @echo $(SRC) @echo $(OBJ) $(CC) $^ -o $@ $(INCLUDES) $(CFLAGS) my_gtest : $(SRC_GTEST) @echo $(SRC_GTEST) $(CXX) $^ -o $@ $(CFLAGS) $(CTESTFLAGS) $(INCLUDES) $(LIBS) ./my_gtest lcov -d . -t test -o test.info -b . -c genhtml -o result test.info $(INCLUDES) $(LIBS) clean: rm my_app clean_test: rm my_gtest rm *.gcda rm *.gcno rm *.info rm -rf result/*
gtest runs with a link-lgtest-lpthread-lgtest_ Main
mockcpp runs with link-lmockcpp, code optimization is-O0
lcov requires gcov built in gcc to provide coverage information before traveling, and -fprofile-arcs-ftest-coverage is required
$(CXX) $^ -o $@ $(CFLAGS) $(CTESTFLAGS) $(INCLUDES) $(LIBS)
My_is generated after compilation GTEST execution file, and. gcno file
./my_gtest
A compiled unit test is executed and generated here. gcda file
lcov -d . -t test -o test.info -b . -c
-d: Store. gcda,. Path to gcno file
-t: Name of the target (optional)
-o: Generated coverage file. info
-b: The starting location of the relative directory
-c: capture, collection coverage
genhtml -o result test.info
Generate coverage report
Open result/index.html is viewable
Output Results
. /my_gtest output, where TEST_is run F (TestF, fun1)
. /my_app output, where you can compare how fun functions work
lcov coverage page, where src coverage is not high, due to fun. Fun_in C Inside function not unit tested
Appendix: Coverage Explanation
Code Coverage
After unit testing, we certainly want to be able to visually see what code our tests cover.
In theory, if we can cover 100% of all our code, we can say that our code is not bugged.
But in fact, 100% coverage is harder than you might think. For large projects, it's good to have 80% to 90% sentence coverage.
Coverage-related references: https://cloud.tencent.com/developer/article/1552518