C++ (boost) 单元测试

C++ (boost) 单元测试

C++ boost 单元测试

[TOC]


基本概念

Boost test库提供了一个用于单元测试的基于命令行界面的测试套件UTF:Unit Test Framework,具有单元测试、检测内存泄露、监控程序运行的功能。

测试模块

  1. 测试安装
  2. 测试主体:测试主体是测试的模块的实际运行部分,由测试用例测试套件组成的测试树形成
  3. 测试清理
  4. 测试运行器

测试用例

测试用例是一个包含多个测试断言的函数;是可以被独立执行测试的最小单元。

测试套件

测试套件是测试用例的容器,可以嵌套,包含一个或多个测试用例,将多个测试用例分组管理,共享安装、清理代码。

测试夹具(test fixture)

测试安装和测试清理好比c++中的构造函数和析构函数,“测试夹具”实现了自动的测试安装和测试清理。

超轻量及测试lightweight_test

在头文件<boost/detail/lightweight_test.hpp>中定义,他提供三个最简单的测试断言

BOOST_TEST      //相当于BOOST_CHECK,断言表达式成立
BOOST_ERROR     //直接断言失败,输出一条错误信息
BOOST_TEST_EQ   //相当于BOOST_CHECK_EQUAL,断言两个表达式相等

Boost最小化测试套件 minimal test

boost提供的最简单的测试套件,有基本的测试断言,适合简单测试

该套件在头文件中

#include <boost/test/minimal.hpp>

定义,使用时只包含这个头文件就可以了,不需要链接其他的库,非常方便。在这个头文件中已经定义了一个mian()函数,我们不需要在写main()函数了,只需要实现一个test_main(int argc, char *argv[])就可以了。这个头文件中定义了四个断言宏,可以供我们使用。

BOOST_CHECK(predicate)      //断言表达式通过,如不通过不影响程序继续执行
BOOST_REQUIRE(predicate)    //断言表达式必须通过,如不通过程序终止
BOOST_ERROR(message)        // 给出一个错误信息,程序继续执行
BOOST_FAIL(message)         // 给出一个错误信息,程序终止执行

下面是一个小栗子:

#include "boost/test/minimal.hpp"
#include "boost/format.hpp"
#include "iostream"

int test_main(int argc, char *argv[])           // 测试主函数,不需要在定义main()
{
    using namespace boost;
    format fmt("%d-%d");

    BOOST_CHECK(fmt.size() == 0);               // 验证fmt对象初始化,不通过继续执行
    
    fmt % 12 % 34;
    
    BOOST_REQUIRE(fmt.str() == "12-34");        // 验证结果,不通过则不予执行
    
    BOOST_ERROR("演示一条错误信息");                // 打印一条错误信息,继续执行

    fmt.clear();
    fmt % 12;
    try {
        std::cout << fmt;
    }
    catch (...) {
        BOOST_FAIL("致命错误,测试终止");            // 给出一个错误信息,终止执行
    }
    
    return 0;
}

程序输出:

boost_test.cpp(9): test fmt.size() == 0 failed in function: 'int test_main(int, char **)'
boost_test.cpp(12): 演示一条错误信息 in function: 'int test_main(int, char **)'
boost_test.cpp(20): 致命错误,测试终止 in function: 'int test_main(int, char **)'

总结,minimal test方便简单,但功能有限,适用于单元测试的演示,或者较小的程序段。

UTF测试断言

UTF中的测试断言:BOOST_LEVEL_ITEM

LEVEL WARN 警告级,不增加错误数量,不影响程序运行
CHECK 检查级别,增加错误数量,不影响程序运行
REQUIRE 最高级别,增加错误数量,程序终止运行
ITEM EQUAL/CLOSE 测试相等性
GE/GT/LT/LE/NE 测试不等性
(NO_)THROW 是否抛出异常
MESSAGE 测试信息
... ...

组合出来就是如

BOOST_CHECK_EQUAL(l, r)
BOOST_REQUIRE_GE(l, r)

测试实例

举个栗子:

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/smart_ptr.hpp>
using namespace boost;

// 开始测试套件s_smart_ptr
BOOST_AUTO_TEST_SUITE(s_smart_ptr)

// 测试用例1:t_scoped_ptr
BOOST_AUTO_TEST_CASE(t_scoped_ptr)
{
    scoped_ptr<int> p(new int(874));
    BOOST_CHECK(p);                     // 测试指针p的可用性
    BOOST_CHECK_EQUAL(*p, 875);         // 测试p解引用的值
 
    p.reset();
    BOOST_CHECK(p == 0);                // 测试p为空
}

