前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通过Gtest访问C++静态、私有、保护变量和方法

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

作者头像
顾翔
发布2024-09-10 15:21:38
2260
发布2024-09-10 15:21:38
举报
文章被收录于专栏:啄木鸟软件测试

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档