C++单元测试Gtest+Stub攻略

这篇具有很好参考价值的文章主要介绍了C++单元测试Gtest+Stub攻略。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

笔者环境为linux环境(deepin),以下均在此环境进行

环境搭建

Gtest源码链接
Stub源码链接
StubExt源码链接

Stub的使用方法在cpp-stub/README_zh.md中有讲解
StubExt的使用方法在 cpp-stub-ext/ README.md中有讲解

StubExt可支持Lambda表达式进行打桩写Gtest时如果想获取一个固定的返回值或者出参十分好用

搭建环境时如果不想下载Gtest源码可以直接使用Stub中提供的Gtest库
仔细阅读README中说明,查看Stub源码提供的Demo

gtest打桩函数,C/C++,单元测试,c++,linux
stubext.h中需要引用stub.h,并且需要将stub.h中的private改为protected

写Gtest时只要引用
#include “gtest/gtest.h”
#include “stubext.h”
#include “addr_pri.h”

编写单元测试

gtest的使用

Gtest提供了几个不同case方法进行测试不同的用例。主要常见的有TEST/TEST_F及TEST_P宏的使用。在每个TestCase中可以通过断言提供的方法进行控制检查程序的预期走向是否是期望的结果,从而以此来判定程序的正确性。

TEST的第一个参数一般情况下使用类名或者文件名,第二个参数一般情况下写要测试的函数名,如果一个函数需要写多个测试用例第二个参数增加一些后缀区分

TEST(test_case_name, test_name){
	//编写你的TestCase
	//使用EXPECT_EQ,ASSERT_EQ等去判断TestCase的值是否和期望值一致
}

这里说下EXPECT_*和ASSERT_*的区别,EXPECT_*如果当前不成立会继续执行当前TestCase而ASSERT_*如果不成立会直接结束当前TestCase

TEST_F的第一个参数为TestBase第二个参数一般情况下写要测试的函数名,如果一个函数需要写多个测试用例第二个参数增加一些后缀区分

class TestTmp{
    public:
    void setA(int a){
        this->a=a;
    }
    int getA(){
        return a;
    }
    private:
    int a;    
};
class TestBase : public ::testing::Test
{
  protected:
    // 为测试准备数据对象
    void SetUp() override
    {
    	t.setA(10);
    }
    // 清除资源
    void TearDown() override
    {
    }
	TestTmp t;
};
TEST_F(TestBase,test1){
    int b =t.getA();
    EXPECT_EQ(10,b);
    t.setA(99);
    int c = t.getA();
    EXPECT_EQ(99,c);
}
TEST_F(TestBase,test2){
    int b =t.getA();
    EXPECT_EQ(10,b);
}

输出如下:
gtest打桩函数,C/C++,单元测试,c++,linux
通过输出可以看出在test1中调用的t.setA(99);在test2中并未生效,所以TEST_F只是通过自定义一个类实现了一些资源的准备,在各个TEST_F中都可以使用准备好的资源,如果在TEST_F中修改了准备好的资源也只对当前这个TEST_F有效.

TEST_P的参数和TEST_F类似

class TestTmp{
    public:
        void setA(std::string a){
            this->a=a;
        }
        std::string getA(){
            return a;
        }
    private:
    std::string a;
};
class StringsFixture : public ::testing::TestWithParam<std::string>
{
    public:
        virtual void SetUp()
        {
            t.setA("test");
        }
        virtual void TearDown()
        {
            // Do some tear down
        }
        TestTmp t;
};


INSTANTIATE_TEST_SUITE_P(
    aValue,  // Instantiation name
    StringsFixture,  // Fixture controller
    ::testing::Values(  // Parameters
        "qwe",
        "asd",
        "zxc",
        "bnm",
        "tyu",
        "iop"
    )
);
TEST_P(StringsFixture,test1){
    auto test_str = this->GetParam();
    EXPECT_STREQ(t.getA().c_str(),"test");
    t.setA(test_str);
    EXPECT_STREQ(t.getA().c_str(),test_str.c_str());
}

TEST_P相当于对这个案例做了一个循环调用,参数值设置几个就会调用几次,每次调用可以通过this->GetParam();获取之前预制的参数值.如果有案例需要重复输入不同的参数去测试就可以使用这种方式来减少代码量.

Stub/StubExt的使用

Stub是通过改变运行是调用进程内存页,将原本调用的函数地址改为打桩函数的地址从而去满足打桩需求.

int fun()
{
    int a=10;
    LOGD("--------------------------------------------fun");
    return a;
}
int fun_stub()
{
    int a=99;
    LOGD("--------------------------------------------stub");
    return a;
}
TEST(test_case_name, test_name)
{
    Stub stub;
    stub.set(fun, fun_stub);
    int ret = fun(); //调用fun就去执行fun_stub中的代码
    EXPECT_EQ(ret, 99);
    stub.reset(fun);
    ret = fun(); //此时调用fun就执行fun中的代码
    EXPECT_EQ(ret, 10);
}
TEST(test_case_name, test_name1)
{
    StubExt stub;
    int dd = 0;
    stub.set_lamda(fun, [&dd](){
        dd = 55;
        return dd;
    });
    int ret = fun(); //调用fun就去执行fun_stub中的代码
    EXPECT_EQ(ret, 55);
}

