美文网首页
C++ (boost) 单元测试

C++ (boost) 单元测试

作者: lcode | 来源:发表于2015-08-20 15:43 被阅读3749次

    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
    

    相关文章

      网友评论

          本文标题:C++ (boost) 单元测试

          本文链接:https://www.haomeiwen.com/subject/injgqttx.html