玩转单元测试之gtest

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

引言

程序开发的时候,往往需要编写一些测试样例来完成功能测试,以保证自己的代码在功能上符合预期,能考虑到一些异常边界问题等等。

gtest快速入门

1.引入gtest

# 使用的是1.10版本,其他版本可根据需要选择
git clone -b v1.10.x https://github.com/google/googletest.git
cd googletest
mkdir build && cd build
cmake .. && make -j4
sudo make install
sudo ldconfig

2.编写第一个单测

2.1 待测试文件

#ifndef __HELLO_H__
#define __HELLO_H__

#include <iostream>
#include <string>

class Animal {
public:
    Animal(std::string name) 
        : _name(name)
    {
        
    }
    virtual ~Animal() {}
    virtual bool eat(const std::string& food) = 0;

private:
    std::string _name;
};

class Tigger : public Animal {
public:
    Tigger() : Animal("tigger")
    {

    }
    bool eat(const std::string& food) override
    {
        if (food == "meat") {
            return true;
        }
        return false;
    }
};

class Horse : public Animal {
public:
    Horse() : Animal("Horse")
    {
         
    }
    bool eat(const std::string& food) override
    {
        if (food == "grass") {
            return true;
        }
        return false;
    }
};
#endif

2.2 单测文件

#include "hello.h"
#include "gtest/gtest.h"

using namespace ::testing;

namespace {
TEST(TestTigger, CaseEat) 
{
    Animal *tigger = new Tigger();
 	bool ret = tigger->eat("meat");
    EXPECT_TRUE(ret);

    ret = tigger->eat("grass");
    EXPECT_FALSE(ret);
    delete tigger;
}

TEST(TestHorse, CaseEat)
{
    Animal *horse = new Horse();
    bool ret = horse->eat("grass");
    EXPECT_TRUE(ret);

    ret = horse->eat("meat");
    EXPECT_FALSE(ret);
    delete horse;
}
}

2.3 makefile文件

CXX = g++
CXXFLAGS = -Wall
LIBES = -lgtest -lgtest_main -lpthread
LPATH = -L/tools/googletest/1.11.0/build/lib  # 替换成自己lib路径
HPATH = -I/tools/googletest/1.11.0/googletest/include/ # 替换成自己的include路径

UTEST_OBJD = hello_unit_test

hello_unit_test:hello_unit_test.cpp
	${CXX} -o $@ $+ -I ../ ${HPATH} ${CXXFLAGS} ${LIBES} ${LPATH}

clean:
	rm -rf *_unit_test

make && ./hello_unit_test 编译并执行单测程序,执行结果如下:
玩转单元测试之gtest,生产工具,单元测试,c++

gtest常用宏

1. 各种断言

1.1 Bool断言
致命断言 非致命断言 含义
ASSERT_TRUE(val) EXPECT_TRUE(val) val == true
ASSERT_FALSE(val) EXPECT_FALSE(val) val == false
1.2 二元值断言(比较大小)
致命断言 非致命断言 含义
ASSERT_EQ(a, b) EXPECT_EQ(a, b) a == b
ASSERT_NE(a, b) EXPECT_NE(a, b) a != b
ASSERT_LT(a, b) EXPECT_LT(a, b) a < b
ASSERT_LE(a, b) EXPECT_LE(a, b) a <= b
ASSERT_GT(a, b) EXPECT_GT(a, b) a > b
ASSERT_GE(a, b) EXPECT_GE(a, b) a >= b
1.3 字符串断言(字符串比较)
致命断言 非致命断言 含义
ASSERT_STREQ(a, b) EXPECT_STREQ(a, b) a == b
ASSERT_STRNE(a, b) EXPECT_STRNE(a, b) a != b
ASSERT_STRCASEEQ(a, b) EXPECT_STRCASEEQ(a, b) a == b 忽略大小写
ASSERT_STRCASENE(a, b) EXPECT_STRCASENE(a, b) a != b 忽略大小写

2. TEST、TEST_F和TEST_P

2.1 TEST

TEST是最基本的构造测试case的宏,基本用法:

