通过Gtest访问C++静态、私有、保护变量和方法

2024-09-10 15:21:38 浏览数 (2)

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静态、私有、保护变量和方法。

0 人点赞