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

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

编译和安装

下载地址: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

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

相关推荐

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

    2024-03-24 02:54:03       22 阅读
  2. gtest 单元测试

    2024-03-24 02:54:03       30 阅读
  3. 软件测试——单元测试

    2024-03-24 02:54:03       35 阅读
  4. 单元测试框架jUnit

    2024-03-24 02:54:03       40 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-24 02:54:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-24 02:54:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-24 02:54:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-24 02:54:03       18 阅读

热门阅读

  1. 【Rust】Shared-State Concurrency

    2024-03-24 02:54:03       21 阅读
  2. 计算机二级考试注意事项(Python程序设计篇)

    2024-03-24 02:54:03       18 阅读
  3. perl:获取同花顺数据--业绩预告

    2024-03-24 02:54:03       20 阅读
  4. Hive在虚拟机中的部署

    2024-03-24 02:54:03       18 阅读
  5. C++语句,空语句,复合语句

    2024-03-24 02:54:03       19 阅读
  6. SQL题:

    SQL题:

    2024-03-24 02:54:03      16 阅读
  7. Python 类的学习

    2024-03-24 02:54:03       16 阅读
  8. 洛谷 P1011 [NOIP1998 提高组] 车站

    2024-03-24 02:54:03       17 阅读