C++單元測試:boost.test

C++單元測試:boost.test

1) 準備

1.1) 編譯boost test

cd boost_1_55_0

# On Windows
bootstrap.bat
b2 --toolset=msvc-10.0 --build-type=minimal --with-test runtime-link=static stage
# 1) --toolset=msvc-10.0: 指定編譯器,這兒是VS2010。其餘版本可見連接1。
# 2) --build-type=minimal: 默認,按其描述至關於設定了下述屬性:
#   link=static runtime-link=shared threading=multi variant=debug,release
# 3) --with-test: 指定編譯test。一旦用了'--with',就只編譯指定庫了。
# 4) runtime-link=static: 添加靜態連接運行時庫。link與runtime-link區分,可見連接2。
# 5) stage: 只編譯和安裝庫文件,也就是不會包含頭文件。

# On Linux
# 是否已預安裝
ll /usr/lib/libboost*
# yum list installed boost*
./bootstrap.sh
./b2 --toolset=gcc --build-type=minimal --with-test stage
# 1) --prefix: 安裝路徑,默認/usr/local。
# 2) --build-type=minimal: 默認,Linux下至關於設定了下述屬性:
#   link=static,shared threading=multi variant=release

# 幫助
./b2 --help
./b2 --show-libraries

參考html

  1. b2 Invocation
  2. Getting Started on Windows
  3. Getting Started on Unix Variants

中文的話,可參考這兩篇:ios

  1. Boost下載安裝編譯配置使用指南
  2. VS2010 編譯安裝boost庫

連接bootstrap

  1. C++ Compilers: Microsoft Visual C++
  2. link和runtime-link,搭配shared和static

1.2) 引入boost test

# On Windows,靜態連接方式
"IncludePath" += boost_1_55_0
"LibraryPath" += boost_1_55_0\stage\lib
指定選項:/EHa,/MT[d]

# On Linux,動態連接方式
定義宏:BOOST_TEST_DYN_LINK
連接時:-lboost_unit_test_framework

2) 使用

官方文檔Boost Test Library講的很詳細。主要是幾下幾方面:windows

2.1) Hello the testing world

test_hello.cc框架

#define BOOST_TEST_MODULE MyTest
#include <boost/test/unit_test.hpp>

int add( int i, int j ) { return i+j; }

BOOST_AUTO_TEST_CASE( my_test )
{
    // seven ways to detect and report the same error:
    BOOST_CHECK( add( 2,2 ) == 4 );        // #1 continues on error

    BOOST_REQUIRE( add( 2,2 ) == 4 );      // #2 throws on error

    if( add( 2,2 ) != 4 )
      BOOST_ERROR( "Ouch..." );            // #3 continues on error

    if( add( 2,2 ) != 4 )
      BOOST_FAIL( "Ouch..." );             // #4 throws on error

    if( add( 2,2 ) != 4 ) throw "Ouch..."; // #5 throws on error

    BOOST_CHECK_MESSAGE( add( 2,2 ) == 4,  // #6 continues on error
                         "add(..) result: " << add( 2,2 ) );

    BOOST_CHECK_EQUAL( add( 2,2 ), 4 );   // #7 continues on error
}

官方的例子,很簡單:ide

  1. "BOOST_TEST_MODULE",定義測試模塊。以後再include "unit_test.hpp"。
  2. "BOOST_AUTO_TEST_CASE",自動註冊測試用例。
  3. 測試工具分爲"WARN","CHECK"和"REQUIRE"三個等級。"CHECK"與"REQUIRE"差異爲:前者即便失敗,也仍然繼續;後者則認爲是必須的,爲嚴重錯誤,直接退出當前測試。

測試工具參考,見testing tools reference工具

2.2) 自動註冊測試套件(Test suites

用如下宏把"TEST_CASE"包起來即成:單元測試

BOOST_AUTO_TEST_SUITE(test_suite_name)
BOOST_AUTO_TEST_SUITE_END()

test_suite.cc測試

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

/* test_suite1 start */
BOOST_AUTO_TEST_SUITE( test_suite1 )
// test_case1 in test_suite1
BOOST_AUTO_TEST_CASE( test_case1 )
{
    BOOST_WARN( sizeof(int) < 4 );
}
// test_case2 in test_suite1
BOOST_AUTO_TEST_CASE( test_case2 )
{
    BOOST_REQUIRE_EQUAL( 1, 2 );  // note: REQUIRE
    BOOST_FAIL( "Should never reach this line" );
}
BOOST_AUTO_TEST_SUITE_END()
/* test_suite1 end */

/* test_suite2 start */
BOOST_AUTO_TEST_SUITE( test_suite2 )
// test_case3 in test_suite2
BOOST_AUTO_TEST_CASE( test_case3 )
{
    BOOST_CHECK( true );
}
BOOST_AUTO_TEST_SUITE_END()
/* test_suite2 end */

// test_case_on_file_scope
BOOST_AUTO_TEST_CASE( test_case_on_file_scope )
{
    BOOST_CHECK( true );
}

/* test_suite2 start */
BOOST_AUTO_TEST_SUITE( test_suite2 )
// test_case4 in test_suite2
BOOST_AUTO_TEST_CASE( test_case4 )
{
    BOOST_CHECK( false );
}
BOOST_AUTO_TEST_SUITE_END()
/* test_suite2 end */
  1. 上述定義了兩個"TEST_SUITE":test_case一、test_case1在test_suite1內;test_case三、test_case4在test_suite2內。
  2. 注意test_case_on_file_scope,其上下分別是test_suite2的test_case三、test_case4。也就是測試套件能夠分爲多個部分,以便放在不一樣文件。

2.3) 使用測試夾具(Test fixtures

重複的測試數據,均可以放到一個夾具裏。其模板以下:ui

struct <fixture-name>{
   <fixture-name>(); // setup function
   ~<fixture-name>(); // teardown function
};

而後,使用時:

  1. "BOOST_FIXTURE_TEST_CASE",用在測試用例上。
  2. "BOOST_FIXTURE_TEST_SUITE",用在測試套件上。這樣的話,測試套件每一個測試用例就不用寫了。
  3. "BOOST_GLOBAL_FIXTURE",用在全局上。

test_suite.cc

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

/* 3) Global fixture */
struct MyConfig {
    MyConfig() : g_i( 0 )
    {
        instance() = this;
        std::cout << "global setup\n";
    }
    ~MyConfig()
    {
        std::cout << "g_i: " << g_i << std::endl;
        std::cout << "global teardown\n";
    }
    static MyConfig *&instance();
    int g_i;
};
BOOST_GLOBAL_FIXTURE(MyConfig);

MyConfig *&MyConfig::instance()
{
    static MyConfig *s_inst = 0;
    return s_inst;
}

/* 1) Per test case fixture */
struct F {
    F() : i( 0 ) { std::cout << "setup fixture\n"; }
    ~F()         { std::cout << "teardown fixture\n"; }
    int i;
};
BOOST_FIXTURE_TEST_CASE( test_case1, F )
{
    BOOST_CHECK( i == 1 );  // failed: i == 0
    ++i;
}
BOOST_FIXTURE_TEST_CASE( test_case2, F )
{
    BOOST_CHECK_EQUAL( i, 0 );  // pass: i == 0
    ++(MyConfig::instance()->g_i);
}
BOOST_AUTO_TEST_CASE( test_case3 )
{
    BOOST_CHECK( true );
    std::cout << "g_i: " << MyConfig::instance()->g_i << std::endl;
}

/* 2) Test suite level fixture */
BOOST_FIXTURE_TEST_SUITE( test_suite1, F )
BOOST_AUTO_TEST_CASE( test_case1 )
{
    BOOST_CHECK( i == 1 );  // failed: i == 0
    ++i;
}
BOOST_AUTO_TEST_CASE( test_case2 )
{
    BOOST_CHECK_EQUAL( i, 0 );  // pass: i == 0
    ++(MyConfig::instance()->g_i);
}
BOOST_AUTO_TEST_SUITE_END()
  1. 輸出會有四組"setup fixture"與"teardown fixture",每一個用到的測試用例下各自一份。
  2. "global setup"與"global teardown"則分別於頭尾,只有一個實例。官方文檔沒看到如何訪問其成員,這裏用了單例方式來處理。

3) 總結

本文主要介紹了boost單元測試框架的使用。


附1:樣例工程btest_start

下載:btest_start.zip

目錄樹以下:

btest_start/
├─build/
│  ├─btest_start-gcc.cbp   # for gnu gcc
│  └─btest_start-msvc.cbp  # for msvc 2010
├─src/
├─third_party/
│  └─boost_1_55_0/
└─tools/

C::B工程,boost_1_55_0/目錄Windows上配置時用到了。

相關文章
相關標籤/搜索