当前位置:网站首页>Gtest之TEST宏的用法

Gtest之TEST宏的用法

2022-07-06 05:48:00 panamera12

1. TestCase的介绍
Gtest提供了若干个case方法进行测试不同的用例。主要常见的有TEST/TEST_F及TEST_P宏的使用。在每个TestCase中可以通过断言提供的方法进行控制检查程序的预期走向是否是期望的结果,从而以此来判定程序的正确性。在同一份TestCase中不能同时出现TEST和TEST_F两者进行混用;其次TEST_F比TEST强的地方是会通过继承::testing::Test生成一个新类,而且这是必须的。在新类中可以通过void SetUp();和void TearDown();进行创建和清除相关的资源数据;

2. TEST宏
TEST宏的作用是创建一个简单测试,它定义了一个测试函数,在这个函数里可以使用任何C++代码并使用提供的断言来进行检查。

TEST语法定义:
TEST(test_case_name, test_name)

  • test_case_name第一个参数是测试用例名,通常是取测试函数名或者测试类名
  • test_name 第二个参数是测试名这个随便取,但最好取有意义的名称
  • 当测试完成后显示的测试结果将以"测试用例名.测试名"的形式给出
// SharedUnique.cpp
#include <iostream>
#include <memory>
#include <gtest/gtest.h>

// A custom make_unique templete class
#include <Memory.h>

using namespace sampleCXX::common;

class Base {
public:
	Base(std::string name):m_name{name} {
		std::cout << "name: " << m_name << std::endl;
	}

	std::string getName() {
		return m_name;
	}
	~Base() {
		
		std::cout << "destory base" << std::endl;
	}
private:
	std::string m_name;
};

void getNameFunc(std::shared_ptr<Base> base) {
	std::cout << __func__ << " : usercount: " << base.use_count() << std::endl;
	std::cout << __func__ << " : name: " << base->getName() << std::endl;
	// EXPECT_EQ(2, base.use_count());
}

TEST(Base, createInstance) {
	std::unique_ptr<Base> instance = make_unique<Base>("SvenBaseUnique");
	// 测试创建的instance实例是否不为nullptr
	EXPECT_NE(instance, nullptr);
	instance.reset();
	// 测试instance实例是否为nullptr
	EXPECT_EQ(instance, nullptr);
}

TEST(Base, getName) {
	std::unique_ptr<Base> instance = make_unique<Base>("BaseUnique");
	EXPECT_NE(instance, nullptr);
	auto name = instance->getName();
	// 测试获取的name值是否和被给的值相等
	EXPECT_STREQ(name.c_str(), "BaseUnique");
	instance.reset();
	EXPECT_EQ(instance, nullptr);
}

TEST(Base, shared_ptr) {
	std::shared_ptr<Base> instance = std::make_shared<Base>("BaseShared");
	EXPECT_NE(instance, nullptr);
	std::cout << "shared_ptr.use_count: " << instance.use_count() << std::endl;
	// 测试instance引用次数是否为1
	EXPECT_EQ(1, instance.use_count());
	getNameFunc(instance);
	EXPECT_EQ(1, instance.use_count());
}

TEST(Base, unique_ptr) {
	std::unique_ptr<Base> instance = make_unique<Base>("BaseUnique");
	EXPECT_NE(instance, nullptr);
	getNameFunc(std::move(instance));
	EXPECT_EQ(instance, nullptr);
}

在这里插入图片描述

 3. TEST_F宏
TEST_F主要是进行多样测试,就是多种不同情况的测试TestCase中都会使用相同一份的测试数据的时候将会才用它。
即用相同的数据测试不同的行为,如果采用TEST宏进行测试那么将会为不同的测试case创建一份数据。TEST_F宏将会共用一份避免重复拷贝共具灵活性。

语法定义为:
TEST_F(test_case_name, test_name);
test_case_name第一个参数是测试用例名,必须取类名。这个和TEST宏不同
test_name 第二个参数是测试名这个随便取,但最好取有意义的名称
使用TEST_F时必须继承::testing::Test类。并且该类提供了两个接口void SetUp(); void TearDown();
void SetUp()函数,为测试准备对象.
void TearDown()函数 为测试后销毁对象资源。
如下程序测试一个Base类的两个方法,它们都共用相同的数据(Base类对象):
程序通过BaseTest类创建一个共用的数据资源,这个在测试时将无需为没有测试用例单独创建Base对象。
 