// 测试用例2:t_shared_ptr
BOOST_AUTO_TEST_CASE(t_shared_ptr)
{
    shared_ptr<int> p(new int(100));
 
    BOOST_CHECK(p);
    BOOST_CHECK_EQUAL(*p, 100);
    BOOST_CHECK_EQUAL(p.use_count(), 1);
    shared_ptr<int> p2 = p;
    BOOST_CHECK_EQUAL(p, p2);
    BOOST_CHECK_EQUAL(p2.use_count(), 2);
 
    *p2 = 255;
    BOOST_CHECK_EQUAL(*p, 255);
    BOOST_CHECK_GT(*p, 200);
}

// 结束测试套件
BOOST_AUTO_TEST_SUITE_END()

关于#define BOOST_TEST_DYN_LINK,如果不加的话会出现下面的错误:

Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

编译时同时需要链接-lboost_unit_test_framework

测试夹具

前面说测试夹具就好比c++的构造函数和析构函数,也可以理解为在执行测试之前设置一个环境,在测试完成时清除它。

看两个栗子吧:

#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
#include <iostream>

struct F {
    F():i(0) { std::cout << "setup" << std::endl; }
    ~F() { std::cout << "teardown" << std::endl; }

    int i;
};

BOOST_AUTO_TEST_SUITE( test )

BOOST_FIXTURE_TEST_CASE( test_case1, F ) {
    BOOST_CHECK( i == 1 );
    ++i;
}

BOOST_AUTO_TEST_CASE( test_case2 ) {
    BOOST_REQUIRE( 2 > 1 );
}

BOOST_AUTO_TEST_CASE( test_case3 ) {
    int i = 1;
    BOOST_CHECK_EQUAL( i, 1 );
    ++i;
}

BOOST_AUTO_TEST_SUITE_END()

输出结果是:

Running 3 test cases...
setup
boost_test.cpp:22: error in "test_case1": check i == 1 failed
teardown

*** 1 failure detected in test suite "Master Test Suite"

另一个栗子:

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/assign.hpp>
#include <vector>
using namespace std;
using namespace boost;

// 全局测试夹具类
struct global_fixture {
    global_fixture() {cout << "global setup" << endl;}
    ~global_fixture() {cout << "global teardown" << endl;}
};

// 定义全局夹具
BOOST_GLOBAL_FIXTURE(global_fixture);

// 测试套件夹具类
struct assign_fixture {
    assign_fixture() {cout << "suit setup" << endl;}
    ~assign_fixture() {cout << "suit teardown" << endl;}

    std::vector<int> v;
};

// 定义测试套件级别的夹具
BOOST_FIXTURE_TEST_SUITE(s_assign, assign_fixture)

BOOST_AUTO_TEST_CASE(t_assign1) {
    using namespace boost::assign;
    v += 1, 2, 3, 4;
    BOOST_CHECK_EQUAL(v.size(), 4);
    BOOST_CHECK_EQUAL(v[2], 3);
}

BOOST_AUTO_TEST_CASE(t_assign2) {
    using namespace boost::assign;

    push_back(v)(11)(22)(33);
    BOOST_CHECK_EQUAL(v.empty(), false);
    BOOST_CHECK_LT(v[0], v[1]);
}

BOOST_AUTO_TEST_SUITE_END()

后一个栗子的输出是

global setup
Running 2 test cases...
suit setup
suit teardown
suit setup
suit teardown
global teardown
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • Android单元测试介绍 处于高速迭代开发中的Android项目往往需要除黑盒测试外更加可靠的质量保障,这正是单...
    东经315度阅读 3,069评论 6 37
  • 前言 本篇文章是我在学习前端自动化单元测试时的一些思路整理,之前也从未接触过单元测试相关工具,如有错漏,请读者斧正...
    Awey阅读 12,599评论 8 38
  • 原文链接:http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutor...
    butterflyq阅读 1,967评论 1 3
  • 简介 测试 在软件开发中是一个很重要的方面,良好的测试可以在很大程度决定一个应用的命运。软件测试中,主要有3大种类...
    Whyn阅读 5,704评论 0 2
  • @(python) 单元测试是对程序中的单个子程序、函数、过程进行的测试,面向白盒测试。单元测试测试覆盖常用子程序...
    orientlu阅读 1,953评论 1 0