TEST(param1, prama2)
{
/*测试代码*/
}
  • 参数1:用例名,一般由待测试的类名或函数名组成,如TestAnimal
  • 参数2:测试名,代表测试含义,如CaseEat
  • 测试结果将以"用例名.测试名"来区分不同测试case
2.2 TEST_F

TEST_F和TEST的不同之处在于,其可以使用到初始化函数(SetUp)和一个清理函数(TearDown)。基本用法如下:

class TestAnimal : public ::testing::Test {
protected:
	void SetUp() override
	{
		// 成员变量初始化
		tigger = new Tigger();
	}
	void TearDown() override
	{
		// 资源清理、释放
		delete tigger;
		tigger = NULL;
	}
protected:
	Animal *tigger;
};

TEST_F(TestAnimal, caseEatMeat)
{	
	// 执行之前调用SetUp进行初始化
	EXPECT_TRUE(tigger->eat("meat"));
	// case退出时调用TearDown进行释放
}

TEST_F(TestAnimal, caseEatGrass)
{
	// 执行之前调用SetUp进行初始化
	EXPECT_FALSE(tigger->eat("grass"));
	// case退出时调用TearDown进行释放
}
  • 创建一个继承testing::Test的测试类TestAnimal,并在该类中声明成员变量,做好初始化和清理操作
  • TEST_F宏
    • 参数1:同测试类名(TestAnimal )
    • 参数2:测试名,代表测试含义
  • 每一个测试case都是相互独立的,当每个case需要共同使用某个变量时,可以将该变量放在测试类中,每执行一个TEST_F宏构造的case,都会调用一次SetUp和TearDown,因此case之间对变量的操作不会相互影响
2.3 TEST_P

针对某个待测试的方法,当你需要测试不同的输入,但又不想每个case都写一遍时,就可以使用到TEST_P宏,基本使用如下:文章来源地址https://www.toymoban.com/news/detail-662656.html

// 多个参数时,使用结构体更方便
struct MyParams {
	std::string food;
	// other params
};
class TestAnimal : public ::testing::Test, public ::testing::WithParamInterface<MyParams>
{
protected:
	void SetUp() override
	{
		// 成员变量初始化
		tigger = new Tigger();
	}
	void TearDown() override
	{
		// 资源清理、释放
		delete tigger;
		tigger = NULL;
	}
protected:
	Animal *tigger;
};

TEST_P(TestAnimal, caseEat) 
{
	std::string food = GetParam().food; // 获取参数
	ASSERT_FALSE(tigger->eat(food));
}

// 构造不同的测试样例
INSTANTIATE_TEST_SUITE_P(TestCaseEatParams, TestAnimal, ::testing::Values(
	MyParams{"grass"},
	MyParams{"leafs"}
));
  • 和TEST_F有相似的功能,使用SetUp、TearDown进行初始化和清理,创建一个继承testing::Test、testing::WithParamInterface的测试类,其中WithParamInterface是一个模板类,用来关联测试参数。
  • TEST_P宏
    • 参数1:测试类名
    • 参数2:测试名,代表测试含义
  • INSTANTIATE_TEST_SUITE_P宏
    • 参数1:能表明测试含义即可
    • 参数2:测试类名
    • 参数3:不同测试样例集合
  • 执行结果如下:
    玩转单元测试之gtest,生产工具,单元测试,c++

总结

  • 好记性不如烂笔头,最近在写单元测试,于是就有了这篇文章。
  • 通过学习gtest的基本语法,已经可以应对一部分测试场景了,然而还有一些场景只通过gtest是无法完成的,比如,在我们的代码中有许多并不是我们自己设计的接口,可能是外部依赖,也可能来自于其他模块,我们没办法设计一个合适的case来让这些接口返回给我们一个预期值,那我们该怎么办呢?于是gmock由此诞生,这个在下一篇中会进行深入学习,篇名我已经想好了(玩转单元测试之GMock)

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

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

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

