当前位置: 首页 > article >正文

软件测试:C++ Google Test单元测试框架GTest

目录

        • 编译和安装
        • 框架使用
          • Assertions
          • Google Testing
          • Google Mocking
          • Matchers
          • Actions
        • 运行结果

最近在写项目的时候,学到了许多关于软件测试的知识,也不断的使用新的测试框架和测试工具,每次总是机械式的拼接其他人的代码,代码发生错误也不知道怎么解决,因此我打算直接将其学一遍,以便为了更灵活的写测试代码

编译和安装

下载地址:Google Test Github网站

然后直接在CMakeLists.txt引入就好了

include_directories(include) # 设置include路径

set(CXXFLAGS -std=c++11 -lgtest -lpthread)
add_compile_options(${CXXFLAGS})

target_link_libraries(test gtest pthread) # 链接gtest静态库
框架使用

框架的使用主要分为几个模块:AssertionsGoogle TestingGoogle MockingMatchersActions

Assertions

这一部分主要是一些断言和比较宏定义,内容较多,以下是一部分,想看全部的可以去看源码

这一部分理解比较简单,不做概述

#define EXPECT_THROW(statement, expected_exception) \
  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
#define EXPECT_NO_THROW(statement) \
  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
#define EXPECT_ANY_THROW(statement) \
  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
#define ASSERT_THROW(statement, expected_exception) \
  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
#define ASSERT_NO_THROW(statement) \
  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
#define ASSERT_ANY_THROW(statement) \
  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
Google Testing

这部分是框架的主要部分,也是开发人员接触最多的地方

首先来介绍三个常用的宏:TESTTEST_FTEST_P

TEST:一般测试,在其内部设置断言

TestSuiteName定义了测试套件名称,TestName定义了自定义测试名

  • 注意这两个的命名不要包括下划线_
TEST(TestSuiteName, TestName) 
{
  // statements
}

TEST_F:多样测试,就是多种不同情况的测试中都会使用相同一份的测试数据的情况

TEST_P(TestFixtureName, TestName) 
{
  // statements
}

TEST_P:值参数化测试,自动化产生输入参数进行测试

TEST_P(TestFixtureName, TestName) 
{
  // statements
}

TEST_P为例写一个小demo

首先定义一个测试套件类,在其中定义要产生测试输入参数的类型

// 其中TestWithParam从Test类和WithParamInterface类派生来的,这两个类是必要的
class FooTest : public ::testing::TestWithParam<int> {
	
};

产生自动化输入参数结构

INSTANTIATE_TEST_CASE_P(InstantiationName, // 此处自定义名称
                        FooTest, // 测试套件类
                        ::testing::Values(1, 2, 3));

第三个参数是可更改的,比如RangeBoolValuesInValues

INSTANTIATE_TEST_SUITE_P(
    MyInstantiation, MyTestSuite,
    testing::Values(...),
    [](const testing::TestParamInfo<MyTestSuite::ParamType>& info) {
      // Can use info.param here to generate the test suffix
      std::string name = ...
      return name;
    });

要注意的是Combine,它会把其中的变量组成一个联合排列输入参数(确保支持tr/tuple<T>特性)


class Bis {
    bool Even(int dd) {}
    bool Suc(bool dc) {}
};

class CombineTest : 
    public ::testing::TestWithParam< ::testing::tuple<bool, int> > {
protected:
	bool CheckData() {
		bool dc = ::testing::get<0>(GetParam());
        int dd = ::testing::get<1>(GetParam());
		return bis.Suc(dc) && bis.Even(dd);
	}
private:
	Bis bis;
}

TEST_P(MyCombineTest, CombineTestUnit)
{
	EXPECT_TRUE(CheckData());
}

INSTANTIATE_TEST_CASE_P(TestBisValuesCombine, CombineTest, ::testing::Combine(::testing::Bool(), ::testing::Values(3, 4)));

最后在TEST_P中写测试代码

bool IsPrime(int n)
{
	return n > 0;
}