#include <iostream>
#include <memory>
#include <gtest/gtest.h>

#include <Memory.h>

using namespace sampleCXX::common;

class Base {
public:
	Base(std::string name):m_name{name} {
		std::cout << "Create constructor name: " << m_name << std::endl;
	}

	std::string getName() {
		return m_name;
	}

	void setName(const std::string &name) {
		m_name = std::string(name);
	}

	~Base() {
		
		std::cout << "Destory base" << std::endl;
	}
private:
	std::string m_name;
};


class BaseTest : public ::testing::Test {
protected:
	// 为测试准备数据对象
	void SetUp() override {
		m_base = std::make_shared<Base>("SvenBaseTest");
	}
	// 清除资源
	void TearDown() override {
		m_base.reset();
	}

	std::shared_ptr<Base> m_base;
};

TEST_F(BaseTest, testCreateInstance) {
	std::unique_ptr<Base> instance = make_unique<Base>("SvenBaseUnique");
	EXPECT_NE(instance, nullptr);
	instance.reset();
	EXPECT_EQ(instance, nullptr);
}

TEST_F(BaseTest, testGetName) {
	auto name = m_base->getName();
	EXPECT_STREQ(name.c_str(), "SvenBaseTest");
}

TEST_F(BaseTest, testSetName) {
	m_base->setName("NewSvenBase");
	auto name = m_base->getName();
	EXPECT_STREQ(name.c_str(), "NewSvenBase");
}

在这里插入图片描述

5. EXPECT_*和ASSERT_*的宏介绍
5.1.gtest之断言
要测试一个类或函数,我们需要对其行为做出断言。当一个断言失败时,Google Test会在屏幕上输出该代码所在的源文件及其所在的位置行号,以及错误信息。也可以在编写断言时,提供一个自定义的错误信息,这个信息在失败时会被附加在Google Test的错误信息之后。
断言常常成对出现,它们都测试同一个类或者函数,但对当前功能有着不同的效果。ASSERT_*版本的断言失败时会产生致命失败,并结束当前函数。EXPECT_*版本的断言产生非致命失败,而不会中止当前函数。通常更推荐使用EXPECT_*断言,因为它们运行一个测试中可以有不止一个的错误被报告出来。但如果在编写断言如果失败,就没有必要继续往下执行的测试时,你应该使用ASSERT_*断言。 因为失败的ASSERT_*断言会立刻从当前的函数返回,可能会跳过其后的一些的清洁代码,这样也许会导致空间泄漏。

gtest中断言的宏可以分为两类:一类是ASSERT宏,另一类就是EXPECT宏了。
1、ASSERT_*系列:如果当前点检测失败则退出当前函数
2、EXPECT_*系列:如果当前点检测失败则继续往下执行

5.2. gtest断言分类

 

7. 调用小记
TEST()并TEST_F()使用googletest隐式注册他们的测试。因此,与许多其他C ++测试框架不同,您不必重新列出所有已定义的测试以便运行它们。

在定义测试之后,您可以使用RUN_ALL_TESTS()它来运行它们,0如果所有测试都成功,1则返回它们。请注意,在链接单元中 RUN_ALL_TESTS()运行所有测试 - 它们可以来自不同的测试用例,甚至是不同的源文件。

调用时,RUN_ALL_TESTS()宏:

保存所有googletest标志的状态
为第一次测试创建测试夹具对象。

通过初始化它SetUp()。

在夹具对象上运行测试。

通过清理夹具TearDown()。

删除夹具。

恢复所有googletest标志的状态

重复上述步骤进行下一次测试,直到所有测试都运行完毕。

如果发生致命故障,将跳过后续步骤。

重要提示:您不能忽略返回值RUN_ALL_TESTS(),否则您将收到编译器错误。此设计的基本原理是自动化测试服务根据其退出代码确定测试是否已通过,而不是根据其stdout / stderr输出; 因此你的main()函数必须返回值RUN_ALL_TESTS()。
此外,你应该RUN_ALL_TESTS()只打一次电话。多次调用它会与某些高级googletest功能(例如线程安全死亡测试)冲突,因此不受支持。

其实Gtest相比Gmock的使用是简单的多了,主要合理的使用以上断言就能为自己的程序写出一个自动化的测试流程;
 

 

原网站

版权声明
本文为[panamera12]所创,转载请带上原文链接,感谢
https://blog.csdn.net/wteruiycbqqvwt/article/details/125625975