相关文章

  • 生产力工具|GitHub的使用与将其应用到生产中

            GitHub (GitHub: Let’s build from here · GitHub)是一个面向开源及私有软件项目的托管平台,它提供了版本控制功能和协作特性,使得团队成员可以共同协作开发、合并代码、跟踪问题和管理项目。以下是一些 GitHub 的介绍和操作技巧: 版本控制:  GitHub 使用 Git 作为版

    2024年03月28日
    浏览(55)
  • AIGC - 生产力新工具 Copilot

    https://github.com/features/copilot Copilot的主要功能包括: 代码补全和提示:Copilot会根据上下文,智能提示您可能需要的变量,函数,参数等。 快速生成代码:Copilot可以快速生成if语句,for循环,类定义,函数定义等代码模板。 代码优化:Copilot会检测代码并提供重构方案,比如提取方法,调整变量

    2024年02月01日
    浏览(43)
  • 22个提升生产力的工具推荐,稳了

    子曰: 工欲善其事,必先利其器 。 本文给大家推荐22个提高生产力的工具,总有一款符合你的需求。😄😄😄 作为一名开发人员,任务管理是必不可少的。任务管理工具不仅可以帮助开发人员管理日常任务,还可以将任务分解成小部分,并按照优先级进行优化。这里推荐滴

    2024年02月06日
    浏览(69)
  • AI,新时代的生产力工具

    以后每个人在每个领域都会有自己的智能AI助理 AI就是新时代的生产力工具,用得好就能上火星,用不好也能到月球,不用的话你只能停留在地球 有写文的AI,你给个框架、设定,帮你成文 有画画的AI,你给个描述、场景,帮你成画 … ChatGPT就是最明显的代表 ,用来改论文、

    2024年02月13日
    浏览(63)
  • 先进API生产力工具eqable HTTP,一站式开发调试工具推荐

    Reqable是什么? Regable = Fiddler/Charles + Postman Reqable是HTTP一站式开发+调试国产化解决方案,拥有更便捷的体验,更先进的协议,更高效的性能和更精致的界面。 Reqable是一款跨平台的专业HTTP开发和调试工具,在全平台支持HTTP1、HTTP2和HTTP3(QUIC)协议,简单易用、功能先进、性能高效

    2024年02月11日
    浏览(55)
  • Apipost超高效的生产力工具(入门学习)

    【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我

    2023年04月08日
    浏览(50)
  • AIGC - 生产力新工具 Bito AI

    Bito AI是继Github Copilot、Cursor、CodeWhisperer等AI智能编程产品之后发了一大AI编程工具 。 Bito是一款建立在OpenAI和ChatGPT模型之上的人工智能编程辅助软件,Bito AI可以帮助开发人员大幅提升工作效率。 以下是Bito AI 编程助手可以辅助我们完成的一些能力。 生成代码:向Bito提出任何

    2024年02月09日
    浏览(55)
  • 咚咚咚,穷人版生产力工具,好用到飞起

    每个程序员都有自己的生产力工具,不管你是深耕职场多年的老鸟,还是在学校努力学习的小鸟,应该都有自己囊里私藏的好辅助。比如帮你完成从头脑风暴草图到创建线框图/原型的UI工具,让代码规范和交付更为可靠的版本控制工具等等。 今天笔者给大家推荐一款低调且强

    2024年02月08日
    浏览(62)
  • 生产力工具|卸载并重装Anaconda3

             官方推荐的方案是两种,一种是直接在Anaconda的安装路径下,双击:  (可以在搜索栏或者使用everything里面搜索找到这个软件,一般你下载安装的时候都会有的。) 或者说是直接到控制面板找到Anaconda直接卸载就行了。 但是这种方案并不能删除配置文件 。 (

    2024年01月25日
    浏览(60)
  • 【AI生产力工具】Midjourney:为创意人士提供创造性灵感和支持的工具

    在现代社会,创意和创新成为越来越重要的能力。然而,创意灵感的获取却不是一件容易的事情,这就需要我们使用一些辅助工具来帮助我们发现和实现创新的想法。而Midjourney就是这样一款强大的工具。 Midjourney是一款创造性灵感工具,它可以帮助用户在不同的领域中创造、

    2024年02月09日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包