TEST_P(FooTest, DoesBlah) 
{
  // Inside a test, access the test parameter with the GetParam() method
  // of the TestWithParam<T> class:
  //在测试中,使用TestWithParam <T>类的GetParam()方法访问测试参数:
  int n =  GetParam();
  EXPECT_TRUE(IsPrime(n));
  // ...
}

其他部分API用的时候直接看官网就好了,主体是这三个API,其他基本上都是辅助宏

Google Mocking

有点类似于伪装接口,一般情况下用不着,不做概述

Matchers

有点类似于前面的断言,直接看部分源码(在gmok-matchers.h文件中)

inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrEq(
    const std::wstring& str) {
  return MakePolymorphicMatcher(
      internal::StrEqualityMatcher<std::wstring>(str, true, true));
}

// Matches a string not equal to str.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrNe(
    const std::wstring& str) {
  return MakePolymorphicMatcher(
      internal::StrEqualityMatcher<std::wstring>(str, false, true));
}

// Matches a string equal to str, ignoring case.
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring>> StrCaseEq(
    const std::wstring& str) {
  return MakePolymorphicMatcher(
      internal::StrEqualityMatcher<std::wstring>(str, true, false));
}
Actions

这玩意也是一个和断言差不多的东西,看部分源码

template <size_t k, typename Ptr>
struct SaveArgAction {
  Ptr pointer;

  template <typename... Args>
  void operator()(const Args&... args) const {
    *pointer = std::get<k>(std::tie(args...));
  }
};

template <size_t k, typename Ptr>
struct SaveArgPointeeAction {
  Ptr pointer;

  template <typename... Args>
  void operator()(const Args&... args) const {
    *pointer = *std::get<k>(std::tie(args...));
  }
};
运行结果

下面来看看一个普通测试套件的运行结果

#include <gtest/gtest.h>
#include <stdint.h>
#include <stdio.h>

int Add(uint32_t a, uint32_t b)
{
    return a + b;
}

TEST(LLT, MAIN)
{
    EXPECT_EQ(Add(1U, 1U), 1U);
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
ubuntu@VM-8-16-ubuntu:~/finale/llt/build$ ./test 
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from LLT
[ RUN      ] LLT.MAIN
/home/ubuntu/finale/llt/src/test_main.cc:17: Failure
Expected equality of these values:
  add(1U, 1U)
    Which is: 2
  1U
    Which is: 1
[  FAILED  ] LLT.MAIN (0 ms)
[----------] 1 test from LLT (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] LLT.MAIN

 1 FAILED TEST

这个框架自定义的界面还是很好看的!


http://www.kler.cn/a/274303.html

相关文章:

  • 【Windows版】opencv 和opencv_contrib配置
  • 基于 uniapp 开发 android 播放 webrtc 流
  • 如何使用 WebAssembly 扩展后端应用
  • Android Java Ubuntu系统如何编译出 libopencv_java4.so
  • 【Mongo工具】Mongo迁移工具之Mongo-shake
  • 源码编译llama.cpp for android
  • 虚拟机VMware上 centos7 的网络配置
  • 单调栈,LeetCode 1793. 好子数组的最大分数
  • 2、鸿蒙学习-申请调试证书和调试Profile文件
  • 0基础学习VR全景平台篇第145篇:图层控件功能
  • 综合练习(python)
  • GAMES101 学习3
  • 【计算机考研】408全年复习保姆级规划+资料
  • .Net Core 中间件验签
  • 华为组网:核心交换机旁挂防火墙,基于ACL重定向配置实验
  • Maven项目如何导入依赖包
  • Nginx安装教程
  • Springboot+Redis:实现缓存 减少对数据库的压力
  • fastjson反序列化攻略
  • 解决重装系统之后,开始菜单找不到Anaconda3相关图标
  • 快速从0-1完成聊天室开发——环信ChatroomUIKit功能详解
  • Java-SpringAop 编程式事物实现
  • 如何在三个简单步骤中为对象检测标注图像
  • C语言---指针的两个运算符:点和箭头
  • Java 多线程(抢CPU)
  • 面试算法-51-翻转二叉树