1 googletest下载/官方sample分析
1.1 googletest源码下载编译
源码下载编译
// 下载 git clone https://github.com/google/googletest // 现在官方已经把 gtest 和 gmock 一起维护,所以这个 git 仓库还包含了 gmock。 // 编译、安装 cd googletest-main mkdir build install cd build cmake -DCMAKE_INSTALL_PREFIX=../install make -j make install
编译设置
如果需要生成.so库,生成官方sample的二进制文件,需要对源码最外层的CMakeLists.txt进行修改
生成动态库或者静态库,需要修改BUILD_SHARED_LIBS
生成samples测试bin文件,需要修改gtest_build_samples
将L20修改为ON之后,可以在build目录下看到googletest自带的sample都编译为了可执行文件。
1.2 googletest语法
TEST宏
TEST(test_case_name, test_name) 宏用于定义一个测试用例,其中test_case_name是测试用例的名称,test_name是测试的名称。例如:
TEST(MyTestSuite, MyTest) { // 测试代码 }
ASSERT宏
ASSERT_() 宏用于断言结果是否符合预期,其中可以是以下几种:
ASSERT_TRUE(condition):条件为真
ASSERT_FALSE(condition):条件为假
ASSERT_EQ(val1, val2):两个值相等
ASSERT_NE(val1, val2):两个值不相等
ASSERT_LT(val1, val2):第一个值小于第二个值
ASSERT_LE(val1, val2):第一个值小于等于第二个值
ASSERT_GT(val1, val2):第一个值大于第二个值
ASSERT_GE(val1, val2):第一个值大于等于第二个值
例如:
TEST(MyTestSuite, MyTest) { int a = 1; int b = 2; ASSERT_TRUE(a < b); ASSERT_EQ(a + b, 3); }
如果断言失败,测试用例将会失败。
EXPECT宏
EXPECT_() 宏与ASSERT_()宏的作用相同,但是如果检查失败,不会终止测试用例的执行。例如:
TEST(MyTestSuite, MyTest) { int a = 1; int b = 2; EXPECT_TRUE(a < b); EXPECT_EQ(a + b, 3); }
ASSERT宏和EXCEPT宏的区别:
ASSERT 不通过的时候会认为是一个 fatal 的错误,退出当前函数(只是函数)。而 EXPECT 失败的话会继续运行当前函数,所以对于函数内几个失败可以同时报告出来。通常我们用 EXPECT 级别的断言就好,除非你认为当前检查点失败后函数的后续检查没有意义。
SetUp和TearDown
SetUp() 和 TearDown() 函数可以在每个测试用例执行前和执行后分别调用,用于初始化和清理测试环境。例如:
class MyTestSuite : public ::testing::Test { protected: void SetUp() override { // 初始化代码 } void TearDown() override { // 清理代码 } }; TEST_F(MyTestSuite, MyTest) { // 测试代码 }
参数化测试
参数化测试可以用于测试一组输入的不同情况下,程序的输出是否符合预期。例如:
class MyTestSuite : public ::testing::TestWithParam<int> { }; TEST_P(MyTestSuite, MyTest) { int input = GetParam(); // 测试代码 } INSTANTIATE_TEST_SUITE_P(MyTestSuiteInstantiationName, MyTestSuite, ::testing::Values(1, 2, 3));
在这个例子中,MyTestSuite 继承自 TestWithParam,表示这是一个参数化测试。GetParam() 函数可以获取当前测试用例的参数值。INSTANTIATE_TEST_SUITE_P 宏用于实例化测试用例,其中第一个参数是实例化的名称,第二个参数是测试用例的名称,第三个参数是参数值列表。
预期异常
有时候需要测试程序在出现异常时的行为,可以使用 EXPECT_THROW() 和 ASSERT_THROW() 宏。例如:
TEST(MyTestSuite, MyTest) { std::vector<int> v; EXPECT_THROW(v.at(0), std::out_of_range); }
在这个例子中,EXPECT_THROW() 宏表示期望在执行 v.at(0) 时抛出 std::out_of_range 异常。如果没有抛出异常,测试用例将失败。
1.3 官方sample分析
我们安装时下载的代码就包含了 10 个例子,可以直接在根目录下执行 make 并运行。进入 samples 文件夹,阅读每份功能代码和对应的测试文件,可以帮助我们较快入门。我们下面看一下简单的例子。
sample1
#include <limits.h> #include "sample1.h" #include "gtest/gtest.h" // Tests factorial of negative numbers. TEST(FactorialTest, Negative) { // This test is named "Negative", and belongs to the "FactorialTest" // test case. EXPECT_EQ(1, Factorial(-5)); EXPECT_EQ(1, Factorial(-1)); EXPECT_GT(Factorial(-10), 0); } ... TEST(IsPrimeTest, Positive) { EXPECT_FALSE(IsPrime(4)); EXPECT_TRUE(IsPrime(5)); EXPECT_FALSE(IsPrime(6)); EXPECT_TRUE(IsPrime(23)); }
sample1 演示了简单测试用例的编写,主要使用了 TEST() 宏。
一个 test_case_name 对应一个函数的测试用例,test_name 可以对应这个测试用例下的某个场景的测试集。这两个名字可以任意取,但应该是有意义的.
sample1运行结果如下:
2 在自己的代码中使用gtest
上面已经说了如何将gtest编译成库,在自己项目中使用gtest时需要将install的头文件和库文件包含在记录的项目目录中。
项目目录如下:
// CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(GTEST_USAGE) set(CMAKE_CXX_COMPILE_FLAGS "std=c++11") include_directories(${CMAKE_CURRENT_SOURCE_DIR}/install/include) file(GLOB CPP_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.c*) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/install/lib) add_executable(GTEST_USAGE ${CPP_FILES}) target_link_libraries(GTEST_USAGE gtest )
// main.cpp #include <gtest/gtest.h> #include<numeric> int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv) return 0; }
这里我不写自己的代码,直接用官方的sample4充当测试代码
sample4.cc
// Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // A sample program demonstrating using Google C++ testing framework. #include "sample4.h" #include <stdio.h> // Returns the current counter value, and increments it. int Counter::Increment() { return counter_++; } // Returns the current counter value, and decrements it. // counter can not be less than 0, return 0 in this case int Counter::Decrement() { if (counter_ == 0) { return counter_; } else { return counter_--; } } // Prints the current counter value to STDOUT. void Counter::Print() const { printf("%d", counter_); }
sample4.h
// Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // A sample program demonstrating using Google C++ testing framework. #ifndef GOOGLETEST_SAMPLES_SAMPLE4_H_ #define GOOGLETEST_SAMPLES_SAMPLE4_H_ // A simple monotonic counter. class Counter { private: int counter_; public: // Creates a counter that starts at 0. Counter() : counter_(0) {} // Returns the current counter value, and increments it. int Increment(); // Returns the current counter value, and decrements it. int Decrement(); // Prints the current counter value to STDOUT. void Print() const; }; #endif // GOOGLETEST_SAMPLES_SAMPLE4_H_
sample4_unittest.cc
// Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "sample4.h" #include "gtest/gtest.h" namespace { // Tests the Increment() method. TEST(Counter, Increment) { Counter c; // Test that counter 0 returns 0 EXPECT_EQ(0, c.Decrement()); // EXPECT_EQ() evaluates its arguments exactly once, so they // can have side effects. EXPECT_EQ(0, c.Increment()); EXPECT_EQ(1, c.Increment()); EXPECT_EQ(2, c.Increment()); EXPECT_EQ(3, c.Decrement()); } } // namespace
运行结果如下: