boost的单元测试框架

boost提供了单元测试的框架,简单易用。在项目已经用了boost时,无需多余配置,使用非常方便。

1. 简单用法

单元测试框架里有三层,第一层是TEST_MODULE,第二层是TEST_SUITE,第三层是TEST_CASE。简单的例子如下:

// test.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE test_module_1

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(test_suit1)

BOOST_AUTO_TEST_CASE(test_case1)
{
    BOOST_CHECK(2 + 2 == 4);
}

BOOST_AUTO_TEST_CASE(test_case2)
{
    BOOST_CHECK(2 + 2 == 5);
}

BOOST_AUTO_TEST_SUITE_END();


BOOST_AUTO_TEST_SUITE(test_suite2)

BOOST_AUTO_TEST_CASE(test_case3) {
    BOOST_CHECK_EQUAL(1, 2);
}

BOOST_AUTO_TEST_SUITE_END();

编译时,需将boost的头文件和lib文件目录加入搜寻路径,并将boost_unit_test_framework加入链接库。GCC编译的配置选项大概长这个样子

g++ -o test test.cpp -Iboost_include_path -Lboost_lib_path -lboost_unit_test_framework

可以将多个test文件加入到单元测试,编译成同一个可执行文件:

// test2.cpp
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test_case4) {
    BOOST_CHECK_EQUAL(2, 2);
}

编译选项:

g++ -o test test.cpp test2.cpp -Iboost_include_path -Lboost_lib_path -lboost_unit_test_framework

但需注意几点:

  1. #define BOOST_TEST_DYN_LINK用来自动生成main函数(所以不用手写),因此至多一个cpp文件里包含该宏,否则会出现错误。
  2. 同一个目标可执行文件,只能用一个TEST_MODULE,只在一个cpp文件定义#define BOOST_TEST_MODULE即可。

2. 测试断言

测试断言即用来指定测试的行为,其基本格式为 BOOST_LEVEL_ITEM。

LEVEL有三类:

  1. WARN:在测试错误时,发出警告,不增加错误数量,不影响程序运行。实际用得不多。
  2. CHECK: 在测试错误时,增加错误数量,打印错误提示信息,但不影响程序运行。实际中用得最多。
  3. REQUIRE: 在测试错误时,增加错误数量,并终止测试。一般用于该错误将影响后续测试时。

ITEM有多个:

BOOST_CHECK(expr);              // error when expr == false
BOOST_CHECK_EQUAL(a, b);        // error when a != b
BOOST_CHECK_CLOSE(a, b, e);     // error when |a-b|/min(|a|,|b|) > e
BOOST_CHECK_CLOSE_FRACTION(a, b, e);    // error when |a-b|>e
BOOST_CHECK_GE/GT/LT/LE/NE(a,b) // error when a not >=/>/</<=/!= b (compare)
BOOST_CHECK_NO_THROW(a);        // error when a throw error
BOOST_CHECK_THROW(a, e)         // error when a not throw e,where e is an error type

3. 单元测试的初始化

boost的单元测试框架提供一个叫做FIXTURE的框架,可让在单元测试开始前进行初始化,在结束后自动析构。它可以应用在全局、SUITE和CASE级别。

#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
#include <iostream>
struct GlobalFixture {
    GlobalFixture():global_i(0) { std::cout << "global setup" << std::endl; }
    ~GlobalFixture() { std::cout << "global teardown" << std::endl; }

    int global_i;
};

struct SuiteFixture {
    SuiteFixture():suite_i(1) { std::cout << "suite setup" << std::endl; }
    ~SuiteFixture() { std::cout << "suite teardown" << std::endl; }

    int suite_i;
};

struct CaseFixture {
    CaseFixture():case_i(2) { std::cout << "case setup" << std::endl; }
    ~CaseFixture() { std::cout << "case teardown" << std::endl; }

    int case_i;
};

BOOST_GLOBAL_FIXTURE(GlobalFixture);

BOOST_FIXTURE_TEST_SUITE(test_suite10, SuiteFixture);

BOOST_AUTO_TEST_CASE(test_case10) {
    BOOST_CHECK_EQUAL(suite_i, 1);
    suite_i = 2;
}

BOOST_AUTO_TEST_CASE(test_case11) {
    BOOST_CHECK_EQUAL(suite_i, 1);
}

BOOST_AUTO_TEST_SUITE_END();


BOOST_AUTO_TEST_SUITE(test_suite11);

BOOST_FIXTURE_TEST_CASE(test_case12, CaseFixture) {
    BOOST_CHECK_EQUAL(case_i, 2);
    case_i = 3;
}

BOOST_FIXTURE_TEST_CASE(test_case13, CaseFixture) {
    BOOST_CHECK_EQUAL(case_i, 2);
    case_i = 3;
}
BOOST_AUTO_TEST_SUITE_END();

注意几点:

  1. Case内部可直接使用SUITE和CASE的Fixutre类内部的成员变量和函数。
  2. SUITE级别的Fixture是在每个CASE级别进出时初始化和析构,而不是在SUITE进出时。也即,一个定义了Fixture的 SUITE,如果该SUITE包含多个CASE,那么这个Fixture会被初始化和析构多次,而Fixture内部的变量也无法在不同case之间共用。
  3. 注意没有BOOST_FIXTURE_TEST_SUITE_END,全部用BOOST_AUTO_TEST_SUITE_END标志一个SUITE的结束。
Copyright © zhiqiang.org 2016 all right reserved,powered by Gitbook该文件修订时间: 2016-08-03 01:06:06

results matching ""

    No results matching ""