大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
sudo apt-get install libgtest-dev
闲来无事,想尝试一下gtest/gmock,根据下载的源码包里有README,并根据自己安装过程补充记录如下,以便以后查询
1.获取GTest/GMock源码
从Google网站上http://code.google.com/p/googlemock/downloads/list下载GMock源码(GMock源码中包含GTest源码,无需另外下载GTest源码)
放到本地目录,我下载的GMock源码版本是gmock-1.7.0,选择放在/home/USERNAME/Download下,解压,生成gmock-1.7.0
cd gmock-1.7.0
2.创建连接库
生成gtest-all.o : g++ -isystem gtest/include -I./gtest -isystem ./include -I. -pthread -c ./gtest/src/gtest-all.cc
生成gmock-all.o : g++ -isystem gtest/include -I./gtest -isystem ./include -I. -pthread -c ./src/gmock-all.cc
生成libgtest.a和libgmock.a : ar -rv libgmock.a gtest-all.o gmock-all.o
3.拷贝文件到/use/local目录
将gmock-1.7.0/gtest/include下面的gtest目录拷贝到/usr/local/include下
cp gmock-1.7.0/gtest/include/gtest/ /usr/local/include -r
将gmock-1.7.0/include下面的gmock目录拷贝到/usr/local/include下
cp gmock-1.7.0/include/gmock/ /usr/local/include -r
cp gmock-1.7.0/libgtest.a /usr/local/lib
cp gmock-1.7.0/libgmock.a /usr/local/lib
4.编译连接,测试
g++ -o executefile yourcode.cpp -lpthread -lgtest -lgmock
you need modify the Makefile using '-pthread' instead of '-lpthread'.
Or just run command like:
sudo g++ ../samples/sample1.cc ../samples/sample1_unittest.cc /usr/src/gtest/src/gtest_main.cc /usr/src/gtest/src/gtest-all.cc -I/usr/src/gtest/include -I/usr/src/gtest -g -Wall -Wextra -pthread -o sample1_unitte
sudo ./sample1_unittest --gtest_output=xml
--gtest_output=xml[:DIRECTORY_PATH/|:FILE_PATH]
Generate an XML report in the given directory or with the given file
name. FILE_PATH defaults to test_details.xml.
最后附上GTest/GMock学习文档:
GTest学习文章:
http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
GMock三篇学习文章:
1,http://code.google.com/p/googlemock/wiki/ForDummies
2,http://code.google.com/p/googlemock/wiki/CheatSheet
3,http://code.google.com/p/googlemock/wiki/CookBook
按上述顺序阅读,最后一篇文章比较长。
注:如果不用gmock,仅仅用到gtest,可以将上述gmock部分内容去掉。
对于 c++ 来说写单元测试和 mock 框架不是一件容易的事情。还好, Google 为我们搭建了一个出色的单元测试和 mock 框架。网上的例子很多都过多强调概念,本文用一个简单的例子让大家对于什么是 gtest 和 gmock 让大家有一个直观的了解,让大家很快上手,就像写 hello word 一样容易。
gtest&gmock 的 1.6 版本的使用 make 编译,新版的已经已经迁移到 github 上使用 cmake 编译,安装过程很多,这里不在重复,如果大家有需要再单独写。
1.下载安装 Google Test and Google Mock
2. 编译生成静态库gtest_main.a gmock_main.a (包含main库后不需要自己写main函数)
gmock用来对与为实现对象的接口模拟。
我们有一个Messgener.h接口,它的getMessage目前还没有实现,可以使用mock类提供的宏来模拟,这样就可以调试客户端程序,屏蔽Messgener.h的具体实现
#ifndef SRC_MESSENGER_H_
#define SRC_MESSENGER_H_
#include <string>
using namespace std;
class Messenger
{
public:
virtual ~Messenger() {}
virtual string getMessage() = 0;
};
#endif /* SRC_MESSENGER_H_ */
Messenger.h 的 mock 类
#ifndef SRC_MOCKMESSENGER_H_
#define SRC_MOCKMESSENGER_H_
#include "Messenger.h"
#include <string>
#include <gmock/gmock.h>
using namespace std;
class MockMessenger : public Messenger
{
public:
MOCK_METHOD0(getMessage, string());
};
#endif /* SRC_MOCKMESSENGER_H_ */
调用Messenger.h的客户端程序
HelloWorld.h
#ifndef SRC_HELLOWORLD_H_
#define SRC_HELLOWORLD_H_
#include <string>
#include "Messenger.h"
using namespace std;
class HelloWorld
{
public:
HelloWorld();
virtual ~HelloWorld();
string getMessage(Messenger* messenger) const;
};
#endif /* SRC_HELLOWORLD_H_ */
HelloWorld.cpp
#include "HelloWorld.h"
#include "Messenger.h"
HelloWorld::HelloWorld()
{
}
HelloWorld::~HelloWorld()
{
}
string HelloWorld::getMessage(Messenger* messenger) const
{
return messenger->getMessage();
}
有了要测试的代码和依赖的接口的mock模拟类,下面是gtest的单元测试写法:
#include "HelloWorld.h"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "MockMessenger.h"
#include <string>
#include <memory>
using namespace testing;
TEST(HelloWorldTest, getMessage)
{
MockMessenger messenger;
std::string msg = "Hello World";
EXPECT_CALL(messenger, getMessage()).WillRepeatedly(Return(ByRef(msg)));
HelloWorld helloWorld;
EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
}
本文基于笔者的实际开发经验,言简意赅地讲解了C/C++单元测试框架gtest的主要使用方法和注意事项,并设计了若干可编译的精简示例,给出了运行效果图。既可以用作gtest的入门教程,也适合作为工作中的快速参考。
AD:
Google C++ Testing Framework(简称gtest,http://code.google.com/p/googletest/)是Google公司发布的一个开源C/C++单元测试框架,已被应用于多个开源项目及Google内部项目中,知名的例子包括Chrome Web浏览器、LLVM编译器架构、Protocol Buffers数据交换格式及工具等。
优秀的C/C++单元测试框架并不算少,相比之下gtest仍具有明显优势。与CppUnit比,gtest需要使用的头文件和函数宏更集中,并支持测试用例的自动注册。与CxxUnit比,gtest不要求Python等外部工具的存在。与Boost.Test比,gtest更简洁容易上手,实用性也并不逊色。Wikipedia给出了各种编程语言的单元测试框架列表(http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks)。
一、基本用法
gtest当前的版本是1.5.0,如果使用Visual C++编译,要求编译器版本不低于7.1(Visual C++ 2003)。如下图所示,它的msvc文件夹包含Visual C++工程和项目文件,samples文件夹包含10个使用范例。
一般情况下,我们的单元测试代码只需要包含头文件gtest.h。gtest中常用的所有结构体、类、函数、常量等,都通过命名空间testing访问,不过gtest已经把最简单常用的单元测试功能包装成了一些带参数宏,因此在简单的测试中常常可以忽略命名空间的存在。
ASSERT宏 |
EXPECT宏 |
功能 |
ASSERT_TRUE |
EXPECT_TRUE |
判真 |
ASSERT_FALSE |
EXPECT_FALSE |
判假 |
ASSERT_EQ |
EXPECT_EQ |
相等 |
ASSERT_NE |
EXPECT_NE |
不等 |
ASSERT_GT |
EXPECT_GT |
大于 |
ASSERT_LT |
EXPECT_LT |
小于 |
ASSERT_GE |
EXPECT_GE |
大于或等于 |
ASSERT_LE |
EXPECT_LE |
小于或等于 |
ASSERT_FLOAT_EQ |
EXPECT_FLOAT_EQ |
单精度浮点值相等 |
ASSERT_DOUBLE_EQ |
EXPECT_DOUBLE_EQ |
双精度浮点值相等 |
ASSERT_NEAR |
EXPECT_NEAR |
浮点值接近(第3个参数为误差阈值) |
ASSERT_STREQ |
EXPECT_STREQ |
C字符串相等 |
ASSERT_STRNE |
EXPECT_STRNE |
C字符串不等 |
ASSERT_STRCASEEQ |
EXPECT_STRCASEEQ |
C字符串相等(忽略大小写) |
ASSERT_STRCASENE |
EXPECT_STRCASENE |
C字符串不等(忽略大小写) |
ASSERT_PRED1 |
EXPECT_PRED1 |
自定义谓词函数, (pred, arg1)(还有_PRED2, …, _PRED5) |
- // add.h
- #pragma once
- inline int Add(int i, int j) { return i+j; }
- // add_unittest.cpp
- #include "add.h"
- #include <gtest/gtest.h>
- TEST(Add, 负数) {
- EXPECT_EQ(Add(-1,-2), -3);
- EXPECT_GT(Add(-4,-5), -6); // 故意的
- }
- TEST(Add, 正数) {
- EXPECT_EQ(Add(1,2), 3);
- EXPECT_GT(Add(4,5), 6);
- }
- ASSERT_EQ(M[i], N[j]) << "i = " << i << ", j = " << j;
- // gtest-main.cc
- int main(int argc, char **argv) {
- std::cout << "Running main() from gtest_main.cc\n";
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
- }
从gtest的 testing::Test类派生一个类,用 public或 protected定义以下所有成员。
(可选)建立环境:使用默认构造函数,或定义一个虚成员函数 virtual void SetUp()。
(可选)销毁环境:使用析构函数,或定义一个虚成员函数 virtual void TearDown()。
用 TEST_F定义测试,写法与 TEST相同,但测试用例名必须为上面定义的类名。
调用默认构造函数创建一个新的带固件对象。
立即调用 SetUp函数。
运行 TEST_F体。
立即调用 TearDown函数。
调用析构函数销毁类对象。
- // add_unittest2.cpp
- #include "add.h"
- #include <stdio.h>
- #include <gtest/gtest.h>
- class AddTest: public testing::Test
- {
- public:
- virtual void SetUp() { puts("SetUp()"); }
- virtual void TearDown() { puts("TearDown()"); }
- };
- TEST_F(AddTest, 正数) {
- ASSERT_GT(Add(1,2), 3); // 故意的
- ASSERT_EQ(Add(4,5), 6); // 也是故意的
- }
(可选)在 testing::Test的派生类中,定义若干静态成员变量来维护套件的状态。
(可选)建立共享环境:定义一个静态成员函数 static void SetUpTestCase()。
(可选)销毁共享环境:定义一个静态成员函数 static void TearDownCase()。
- class Environment {
- public:
- virtual ~Environment() {}
- virtual void SetUp() {}
- virtual void TearDown() {}
- };
- Environment* AddGlobalTestEnvironment(Environment* env);
ASSERT宏 |
EXPECT宏 |
功能 |
ASSERT_NO_THROW |
EXPECT_NO_THROW |
不抛出异常,参数为 (statement) |
ASSERT_ANY_THROW |
EXPECT_ANY_THROW |
抛出异常,参数为 (statement) |
ASSERT_THROW |
EXPECT_THROW |
抛出特定类型的异常,参数为 (statement, type) |
- // divide.h
- #pragma once
- #include <stdexcept>
- int divide(int dividend, int divisor) {
- if(!divisor) {
- throw std::length_error("can't be divided by 0"); // 故意的
- }
- return dividend / divisor;
- }
- // divide-unittest.cpp
- #include <gtest/gtest.h>
- #include "./divide.h"
- TEST(Divide, ByZero) {
- EXPECT_NO_THROW(divide(-1, 2));
- EXPECT_ANY_THROW({
- int k = 0;
- divide(k, k);
- });
- EXPECT_THROW(divide(100000, 0), std::invalid_argument);
- }
- try {
- statement;
- }
- catch(type const&) {
- // throw
- }
- catch(...) {
- // any throw
- }
- // no throw
从gtest的 TestWithParam模板类派生一个类(记为 C),模板参数为需要输入的测试参数的类型。由于 TestWithParam本身是从 Test派生的,所以 C就成了一个测试固件类。
在 C中,可以实现诸如 SetUp、 TearDown等方法。特别地,测试参数由 TestWithParam实现的 GetParam()方法依次返回。
使用 TEST_P(而不是 TEST_F)定义测试。
使用 INSTANTIATE_TEST_CASE_P宏集中输入测试参数,它接受3个参数:任意的文本前缀,测试类名(这里即为 C),以及测试参数值序列。gtest框架依次使用这些参数值生成测试固件类实例,并执行用户定义的测试。
参数值序列生成函数 |
含义 |
Bool() |
生成序列 {false, true} |
Range(begin, end[, step]) |
生成序列 {begin, begin+step, begin+2*step, …} (不含 end), step默认为1 |
Values(v1, v2, …, vN) |
生成序列 {v1, v2, …, vN} |
ValuesIn(container), ValuesIn(iter1, iter2) |
枚举STL container,或枚举迭代器范围 [iter1, iter2) |
Combine(g1, g2, …, gN) |
生成 g1, g2, …, gN的笛卡尔积,其中g1, g2, …, gN均为参数值序列生成函数(要求C++0x的<tr1/tuple>) |
- // addupto.h
- #pragma once
- inline unsigned NaiveAddUpTo(unsigned n) {
- unsigned sum = 0;
- for(unsigned i = 1; i <= n; ++i) sum += i;
- return sum;
- }
- inline unsigned FastAddUpTo(unsigned n) {
- return n*(n+1)/2;
- }
- // addupto_test.cpp
- #include <gtest/gtest.h>
- #include "addupto.h"
- class AddUpToTest : public testing::TestWithParam<unsigned>
- {
- public:
- AddUpToTest() { n_ = GetParam(); }
- protected:
- unsigned n_;
- };
- TEST_P(AddUpToTest, Calibration) {
- EXPECT_EQ(NaiveAddUpTo(n_), FastAddUpTo(n_));
- }
- INSTANTIATE_TEST_CASE_P(
- NaiveAndFast, // prefix
- AddUpToTest, // test case name
- testing::Range(1u, 1000u) // parameters
- );
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/188112.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...