用gtest测试类的私有成员
- 格式:docx
- 大小:92.59 KB
- 文档页数:4
gtest 使用手册gtest 是一个流行的 C++单元测试框架,它提供了丰富的功能和简洁的 API,使得编写和运行单元测试变得更加容易和高效。
本文将介绍 gtest 的基本概念和使用方法,帮助读者快速上手并熟练使用 gtest 进行单元测试。
下面是本店铺为大家精心编写的3篇《gtest 使用手册》,供大家借鉴与参考,希望对大家有所帮助。
《gtest 使用手册》篇1一、什么是 gtest?gtest 是一个由 Google 开发的 C++单元测试框架,旨在为开发者提供一种简单、高效的方式来编写和运行单元测试。
gtest 提供了丰富的功能和简洁的 API,可以与各种编译器和 IDE 集成,并支持多种测试类型和断言风格。
二、gtest 的基本概念1. 测试套件(Test Suite):测试套件是 gtest 的基本单位,它包含一个或多个测试用例(Test Case)。
每个测试套件都有一个入口函数,该函数负责初始化和清理测试环境。
2. 测试用例(Test Case):测试用例是测试套件中的基本测试单元,它包含一个或多个测试步骤,每个测试步骤都包含一个预期结果和一个实际结果。
3. 断言(Assertion):断言是 gtest 中用于验证测试结果的一种机制,它用于比较预期结果和实际结果是否相等。
gtest 提供了多种断言类型,包括 EXPECT_EQ、EXPECT_NE、EXPECT_TRUE、EXPECT_FALSE 等。
4. 测试助手(Test Helper):测试助手是一种特殊的测试用例,它用于为其他测试用例提供共性的测试步骤和断言。
三、gtest 的使用方法1. 安装 gtest:在使用 gtest 之前,需要先安装 gtest。
可以使用 CMake 或 Maven 等构建工具来安装 gtest。
2. 编写测试用例:编写测试用例时,需要继承testing::TestWithParam 类,并实现 TestBody 函数。
主题:unittest中如何mock私有方法在使用Python进行软件开发时,我们经常会用到unittest模块来进行单元测试。
在进行单元测试时,有时我们需要测试一个类的某个方法,但是这个方法调用了类中的私有方法,这时就需要对这个私有方法进行mock处理,以便顺利进行单元测试。
本文将介绍如何在unittest中mock私有方法,帮助读者更好地进行单元测试。
一、为什么需要mock私有方法在进行单元测试时,我们通常是针对一个方法进行测试的,但有时这个方法内部会调用类中的私有方法,私有方法也可能会调用其他模块中的方法。
如果我们不对私有方法进行mock处理,单元测试时就会被私有方法所影响,导致测试结果不准确。
我们需要mock私有方法以隔离被测试方法的影响,确保单元测试能够独立进行并得到准确的结果。
二、如何mock私有方法在unittest中,我们可以借助unittest.mock模块来mock私有方法。
我们需要导入unittest和unittest.mock模块,然后使用patch装饰器来对私有方法进行mock处理。
```pythonimport unittestfrom unittest.mock import patchclass MyClass:def __init__(self):passdef _private_method(self):passdef public_method(self):self._private_method()```以上是一个简单的类,其中包含一个私有方法_private_method和一个公有方法public_method。
接下来,我们将介绍如何使用unittest.mock来mock私有方法。
1. 使用patch装饰器patch装饰器可以帮助我们临时替换一个对象的属性,这里我们可以借助patch来mock私有方法。
下面是一个示例:```pythonclass TestMyClass(unittest.TestCase):patch('MyClass._private_method')def test_public_method(self, mock_private_method):my_obj = MyClass()my_obj.public_method()mock_private_method.assert_called_once()```在上面的示例中,我们使用patch装饰器来mock私有方法_private_method,将其替换为mock_private_method。
gtest类方法gtest是Google Test的简称,它是一个C++的单元测试框架。
它由google公司开发,用于测试C++应用程序的正确性。
gtest提供了一个全面的测试框架,包括断言、测试套件和测试用例,可以很容易地写出可维护和易读的测试代码。
1.TEST宏:TEST宏用于定义一个测试用例,它接受两个参数,第一个参数是测试用例名称,第二个参数是测试用例中的测试点名称。
在测试用例中,可以使用gtest提供的各种断言函数来验证代码逻辑的正确性。
例如:TEST(MyTestCase, MyTestPoint)//测试点代码ASSERT_EQ(2+2,4);2.TEST_F宏:TEST_F宏与TEST宏类似,不同之处在于它可以使用测试夹具(Fixture)。
测试夹具是为了简化测试代码而引入的概念,它可以在测试用例执行前进行一些初始化操作,在测试用例执行后进行一些清理操作。
测试夹具可以帮助我们在不同的测试用例中复用一些代码逻辑。
例如:class MyTestFixture : public ::testing::Testprotected://测试用例执行前的初始化操作void SetUp( override//初始化操作}//测试用例执行后的清理操作void TearDown( override//清理操作}};TEST_F(MyTestFixture, MyTestPoint)//测试点代码ASSERT_EQ(2+2,4);3.TEST_P宏:TEST_P宏用于定义一个测试用例生成器,它可以根据参数化生成多个测试用例。
测试用例生成器接受两个参数,第一个参数是测试用例的参数化名称,第二个参数是测试用例中的参数名称。
测试用例生成器需要结合INSTANTIATE_TEST_CASE_P宏来使用。
例如:class MyTestFixture : public ::testing::TestWithParam<int> };TEST_P(MyTestFixture, MyTestPoint)int value = GetParam(;//测试点代码ASSERT_EQ(value + value, value * 2);INSTANTIATE_TEST_CASE_P(MyTestValues,MyTestFixture, ::testing::Values(1, 2, 3));4.TEST_SUITE宏:TEST_SUITE宏用于定义一个测试套件,它接受一个参数,用于定义测试套件的名称。
GoogleTest(GTest)使用方法和源码解析在分析源码之前,我们先看一个例子。
以《Google Test(GTest)使用方法和源码解析——概况》一文中最后一个实例代码为基准,修改最后一个“局部测试”结果为错误。
(转载请指明出于breaksoftware的csdn博客)[cpp] view plain copyprint?1.class ListTest : public testing::Test {2.protected:3.virtual void SetUp() {4._m_list[0] = 11;5._m_list[1] = 12;6._m_list[2] = 13;7.}8.int _m_list[3];9.};10.TEST_F(ListTest, FirstElement) {11.EXPECT_EQ(11, _m_list[0]);12.}13.14.TEST_F(ListTest, SecondElement) {15.EXPECT_EQ(12, _m_list[1]);16.}17.18.TEST_F(ListTest, ThirdElement) {19.EXPECT_EQ(0, _m_list[2]);20.}然后我们观察其输出,从下面的结果我们可以分析出GTest帮我们统计了:•有多少测试用例•一个测试用例中有多少测试特例•一个测试用例中有多少测试特例成功•一个测试用例中有多少测试特例失败•失败的原因、位置、期待结果、实际结果[plain] view plain copyprint?1.Running main() from gtest_2.[==========] Running 3 tests from 1 test case.3.[----------] Global test environment set-up.4.[----------] 3 tests from ListTest5.[ RUN ] ListTest.FirstElement6.[ OK ] ListTest.FirstElement (0 ms)7.[ RUN ] ListTest.SecondElement8.[ OK ] ListTest.SecondElement (0 ms)9.[ RUN ] ListTest.ThirdElement10.../samples/sample11_:86: Failure11.Expected: 012.To be equal to: _m_list[2]13.Which is: 1314.[ FAILED ] ListT est.ThirdElement (0 ms)15.[----------] 3 tests from ListTest (0 ms total)16.17.[----------] Global test environment tear-down18.[==========] 3 tests from 1 test case ran. (0 ms tot al)19.[ PASSED ] 2 tests.20.[ FAILED ] 1 test, listed below:21.[ FAILED ] ListT est.ThirdElement22.23. 1 FAILED TEST在《Google Test(GTest)使用方法和源码解析——自动调度机制分析》一文中,我们分析了,测试用例对象指针将保存在类UnitTestImpl中[cpp] view plain copyprint?1.// The vector of TestCases in their original order. It owns the2.// elements in the vector.3.std::vector<TestCase*> test_cases_;那么结果的统计,肯定也是针对这个vector变量的。
Google单元测试框架gtest之官⽅sample笔记1--简单⽤例1.0 通⽤部分和常见的测试⼯具⼀样,gtest提供了单体测试常见的⼯具和组件。
⽐如判断各种类型的值相等,⼤于,⼩于等,管理多个测试的测试组如testsuit下辖testcase,为了⽅便处理初始化数据减少重复代码,提供了setup和teardown函数。
官⽅⽂档称:TEST has two parameters: the test case name and the test name. 第⼀个是case名称,第⼆个是test名称,这是google的名词称呼⽅法,其实就是⼀般意义上的testsuit和testcase,前者是组,后者是测试⽤例,为了⽅便测试管理,把⼏个相关的测试放到⼀起统称为⼀个测试组。
这是⼀个编程约定,但如果把不相⼲的测试放到⼀个test_case_name下,也不会报错,只是做测试总结和汇总的时候不⽅便⽽已。
# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)关于TEST宏,这是⼀个⼀层包⼀层的宏定义,虽然google编程规范说不建议⽤宏,但是gtest却⼤量的使⽤宏来创建类和函数,使⽤宏可以给⽤户更加简洁的接⼝,在效率上也有优势,但是读起来很晦涩。
⼀般的,在基础⼯具和底层API中,宏还是由⼴⼤的应⽤空间,因为这⼀部分基本上不怎么变化,那些写底层⼯具的⼤⽜们有能⼒驾驭这种反常规的写法。
使⽤宏来实现底层的重复性⼯作或者封装复杂的接⼝,在开源项⽬中是很常见的⽅式。
Sample #1 shows the basic steps of using googletest to test C++ functions.Sample #2 shows a more complex unit test for a class with multiple member functions.Sample #3 uses a test fixture.Sample #4 teaches you how to use googletest and googletest.h together to get the best of both libraries.Sample #5 puts shared testing logic in a base test fixture, and reuses it in derived fixtures.Sample #6 demonstrates type-parameterized tests.Sample #7 teaches the basics of value-parameterized tests.Sample #8 shows using Combine() in value-parameterized tests.Sample #9 shows use of the listener API to modify Google Test's console output and the use of its reflection API to inspect test results.Sample #10 shows use of the listener API to implement a primitive memory leak checker.1.1 sample1官⽅sample1有2个函数,阶乘函数int Factorial()和判断素数函数bool IsPrime(int n)。
gtest单元测试方法gtest单元测试方法1. 什么是gtest单元测试方法gtest单元测试方法是指使用Google Test(简称gtest)框架进行软件单元测试的一种方法。
gtest是一个开源的C++单元测试框架,它提供了丰富的断言和测试工具,可以帮助开发者编写可靠的、易于维护的单元测试。
2. 使用gtest编写单元测试方法的步骤下面是使用gtest编写单元测试方法的步骤:1.安装gtest框架:首先需要将gtest框架下载到本地,并进行安装和配置。
2.编写测试用例:根据需要,编写需要测试的代码和相应的测试用例,在测试用例中调用待测试代码,并使用gtest的断言进行验证。
3.构建和运行测试:通过编译器构建测试代码,并执行生成的可执行文件,查看测试结果。
4.分析结果:根据测试结果,进行相应的修改和优化。
3. 测试用例的编写测试用例是指对待测试代码的某个功能进行测试的一组测试方法。
在gtest中,测试用例是由宏定义的方式进行定义的,下面是一个测试用例的示例:TEST(TestCaseName, TestName) {// 在这里编写测试代码// 调用待测试代码并使用断言进行验证EXPECT_EQ(4, add(2, 2));}•TEST是一个宏定义,用于定义一个测试用例。
TestCaseName 是测试用例的名称,TestName是具体的测试方法的名称。
•在测试用例中,可以编写测试代码,并调用待测试的代码。
使用EXPECT_*系列的断言检查测试结果,如EXPECT_EQ用于判断两个值是否相等。
4. 编译和运行测试使用gtest编写的测试代码,需要通过编译器进行构建,并执行生成的可执行文件进行测试。
下面是使用命令行进行编译和运行的示例:1.编译测试代码:使用编译器将测试代码编译为可执行文件。
$ g++ -o test -lgtest -lgtest_main2.运行测试:执行生成的可执行文件进行测试。
c++ gtest例子Google Test(简称GTest)是Google为C++编写的一个开源的单元测试框架。
它为C++开发者提供了一套简单易用的API,用来编写、组织和运行单元测试。
以下是一个使用GTest的基本示例,展示了如何设置和运行测试用例。
```cpp#include <gtest/gtest.h>// 被测试的函数int add(int a, int b) {return a + b;}// 测试用例1:测试加法运算TEST(AddTest, PositiveNumbers) {EXPECT_EQ(3, add(1, 2));EXPECT_EQ(5, add(2, 3));}// 测试用例2:测试加法运算的边界条件TEST(AddTest, ZeroAndNegativeNumbers) {EXPECT_EQ(1, add(0, 1));EXPECT_EQ(-1, add(1, -2));}int main(int argc, char* argv[]) {// 初始化GTest框架::testing::InitGoogleTest(&argc, argv);// 运行所有测试用例return RUN_ALL_TESTS();}```上述代码中,定义了一个名为add的函数,接收两个整数参数,返回它们的和。
然后,我们使用GTest的宏定义TEST来定义两个测试用例。
第一个测试用例AddTest.PositiveNumbers测试了两个正数相加的结果,使用GTest的EXPECT_EQ宏来验证预期结果。
第二个测试用例AddTest.ZeroAndNegativeNumbers测试了零和负数相加的结果。
通过这样定义多个测试用例,我们可以对被测函数的不同输入和边界条件进行全面的测试。
在main函数中,我们首先使用::testing::InitGoogleTest来初始化GTest框架,然后使用RUN_ALL_TESTS运行所有的测试用例。
gtest类方法GTest(Google Test)是Google开源的C++单元测试框架,广泛应用于测试C++代码的正确性和稳定性。
它提供了丰富的断言接口和测试用例管理工具,使得开发人员可以方便地编写和运行单元测试。
GTest类方法是GTest框架中定义的一些类成员方法,用于进行测试用例的断言和异常处理。
下面将介绍GTest类方法的一些常用用法和示例。
1.ASSERT系列断言方法GTest框架提供了一系列的ASSERT断言方法,用于对测试结果进行断言。
其中包括ASSERT_EQ、ASSERT_NE、ASSERT_TRUE、ASSERT_FALSE等方法,可以用于判断两个值是否相等、是否不相等,以及判断一个值是否为真或假。
示例:```cppint add(int a, int b)return a + b;TEST(MathTest, AddTest)ASSERT_EQ(add(2, 3), 5);ASSERT_NE(add(2, 3), 6);ASSERT_TRUE(add(2, 3) > 4);ASSERT_FALSE(add(2, 3) < 4);```2.EXPECT系列断言方法除了ASSERT系列断言方法,GTest还提供了EXPECT系列断言方法。
二者的区别在于,ASSERT断言失败会导致当前测试用例终止,而EXPECT 断言失败只是记录失败信息,当前测试用例会继续执行。
示例:```cppint divide(int a, int b)if (b == 0)throw std::invalid_argument("divide by zero");}return a / b;TEST(MathTest, DivideTest)EXPECT_EQ(divide(6, 3), 2);EXPECT_THROW(divide(6, 0), std::invalid_argument);```3. SetUp和TearDown方法在GTest中,每个测试用例的执行都可以有各自的SetUp和TearDown方法,用于初始化和清理测试环境。
关于C++中对私有的测试总结对于算法项⽬,基本都是被调⽤⽅,像mlr是以动态链接库的形式被isearch调⽤,那mlr模块暴露的公共接⼝是针对isearch,但对mlr的测试不仅仅是靠这些公共接⼝就够的,因为其本⾝的很多逻辑都是在私有的,这就需要我们有时候对其私有⽅法和成员进⾏测试。
下⾯有⼏种打开私有成员和⽅法的⼀些办法:1.加宏编译即在你需要打开私有的头⽂件中加⼊#define private public/protect蛮暴⼒的,当然也是最容易操作和简单的。
2.利⽤Gtest的FRIEND_TEST()Private class members are only accessible from within the class or by friends. To access a class' private members, you can declare your test fixture as a friend to the class and define accessors in your fixture. Tests using the fixture can then access the private members of your production class via the accessors in the fixture. Note that even though your fixture is a friend to your production class, your tests are not automatically friends to it, as they are technically defined in sub-classes of the fixture.FRIEND_TEST(TestCaseName, TestName);上⾯是gtest的关于私有成员测试wiki介绍,gtest会通过FRIEND_TEST(TestCaseName, TestName)声明了友元,即TestCaseName为友元类,⽽TestName为具体的case名。
使⽤gtest⾃动化测试并给出性能测试结果(windows版本,版本平台也可以使⽤,但并没。
/**************************************************************使⽤gtest⾃动化测试**************************************************************/[依赖项]eclips KEPLERcygwinwindow xpgtest库cmd已是管理员权限[gtest 搭建]a)、⾸先确定已成功安装好了eclips C++ 开发相关的⼯具,并确定g++的环境变量已能正常使⽤b)、打开eclips,新建两个项⽬,gtest(appliction),testlibs(static library),c)、解压gtest库,copy (include,src)到新建好的gtest⽬录中d)、排除库⽂件的编译 gtest库中的所有⽂件,选中gtest项⽬中的include⽂件夹,右键->属性-> c/c++build -> 选中exclude resouce form build,再⽤同样的⽅法去掉src⽂件夹的编译设置e)、设置编译头⽂件,选中gtest项⽬->右键->属性->c/c++1)、选中setting -> 选中tool settings -> 选中 cross g++ compiler -> 选中includes ->添加include paths"${workspace_loc:/${ProjName}/include}","${workspace_loc:/${ProjName}}","${workspace_loc:/testlibs}"2)、点击apply,再点okf)、在gtest项⽬中新增加⼀个⽂件并输⼊下⾯的代码//-------------------------------#include "gtest/gtest.h"#include "src/gtest_"#include "src/"//-------------------------------g)、选中gtest项⽬中的include⽂件夹,右键->属性->c/c++build -> 选中build steps 在post-build steps的command中输⼊"..\auto_test.bat"h)、编写脚本1)、向gtest项⽬中增加⼀个auto_test.bat⽂件2)、输⼊脚本@gtest.exe > out.logI)、在testlibs中写⼊⽬标代码(新建了⼀个class类的声明和定义)test-class.h://code begin-----------------------#ifndef TEST_CLASS_H_#define TEST_CLASS_H_class test_class{public:int write();};#endif /* TEST_CLASS_H_ *///code end-------------------------://code begin------------------------#include "test-class.h"int test_class::write(){return 10;}//code end------------------------J)、在gtest项⽬中编写测试⽤列(添加)://------------------------#include "gtest/gtest.h"#include <test-class.h>TEST(TESTCASE,TEST){test_class test;//test.write();EXPECT_EQ(10,test.write());}TEST(TESTCASE1,TEST1){FAIL(); //⼿动增加⼀个失败的测试}//------------------------k)正常编译gtest项⽬l)、打开eclips的console,就会看到测试输出的⼀些信息,那就是测试报告console://------------------------Running main() from gtest_[==========] Running 1 test from 1 test case.[----------] Global test environment set-up.[----------] 1 test from TESTCASE[ RUN ] TESTCASE.TEST[ OK ] TESTCASE.TEST (0 ms)[----------] 1 test from TESTCASE (30 ms total)[----------] Global test environment tear-down[==========] 1 test from 1 test case ran. (30 ms total)[ PASSED ] 1 test.[性能测试搭建]a) 修改gtest项⽬属性1)、选中gtest项⽬(alt+enter)->打开(c/c++ build 节点)-> setting-> cross g++ compiler2)、修改command 原为 g++ ,改为 g++ -pg3)、打开(cross g++ linker) -> 修改command 原为 g++ ,改为 g++ -pgb) 修改testlibs项⽬属性1)、选中testlibs项⽬(alt+enter)->打开(c/c++ build 节点)-> setting-> cross g++ compiler2)、修改command 原为 g++ ,改为 g++ -pg3)、打开(cross g++ linker) -> 修改command 原为 g++ ,改为 g++ -pgc)、修改脚本auto_test.bat::修改out的值就可以开启和关闭是否执⾏测试 0为开启⽤//code begin-----------------@set out=1::gtest⽂件输出格式0 txt,1 xml@set testOutType=0::test⽇志⽂件输出⽂件名@set log="out.log";@if %testOutType%==1 then ( %log%="out.xml")@if "%out%"==0 then goto lable1 else goto lable2:lable1@echo "---------start unit test----"@echo "---------unit test results----------">log::@gtest.exe --gtest_output="xml:%log%"@gtest.exe >log@echo "---------Performance Test Results----------">>log@if exist "gmon.out" (goto lable3) else (goto lable4):lable3@(gprof gtest.exe gmon.out -b) >>log@echo "---------test complet----------">>log@cat log@echo "Full output has been output to a log file."::open log file@notepad log:lable2@echo "">loggoto exit;:lable4@goto exit;::exit script:exit@exit(0)//code end-----------d)、打开consol 窗⼝,⽣成项⽬:选中项⽬ (ctrl+b),编译操作完成后会⾃⼰打测试报告e)、查看性能测试报告"---------Performance Test Results----------"Flat profile:Each sample counts as 0.01 seconds.% cumulative self self totaltime seconds seconds calls Ts/call Ts/call name19.16 1.40 1.40 xis_data::set_data(xis_data const&)18.96 2.77 1.38 xis_data_array::append(xis_data)Call graphgranularity: each sample hit covers 4 byte(s) for 0.14% of 7.28 secondsindex % time self children called name<spontaneous>[1] 19.2 1.40 0.00 xis_data::set_data(xis_data const&) [1]-----------------------------------------------<spontaneous>[2] 19.0 1.38 0.00 xis_data_array::append(xis_data) [2]-----------------------------------------------<spontaneous>"---------end Performance Test Results----------"f)、输出报告包括(单元测试、性能测试)console://------------------------Running main() from gtest_[==========] Running 1 test from 1 test case.[----------] Global test environment set-up.[----------] 1 test from TESTCASE[ RUN ] TESTCASE.TEST[ OK ] TESTCASE.TEST (0 ms)[----------] 1 test from TESTCASE (30 ms total)[----------] Global test environment tear-down[==========] 1 test from 1 test case ran. (30 ms total)[ PASSED ] 1 test."---------Performance Test Results----------"Flat profile:Each sample counts as 0.01 seconds.% cumulative self self totaltime seconds seconds calls Ts/call Ts/call name19.16 1.40 1.40 xis_data::set_data(xis_data const&) 18.96 2.77 1.38 xis_data_array::append(xis_data) Call graphgranularity: each sample hit covers 4 byte(s) for 0.14% of 7.28 seconds index % time self children called name<spontaneous>[1] 19.2 1.40 0.00 xis_data::set_data(xis_data const&) [1] -----------------------------------------------<spontaneous>[2] 19.0 1.38 0.00 xis_data_array::append(xis_data) [2]-----------------------------------------------<spontaneous>"---------end Performance Test Results----------"g)、关闭报告,测试结束 (⼀定要操作这⼀步,否则eclips会⽆法操作)。
gtest 用例结果标识在Google Test(gtest)中,测试用例(Test Case)的结果是通过断言来判断的。
测试用例内部可以包含多个断言,如果其中任何一个失败,整个测试用例将被标记为失败。
Google Test 提供了多种断言宏,常用的有`ASSERT_` 和`EXPECT_` 系列。
1. `ASSERT_` 系列:如果`ASSERT_` 系列的断言失败,将导致整个测试用例终止。
这意味着如果一个`ASSERT_` 断言失败,后续的代码不会执行,测试用例被标记为失败。
```cppTEST(MyTest, Example) {ASSERT_EQ(2 + 2, 4); // 正确ASSERT_EQ(1 + 1, 3); // 错误,导致整个测试用例失败}```2. `EXPECT_` 系列:如果`EXPECT_` 系列的断言失败,测试用例将继续执行。
这意味着测试用例内的其他断言仍然会被检查,即使前面的某个`EXPECT_` 断言失败。
```cppTEST(MyTest, Example) {EXPECT_EQ(2 + 2, 4); // 正确EXPECT_EQ(1 + 1, 3); // 错误,但整个测试用例不会终止EXPECT_EQ(3 * 3, 9); // 正确}```3. 失败与成功的标识:在测试用例运行时,Google Test 将在测试用例失败时输出失败的详细信息,并在测试用例成功时输出成功的信息。
你可以在测试运行结束后查看控制台输出,也可以通过运行时参数来控制输出。
-失败时的输出:```[ RUN ] MyTest.Exampletest.cpp:6: FailureExpected equality of these values:1 + 1Which is: 2To the value:3```-成功时的输出:```[ OK ] MyTest.Example (0 ms)```这样,通过查看控制台输出,你可以很容易地看到每个测试用例的执行结果。
gtestTEST_F的使⽤模板(例⼦)在Visual Studio 21-7 环境中:(竟然可以变量名直接使⽤汉字)#pragma once#include "stdafx.h"#include <gtest/gtest.h>class 我的全局环境设置 : public testing::Environment{public:virtual void SetUp(){std::cout << "全局环境启动 SetUP" << std::endl;}virtual void TearDown(){std::cout << "全局环境完成 TearDown" << std::endl;}我的全局环境设置() { std::cout << "全局环境的构造函数" << std::endl; }~我的全局环境设置() { std::cout << "析构函数" << std::endl; } //no use};class 套装例⼦ : public testing::Test{protected:static void SetUpTestCase(){std::cout << "测试套装启动 SetUpTestCase" << std::endl;}static void TearDownTestCase(){std::cout << "测试套装完成 TearDownTestCase" << std::endl;}protected:virtual void SetUp(){std::cout << "个例测试启动 SetUp" << std::endl;}virtual void TearDown(){std::cout << "个例测试完成 TearDown" << std::endl;}};TEST_F(套装例⼦, 套装例⼦1){}TEST_F(套装例⼦, 套装例⼦2){}#include "stdafx.h"#include <gtest/gtest.h>#include "JFgTest.h"int main(int argc, _TCHAR* argv[]){testing::AddGlobalTestEnvironment( new 我的全局环境设置);testing::InitGoogleTest(&argc, argv);int a = RUN_ALL_TESTS();system("pause");return a;}全局环境的构造函数[==========] Running 2 tests from 1 test case.[----------] Global test environment set-up.全局环境启动 SetUP[----------] 2 tests from 套装例⼦测试套装启动 SetUpTestCase[ RUN ] 套装例⼦.套装例⼦1个例测试启动 SetUp个例测试完成 TearDown[ OK ] 套装例⼦.套装例⼦1 (3 ms)[ RUN ] 套装例⼦.套装例⼦2个例测试启动 SetUp个例测试完成 TearDown[ OK ] 套装例⼦.套装例⼦2 (3 ms)测试套装完成 TearDownTestCase[----------] 2 tests from 套装例⼦ (8 ms total)[----------] Global test environment tear-down全局环境完成 TearDown[==========] 2 tests from 1 test case ran. (21 ms total) [ PASSED ] 2 tests.请按任意键继续. . .。
UnitTest相关问题汇总1、测试私有⽅法(1)使⽤反射public class Calcutate {public int test() {return add(2, 3);}private int add(int a, int b) {return a + b;}}public class CalcutateTest {@Testpublic void testAdd() {Calcutate cal = new Calcutate();Object result = null;try {Method method = cal.getClass().getDeclaredMethod("add",new Class[] { int.class, int.class });// 获得method.注意,这⾥不能使⽤getMethod⽅法,因为这个⽅法只能获取public修饰的⽅法.. method.setAccessible(true);// 这个设置为true.可以⽆视java的封装..不设置这个也⽆法或者这个Methodresult = method.invoke(cal, new Object[] { 2, 10 });} catch (Exception e) {e.printStackTrace();}Assert.assertEquals("Must equals.", 13, result);// 这⾥⾃定拆箱..}}method.setAccessible(true);如果不显⽰设为true,则报错:ng.IllegalAccessException: Class CalcutateTest can not access a member of class Calcutate with modifiers "private"at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)at ng.reflect.Method.invoke(Unknown Source)at com.test.junit.CalcutateTest.testAdd(CalcutateTest.java:17)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)at ng.reflect.Method.invoke(Unknown Source)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)at org.junit.runners.ParentRunner.run(ParentRunner.java:309)at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)。
GoogleC++单元测试框架---Gtest框架简介(译⽂)⼀、设置⼀个新的测试项⽬在⽤google test写测试项⽬之前,需要先编译gtest到library库并将测试与其链接。
我们为⼀些流⾏的构建系统提供了构建⽂件: msvc/ for Visual Studio, xcode/ for Mac Xcode, make/ for GNU make, codegear/ for Borland C++ Builder.如果你的构建系统不在这个名单上,在googletest根⽬录有autotools的脚本(不推荐使⽤)和CMakeLists.txtCMake(推荐)。
你可以看看make / Makefile来了解如何编译Google Test(基本上你想在头⽂件中使⽤GTEST_ROOT和GTEST_ROOT / include来编译src / 路径,其中GTEST_ROOT是Google测试根⽬录)。
⼀旦你能够编译google test库,您应该为您的测试程序创建⼀个项⽬或构建⽬标。
Make sure you have GTEST_ROOT/include in the header search path so that the compiler can find "gtest/gtest.h" when compiling your test.把google test库加到你的测试项⽬中(⽐如:在VS 中在gtest.vcproj上添加依赖)。
⼆、基本概念当使⽤⾕歌测试,您⾸先要写断⾔,断⾔是检查条件是否为真的语句。
⼀个断⾔的结果可以是成功,⾮致命性失败,或致命的失败。
如果⼀个致命失败出现,它会终⽌当前的函数;否则程序继续正常运⾏。
测试使⽤断⾔验证代码的⾏为。
如果⼀个测试崩溃或者有⼀个失败的断⾔,那么失败;否则成功。
⼀个测试⽤例包含⼀个或多个测试。
您应该将测试分组为反映测试代码结构的测试⽤例。
ut测试private方法以UT测试Private方法为题,我们来探讨一下如何在软件开发过程中进行Private方法的单元测试。
Private方法是指仅在类内部可见,无法从外部直接调用的方法。
对于Private方法的测试,有以下几个关键点需要注意。
我们需要了解为什么需要测试Private方法。
虽然Private方法在设计上是为了封装内部实现细节,但它们往往承担着重要的功能,对整个类的行为产生影响。
因此,为了确保类的功能和质量,我们需要对Private方法进行测试。
接下来,我们来讨论如何测试Private方法。
由于Private方法无法从外部直接调用,我们无法像测试Public方法那样直接调用并断言结果。
但是,我们可以通过以下几种方法来进行测试。
第一种方法是通过反射来调用Private方法。
反射是一种强大的机制,可以让我们在运行时获取类的信息并操作其私有成员。
通过反射,我们可以获取Private方法的引用并调用它,从而进行测试。
然而,使用反射需要额外的代码,并且可能会破坏封装性,因此在使用时需要慎重考虑。
第二种方法是将Private方法改为Protected方法。
Protected方法是指只能在类内部和子类中调用的方法。
通过将Private方法改为Protected方法,我们可以在测试类或子类中调用该方法进行测试。
这种方法相对简单,但也需要修改源代码,可能会导致其他地方的调用出现问题。
第三种方法是使用PowerMock等测试框架来测试Private方法。
PowerMock是一个强大的测试框架,可以模拟Private方法的调用。
它能够绕过访问修饰符的限制,直接调用Private方法并进行断言。
使用PowerMock需要在测试类中引入相关的注解和依赖,并对被测试类进行一些修改。
无论采用哪种方法,我们在测试Private方法时都需要注意以下几点。
我们需要确保测试的覆盖率。
即使是Private方法,也需要覆盖其各种可能的执行路径,以保证代码的完整性和稳定性。
用gtest测试类的私有成员
使用gtest、或者cppunit之类的框架编写单元测试代码,一个最常见的问题是对类私有成员的测试与验证。
理想情况下,我们希望在测试中,类中所有的数据与方法都是可以访问的;而在产品代码中,只暴露实现定义好的接口。
gtest官方文档中,也提到了对私有成员的处理,方法不外乎两种:一是使用friend关键字,骗取信任得以通行;二是重构采用Pimpl模式,公共类中只暴露接口,而实现类中暴露所有细节(public),测试时包含实现类即可。
但这两个方法都试了一下,觉不太方便。
∙使用friend关键字
gtest提供了一个FRIEND_TEST的宏,用来将一个test声明为产品类的
友元。
其缺点是显而易见的。
一是需要往产品类中添加纯测试代码;二是每加一个test,需要在产品类中添加一项FRIEND_TEST。
∙重构采用Pimpl模式
我认可Pimpl模式,但同时我也不会对所有的类都这么做。
所以如果让我只是为了支持测试而做这样的重构,我可能并不情愿。
况且,手工重构很麻烦,而我手头也没有这么个自动化的工具。
(当然,我相信这是可以自动化的)
其实我们想要达到的目的无非是:在产品代码中,该pubic的是public,该private的还是private;而在测试代码中,全部都是public。
于是:
1 #ifdef GTEST
2 #define private public
3 #define protected public
4 #endif
将其放在每个类的声明前,或者放在一个单独的头文件如ForcePublic.h中并包含之。
这样,在编译测试代码时,加上GTEST的预编译宏,就可以非常方便的使用被测试类中的任何成员了,并不会对产品代码产生任何的影响。
如果你是以纯源代码的方式使用你的产品类的,这个方法没有任何问题;但如果你是通过静态库,或者动态库的方式使用你的产品类的,在测试代码中若直接使用这些库,编译是没有问题,因为全伪装成了public,但在链接的时候,因为private的成员是没有从库中导出来的,必然会出现链接错误。
此时有两个方案:一是以GTEST的方式重新编译库;二是直接将产品源代码编译进你的测试工程中去。
我使用的是动态库,选择了将代码编译进测试工程的方法,为了解决dllexport, dllimport相关的一些编译问题,还做了如下定义:
1 #ifdef TXNMGR_EXPORTS
2 #define TXNMGR_API __declspec(dllexport)
3 #else
4 #ifdef GTEST
5 #define TXNMGR_API
6 #else
7 #define TXNMGR_API __declspec(dllimport)
8 #endif
9 #endif
这样,在测试工程中,TXNMGR_API宏的定义为空,自然被忽略了,而不会影响
到产品代码。
感觉着这种方法的好处在于只要在一开始做一些小小的修改,便可以一劳永逸的解决访问所有产品类所有私有成员的问题;由于我们改变的只是成员的访问级别,对类的行为应该没有什么影响。
更新:
在gtest的google group中就这个问题提出了讨论,大家指出这种方式的问题在于:
∙使得访问私有成员过分容易,从而导致写出来的test访问私有成员的可能性增大。
测试访问了私有成员,也就是依赖于实现,这让单元测试成为
你重构的负担,而不是保证。
∙万战勇同学也指出,这种方法是不标准的C++用法: 一是C++标准不允许重定义关键词,所以这种方法即使此时在你当前的编译器上是可行的,你
也不能保证将来,或者在其他编译器上可行;二是public, protected
private等访问修饰符可能会影响对象成员的布局,这样当你的测试是直
接链接到产品代码时会有些问题。
所以,除非你对以上两点十分清楚并且可以接受,不然,还是使用官方的FRIEND_TEST要更好一些。
∙因为每一个需要访问私有成员的test都需要在产品代码上加上一项 FRIEND_TEST,这会让你思考:我真的需要访问私有成员吗?有没有不
用访问私有成员的方法?从而帮助形成更好的设计与测试∙因为每一个依赖于实现的test都显式的登记在案,这样当你的实现细节有所改变时,你知道会影响哪些test
∙
∙如何使用gtest测试类的成员函数
∙这两天学习了一下gtest,仅仅是接触到了皮毛,有很多问题还是不怎么明白,不过还是要将自己的一点学习心得与大家分享一下。
∙刚开始学习gtest都是直接使用一些函数,但是在c++中我们最经常用到的是类,那么在单元测试的时候如何测这个类呢?
∙gtest的一个特点是它可以参数化,即产生任意类型的对象,包括基本类型和你的自定义类型。
基本类型很简单,对于自定义类型如何测试呢……∙今天在看关于gmock的一篇文章时突然想到了gtest参数化,之前没有想明白如何测试类。
于是自己就随手写了一个测试程序结果真的通过了。
∙在玩转gtest系列文章中有一篇就是介绍参数化,其中的一个例子类似于:∙class testMyMath:public testing::TestWithParam<MyMath> {
∙};
∙
∙这个类是不需要实现的,当然我的意思是不要添加任何的成员变量和函数,因为你只是测试其他的类。
我的待测类是:
∙class MyMath
{
public:
MyMath(void);
MyMath(int x,int y);
int Add();
int Sub();
int Mul();
int Mod();
~MyMath(void);
private:
int m_x;
int m_y;
};
∙这个类用来实现简单的加减乘除而已。
∙关于参数化不多介绍,因为玩转gtest中介绍的已经蛮好了,何况我还是个菜鸟。
∙接下来:
∙TEST_P(testMyMath,test_Add)
{
MyMath my=GetParam();
EXPECT_EQ(3,my.Add());
}
∙TEST_P(testMyMath,test_Sub)
{
MyMath my=GetParam();
EXPECT_EQ(-1,my.Sub());
}
∙TEST_P(testMyMath,test_Mul)
{
MyMath my=GetParam();
EXPECT_EQ(2,my.Mul());
}
∙TEST_P(testMyMath,test_Mod)
{
MyMath my=GetParam();
EXPECT_EQ(0,my.Mod());
}
∙关于TEST_P这个宏也不介绍,只是要说一点第一个参数一定要是你写的那个用来产生测试类类型的那个类,这里必须是testMyMath,第二个参数的话就是自己起的测试用例的名字了,我感觉英文文档给颠倒了。
∙然后最后一步通过初始化添加测试数据:
∙INSTANTIATE_TEST_CASE_P(Test_MyMath,testMyMath,testing::Values( MyMath(2,1),MyMath(3,4),MyMath(2,2)));
∙
∙ok,然后在运行就可以了。
∙。