1,通常情况
在工作目录主目录下建立目录src
进入src下建立TestAll.cpp测试主文件.
代码语言:javascript
复制
#include "gtest/gtest.h" #include <iostream> using namespace std; int main(int argc,char* argv[]) { testing::GTEST_FLAG(output) = "xml:"; //若要生成xml结果文件 testing::InitGoogleTest(&argc,argv); //初始化 return RUN_ALL_TESTS(); //跑单元测试 }
建立参数化文件CallArgs.h
代码语言:javascript
复制
//CallArgs.cpp #include <gtest/gtest.h> class CallArgs{ public: CallArgs(int haspramx,int hasprama,int haspramb, float hasresult); int pramx(); int prama(); int pramb(); float result(); private: int _hasPramx; int _hasPrama; int _hasPramb; float _hasResult; };
和CallArgs.cpp
代码语言:javascript
复制
//CallArgs.cpp #include <gtest/gtest.h> #include "CallArgs.h" CallArgs::CallArgs(int haspramx,int hasprama,int haspramb, float hasresult): _hasPramx(haspramx),_hasPrama(hasprama),_hasPramb(haspramb),_hasResult(hasresult){} int CallArgs::pramx(){ return _hasPramx;} int CallArgs::prama(){ return _hasPrama;} int CallArgs::pramb(){ return _hasPramb;} float CallArgs::result(){return _hasResult;} int _hasPramx; int _hasPrama; int _hasPramb; float _hasResult;
接下来建立被测文件的头文件process.h
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H class Process { public: int x; Process(); int process(int a, int b); }; #endif
被测文件很简单,包括类变量x和类函数Process,默认为public。本文通过改变类变量x和类函数Process的属性来介绍如何通过Gtest访问C++静态、私有、保护变量和方法。建立被测文件的实现方法,process.cpp。
代码语言:javascript
复制
#include <stdio.h> #include "process.h" int x; Process::Process(){} int Process::process(int a, int b){ if ((a>1) && (b==0)){ Process::x=Process::x/a; } if((a==2) || (Process::x>1)){ Process::x=Process::x+1; } return Process::x; }
在下面的介绍中process.cpp不会做任何变化。下面来建立gtest的测试代码,processTest.cpp。
代码语言:javascript
复制
// ProcessTest.cpp #include "process.h" #include "../../src/CallArgs.h" #include <gtest/gtest.h> class ProcessTestWithTestP:public ::testing::TestWithParam { }; INSTANTIATE_TEST_CASE_P(VOIP, ProcessTestWithTestP, ::testing::Values( CallArgs{1,2,0,1}, CallArgs{0,4,0,0}, CallArgs{1,2,1,2}, CallArgs{0,1,1,0} )); TEST_P(ProcessTestWithTestP,BasicTest){ CallArgs args = GetParam(); Process p; p.x = args.pramx(); EXPECT_FLOAT_EQ(p.process(args.prama(),args.pramb()),args.result()); }
ProcessTestWithTestP为测试类,为了达到被测程序的100%路径覆盖,设计4组测试用例,在Gtest中正好可以使用TEST_P参数化来进行测试。
INSTANTIATE_TEST_CASE_P来初始化这4组测试用例的测试数据。
通过
代码语言:javascript
复制
TEST_P(ProcessTestWithTestP,BasicTest)
来实现。
通过
代码语言:javascript
复制
g++ process.h process.cpp processTest.cpp ../../src/AllTest.cpp ../../src/ CallArgs.cpp.h ../../src/ CallArgs.cpp.cpp -o process -lgtest -lgmock -lpthread -std=c++14
来编译,然后通过
代码语言:javascript
复制
./process
来运行
2,静态变量和静态方法
在下面介绍中如何调用静态变量和静态方法,静态变量和静态方法比较简单,一般直接调用就可以。
2.1静态变量
修改process.h文件。
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H extern int x; class Process { public: Process(); int process(int a, int b); }; #endif
通过extern int x;将x变为静态全局变量,在测试文件procesTest.cpp,可以直接通过x来访问。
代码语言:javascript
复制
TEST_P(ProcessTestWithTestP,BasicTest){ CallArgs args = GetParam(); Process p; x = args.pramx(); EXPECT_FLOAT_EQ(p.process(args.prama(),args.pramb()),args.result()); }
2.2静态方法
修改process.h文件。
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H extern int x; class Process { public: Process(); static int process(int a, int b); }; #endif
通过static int process(int a, int b);将process(int a, int b)变为静态方法,在测试文件procesTest.cpp,仍旧通过p.process()来访问。
代码语言:javascript
复制
TEST_P(ProcessTestWithTestP,BasicTest){ CallArgs args = GetParam(); Process p; x = args.pramx(); EXPECT_FLOAT_EQ(p.process(args.prama(),args.pramb()),args.result()); }
3,保护变量和保护方法
保护变量和保护方法,在测试文件procesTest.cpp定义class ProcessTest类的时候将继承的Process类改为public属性。
3.1保护变量
修改process.h文件。
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H class Process { public: Process(); int process(int a, int b); protected: int x; }; #endif
将int x;放在protected下,在测试文件procesTest.cpp定义class ProcessTest类的时候将继承的Process类改为public属性。
代码语言:javascript
复制
class ProcessTest : public ::testing::TestWithParam, public Process{ };
然后在测试文件中直接使用x和process()方法。
代码语言:javascript
复制
class ProcessTest : public ::testing::TestWithParam, public Process{ }; TEST_P(ProcessTest,BasicTest){ CallArgs args = GetParam(); x = args.pramx(); EXPECT_FLOAT_EQ(process(args.prama(),args.pramb()),args.result()); }
3.2保护方法
修改process.h文件。
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H class Process { public: int x; Process(); protected: int process(int a, int b); }; #endif
将int process(int a, int b);放在protected下,同样在测试文件procesTest.cpp定义class ProcessTest类的时候将继承的Process类改为public属性。
代码语言:javascript
复制
class ProcessTest : public ::testing::TestWithParam, public Process{ }; TEST_P(ProcessTest,BasicTest){ CallArgs args = GetParam(); x = args.pramx(); EXPECT_FLOAT_EQ(process(args.prama(),args.pramb()),args.result()); }
4,私有变量和私有方法
访问私有变量和私有方法比较复杂,不太推荐,因为它会破坏类的封装。但是实现方法基本相同。
1)在被测类头文件中加入:
代码语言:javascript
复制
#define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test
2)在被测类头文件中预先声明被测类
代码语言:javascript
复制
class 被测类;
3)在被测类头文件中类定义中加入
代码语言:javascript
复制
FRIEND_TEST(被测类, TEST_P);
4)在测试类文件processTest.cpp开始加入:
代码语言:javascript
复制
#include: <cstddef>:定义常用常量
5)在测试类文件processTest.cpp中将测试类定义为保护属性。
代码语言:javascript
复制
class ProcessTest : public ::testing::TestWithParam,protected Process{ };
6)使用第3)步定义的测试方法
代码语言:javascript
复制
TEST_P(被测类, TEST_P)
4.1私有变量
修改process.h文件。
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H #define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test class ProcessTest; class Process { public: Process(); int process(int a, int b); private: int x; FRIEND_TEST(ProcessTest, TEST_P); }; #endif
将int x放在private下
修改processTest.cpp文件
代码语言:javascript
复制
//ProcessTest.cpp #include "process.h" #include "../../../src/CallArgs.h" #include <gtest/gtest.h> #include <cstddef> class ProcessTest : public ::testing::TestWithParam,protected Process{ }; INSTANTIATE_TEST_CASE_P(VOIP, ProcessTest, testing::Values( CallArgs{1,2,0,1}, CallArgs{0,4,0,0}, CallArgs{1,2,1,2}, CallArgs{0,1,1,0} )); TEST_P(ProcessTest, TEST_P){ CallArgs args = GetParam(); Process p; p.x = args.pramx(); EXPECT_FLOAT_EQ(p.process(args.prama(),args.pramb()),args.result()); }
4.2私有方法
修改process.h文件
代码语言:javascript
复制
//process.h #ifndef PROCESS_H #define PROCESS_H #define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test class ProcessTest; class Process { public: Process(); int x; private: int process(int a, int b); FRIEND_TEST(ProcessTest, TEST_P); }; #endif
将int process(int a, int b);放在private下
修改processTest.cpp文件同私有变量。
代码语言:javascript
复制
//ProcessTest.cpp #include "process.h" #include "../../../src/CallArgs.h" #include <gtest/gtest.h> #include <cstddef> class ProcessTest : public ::testing::TestWithParam,protected Process{ }; INSTANTIATE_TEST_CASE_P(VOIP, ProcessTest, testing::Values( CallArgs{1,2,0,1}, CallArgs{0,4,0,0}, CallArgs{1,2,1,2}, CallArgs{0,1,1,0} )); TEST_P(ProcessTest, TEST_P){ CallArgs args = GetParam(); Process p; p.x = args.pramx(); EXPECT_FLOAT_EQ(p.process(args.prama(),args.pramb()),args.result()); }
另外,还可以通过公共接口类来访问私有和保护对象和方法。
5,通过公共接口类来访问私有和保护对象和方法
5.1 通过公共接口类来访问私有对象和方法
MyClass.h
代码语言:javascript
复制
// MyClass.h class MyClass { private: int value; void Increment() { // 私有方法 value++; } public: MyClass() : value(0) {} void PerformIncrement() { // 公共方法 Increment(); } int GetValue() const { // 公共方法,用于获取私有成员的值 return value; } };
MyClass.h定义了私有类value和私有方法Increment()。
通过公共方法PerformIncrement()来调用私有方法Increment();
通过公共方法GetValue()来获取私有成员value的值。
建立测试程序MyClassTest.cpp
代码语言:javascript
复制
// MyClassTest.cpp #include "MyClass.h" #include TEST(MyClassTest, IncrementTest) { MyClass obj; obj.PerformIncrement(); // 调用公共方法来间接调用私有方法 EXPECT_EQ(1, obj.GetValue()); // 验证私有方法的行为 }
5.2通过公共接口类来访问保护对象和方法
同样也可以通过公共接口类来访问保护对象和方法。
代码语言:javascript
复制
// MyClass.h class MyClass { protected: int value; void ProtectedMethod() { // 保护方法 value = 42; } public: MyClass() : value(0) {} void CallProtectedMethod() { // 公共方法,调用保护方法 ProtectedMethod(); } int GetValue() const { // 公共方法,用于获取保护成员的值 return value; } };
MyClass.h定义了int value;保护变量和void ProtectedMethod()保护方法。
通过公共方法CallProtectedMethod()调用保护方法;
通过公共方法GetValue()获取保护成员的值。
建立测试程序MyClassTest.cpp
代码语言:javascript
复制
//MyClassTest.cpp #include "MyClass.h" #include TEST(MyClassTest, ProtectedMethodTest) { MyClass obj; obj.CallProtectedMethod(); // 调用公共方法来间接调用保护方法 EXPECT_EQ(42, obj.GetValue()); // 验证保护方法的行为 }
这里介绍了如何通过Gtest访问C++静态、私有、保护变量和方法,下一节将介绍如何通过JUnit访问Java静态、私有、保护变量和方法。