Stub只可以通过桩函数fun_stub实现打桩,StubExt可以通过set设置桩函数也可以通过set_lamda设置lambda表达式并且如果你不关注返回值和参数可以统统都不设置让设置的函数执行个空相当于被打桩函数被跳过.更加详细的使用方式请参考README和doc_zh.md
注意事项:
Stub::set()和Stub::reset()一定要成对出现除非你想在后面执行的程序都走到桩函数中去
addr_pri.h中定义了获取私有成员私有方法的宏这里简单列举,具体的可以到README和doc_zh.md中通过下面的关键字搜索文章来源地址https://www.toymoban.com/news/detail-689634.html

Declaration:
    ACCESS_PRIVATE_FIELD(ClassName, TypeName, FieldName)
    ACCESS_PRIVATE_FUN(ClassName, TypeName, FunName)
    ACCESS_PRIVATE_STATIC_FIELD(ClassName, TypeName, FieldName)
    ACCESS_PRIVATE_STATIC_FUN(ClassName, TypeName, FunName)

Use:
    access_private_field::ClassNameFieldName(object);
    access_private_static_field::ClassName::ClassNameFieldName();
    call_private_fun::ClassNameFunName(object,parameters...);
    call_private_static_fun::ClassName::ClassNameFunName(parameters...);
    get_private_fun::ClassNameFunName();
    get_private_static_fun::ClassName::ClassNameFunName();

到了这里,关于C++单元测试Gtest+Stub攻略的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++单元测试GoogleTest和GoogleMock十分钟快速上手(gtest&gmock)

    下载 安装 重要文件 googletest gtest/gtest.h libgtest.a libgtest_main.a 当不想写 main 函数的时候,可以直接引入 libgtest_main.a; 否则 googlemock gmock/gmock.h libgmock.a libgmock_main.a 一 .断言 gtest 中的断言分成两大类: ASSERT_* 系列:如果检测失败就直接退出 当前函数 EXPECT_* 系列:如果检测失败

    2024年02月06日
    浏览(39)
  • 玩转Google开源C++单元测试框架Google Test系列(gtest)之六 - 运行参数

    目录 一、前言 二、基本介绍 三、参数列表 四、XML报告输出格式 五、总结 使用gtest编写的测试案例通常本身就是一个可执行文件,因此运行起来非常方便。同时,gtest也为我们提供了一系列的运行参数(环境变量、命令行参数或代码里指定),使得我们可以对案例的执行进行

    2024年02月07日
    浏览(68)
  • gtest--单元测试

    gtest是Google的一套用于编写C++测试的框架,可以运行在很多平台上(包括Linux、Mac OS X、Windows、Cygwin等等)。基于xUnit架构。支持很多好用的特性,包括自动识别测试、丰富的断言、断言自定义、死亡测试、非终止的失败、生成XML报告等等。 好的测试应该有下面的这些特点,我

    2024年02月13日
    浏览(34)
  • gtest单元测试

    gtest是 Google 的一套用于 编写C++测试的框架 ,可以运行在很多平台上(包括Linux、Mac OS X、Windows、Cygwin等等)。基于xUnit架构。支持很多好用的特性,包括自动识别测试、丰富的断言、断言自定义、死亡测试、非终止的失败、生成XML报告等等。 测试应该是 独立的、可重复 的。

    2024年02月08日
    浏览(74)
  • 使用gtest做单元测试

    gtest是一个跨平台的(Liunx、Mac OS X、Windows 、Cygwin 、Windows CE and Symbian ) C++单元测试框架,由google公司发布。gtest是为在不同平台上为编写C++测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等 配置gtest头文件及库 下载gtest源码: Releases · goog

    2023年04月12日
    浏览(30)
  • 玩转单元测试之gtest

    程序开发的时候,往往需要编写一些测试样例来完成功能测试,以保证自己的代码在功能上符合预期,能考虑到一些异常边界问题等等。 1.引入gtest 2.编写第一个单测 2.1 待测试文件 2.2 单测文件 2.3 makefile文件 make ./hello_unit_test 编译并执行单测程序,执行结果如下: 1. 各种断

    2024年02月12日
    浏览(34)
  • cmake应用:集成gtest进行单元测试

    编写代码有bug是很正常的,通过编写完备的单元测试,可以及时发现问题,并且在后续的代码改进中持续观测是否引入了新的bug。对于追求质量的程序员,为自己的代码编写全面的单元测试是必备的基础技能,在编写单元测试的时候也能复盘自己的代码设计,是提高代码质量

    2024年02月13日
    浏览(40)
  • CMake项目使用ctest+gtest进行单元测试

    随着CMake工具越来越强大便捷,越来越多的C/C++项目转而使用CMake来进行编译管理,它还提供了用于测试的ctest命令来执行项目中编写的单元测试。 本文就以一个实例来介绍如何使用ctest来进行单元测试。 本文实例环境VSCode+MinGW64+CMake+gtest。 需要在MinGW中安装gtest,如果没有安装

    2024年02月05日
    浏览(40)
  • 基于gtest/gmock/mockcpp的单元测试探索

    本文整体内容参考https://www.cnblogs.com/heimianshusheng/p/13530672.html(后面统一称为\\\"引文\\\"),在实际调试中发现了一些问题并予以解决,记录一下方便自己和同道中人查阅。 通过实例演练学习使用gtest对C语言编写的程序进行单元测试 学习如何用mockcpp对C语言的函数进行mock *GitHub上的

    2023年04月21日
    浏览(37)
  • 手把手教你使用gtest写单元测试

    开源框架:gtest,它主要用于写单元测试,检查真自己的程序是否符合预期行为。这不是QA(测试工程师)才学的,也是每个优秀后端开发codoer的必备技能。 本期博文内容及使用的demo,参考: Googletest Basic Guide[1] Googletest Samples [2] 构建依赖环境 按照惯例,先介绍下怎么基于

    2024年02月16日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包