1,通常情况
在工作目录主目录下建立目录src
进入src下建立TestAll.cpp测试主文件.
#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
//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
//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
//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。
#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。
// 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组测试用例的测试数据。
通过
TEST_P(ProcessTestWithTestP,BasicTest)
来实现。
通过
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
来编译,然后通过
./process
来运行
2,静态变量和静态方法
在下面介绍中如何调用静态变量和静态方法,静态变量和静态方法比较简单,一般直接调用就可以。
2.1静态变量
修改process.h文件。
//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来访问。
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文件。
//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()来访问。
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文件。
//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属性。
class ProcessTest : public ::testing::TestWithParam, public Process{
};
然后在测试文件中直接使用x和process()方法。
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文件。
//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属性。
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)在被测类头文件中加入:
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
2)在被测类头文件中预先声明被测类
class 被测类;
3)在被测类头文件中类定义中加入
FRIEND_TEST(被测类, TEST_P);
4)在测试类文件processTest.cpp开始加入:
#include: <cstddef>:定义常用常量
5)在测试类文件processTest.cpp中将测试类定义为保护属性。
class ProcessTest : public ::testing::TestWithParam,protected Process{
};
6)使用第3)步定义的测试方法
TEST_P(被测类, TEST_P)
4.1私有变量
修改process.h文件。
//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文件
//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文件
//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文件同私有变量。
//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
// 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
// MyClassTest.cpp
#include "MyClass.h"
#include
TEST(MyClassTest, IncrementTest) {
MyClass obj;
obj.PerformIncrement(); // 调用公共方法来间接调用私有方法
EXPECT_EQ(1, obj.GetValue()); // 验证私有方法的行为
}
5.2通过公共接口类来访问保护对象和方法
同样也可以通过公共接口类来访问保护对象和方法。
// 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
//MyClassTest.cpp
#include "MyClass.h"
#include
TEST(MyClassTest, ProtectedMethodTest) {
MyClass obj;
obj.CallProtectedMethod(); // 调用公共方法来间接调用保护方法
EXPECT_EQ(42, obj.GetValue()); // 验证保护方法的行为
}
这里介绍了如何通过Gtest访问C++静态、私有、保护变量和方法,下一节将介绍如何通过JUnit访问Java静态、私有、保护变量和方法。