CppUnit 導入ガイド
ダウンロードとインストール
CppUnitは http://sourceforoge/projects/cppunit/ からダウンロードできます。2002.11時点での最新版は1.8.0(βは1.9.10)です。
zipもしくはtar+gzipで圧縮されているので、適当なディレクトリに展開してください。
以下の説明はWindows/Visual C++ v6.0 環境で、CppUnitのルート・ディレクトリを<CPPUNIT>と表記します。
ライブラリのビルド
CppUnitはツール/ユーティリティの類ではありません。テスト対象およびテストコードと一緒にリンクして実行モジュールを生成する’ライブラリ’です。
CppUnitは様々なOS/処理系に対応しており、その使用に先だってライブラリをビルドしなければなりません。
Visual Studio IDE から プロジェクト:<CPPUNIT>\src\CppUnitLibraries.dsw をオープンし、ビルド/バッチビルド-ダイアログからcppunitおよびcppunit_dllをチェックしてビルドします。
これによって、<CPPUNIT>\libに必要なライブラリ(とDLL)が生成されます。DLLはパスの通ったディレクトリにコピーしておくとよいでしょう。DLL版CppUnitはテストの実行モジュール・サイズを小さく抑えることができます。

cppunit/cppunit_dll以外のライブラリはMFC環境下でテスト結果をグラフィカルに表示するときに利用します。詳しくはCppUnitディストリビューションに同梱されているドキュメントをご覧ください。
テストコードの雛型
テストコードの雛型を示します。この雛型は様々なテストに応じて書き換えて利用してください。
XXXTest.cpp
/*
* test skeleton XXXTest.cpp [1]
*/
// 必要なヘッダの #include [2]
// ex. #include "XXX.h"
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestAssert.h>
// XXX をテストする [3]
class XXXTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(XXXTest); // [4]
CPPUNIT_TEST(test_one); // [5]
CPPUNIT_TEST(test_two); // [5]
CPPUNIT_TEST(test_three); // [5]
CPPUNIT_TEST(test_four); // [5]
CPPUNIT_TEST(test_five); // [5]
CPPUNIT_TEST(test_six); // [5]
CPPUNIT_TEST_SUITE_END(); // [4]
private:
// 必要な メンバ変数/関数 [6]
public:
/*
* コンストラクタ/デストラクタ [7]
*/
XXXTest() {
}
~XXXTest() {
}
/*
* 初期化/後始末 [8]
*/
virtual void setUp() {
}
virtual void tearDown() {
}
/*
* テスト・ケース [9]
*/
void test_one() {
CPPUNIT_ASSERT( 0 == 1 );
}
void test_two() {
CPPUNIT_ASSERT_MESSAGE( "0 is not equal to 1", 0 == 1 );
}
void test_three() {
CPPUNIT_FAIL( "never reached here!" );
}
void test_four() {
CPPUNIT_ASSERT_EQUAL( 0, 1 );
}
void test_five() {
CPPUNIT_ASSERT_EQUAL_MESSAGE( "1 is not equal to 0", 0, 1 );
}
void test_six() {
CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.23, 1.24, 0.001 );
}
};
/*
* register test suite
*/
CPPUNIT_TEST_SUITE_REGISTRATION(XXXTest); // [10]
- [1] ファイル名
- 慣習的に、テスト対象であるモジュール名の末尾に’Test’を付加します。たとえば、’Counter’のテストコードは’CounterTest.cpp’のように。
- [2] インクルード
- 必要なインクルードをここに記述します。
- [3] テストクラス
-
テストクラスはテスト対象に対するテスト・ケースの集合体で、
ファイル名と同じクラス名とするのが望ましいでしょう。 - [4] テスト・スイート
-
CPPUNIT_TEST_SUITE(テストクラス名);とCPPUNIT_TEST_SUITE_END();の間にテスト・ケースを記述します。 - [5] テスト・ケース(メソッド)の登録
-
CPPUNIT_TEST(テスト・ケース名);によって、テスト・ケースを登録します。 - [6] メンバ変数/関数
- 各テスト・ケースの実行に必要なメンバ変数/関数を宣言します。
- [7] コンストラクタ/デストラクタ
- 必要に応じ、コンストラクタ/デストラクタを定義します。なお、テストクラスのインスタンスは各テスト・ケース毎に生成されます。
- [8] 初期化/後始末
-
setUp(初期化)とtearDown(後始末)は、それぞれ各テスト・ケース実行の直前/直後に呼び出されます。 - [9] テスト・ケース(メソッド)
- テスト・ケースは引数/戻り値を持たないメソッドで、テスト項目毎に用意します。
- [10] テスト・スイート登録
-
CPPUNIT_TEST_SUITE_REGISTRATION(テストクラス名);によって、テスト・スイートが登録されます。
アサート・マクロ
各テスト・ケースの中では、テスト対象が正常に機能しているかを検証するコードを記述します。
以下のアサート・マクロが用意されています。
各アサート・マクロはそれぞれ特定の条件を満たさないとき、テスト失敗(failre)とみなしてそれ以降の処理をせずにテスト・ケースから脱出し、次のテスト・ケースに移ります。
CPPUNIT_ASSERT( condition );- conditionが偽(false,0)であったとき、失敗します。
CPPUNIT_ASSERT_MESSAGE( message, condition );- conditionが偽であったとき、失敗します。このときmessageを出力します。
CPPUNIT_FAIL( message );- 必ず失敗します。messageを出力します。
CPPUNIT_ASSERT_EQUAL( expected, actual );- 得られた結果actualが期待する値expectedでなかったとき、すなわちexpected != actualのときに失敗します。
CPPUNIT_ASSERT_EQUAL_MESSAGE( message, expected, actual );- 得られた結果actualが期待する値expectedでなかったとき、すなわちexpected != actualのときに失敗します。このときmessageを出力します。
CPPUNIT_ASSERT_DOUBLES_EQUAL( expected, actual, delta );- 得られた結果actualと期待する値expectedとの差がdeltaより大きいとき、失敗します。
メイン・ルーチン
以上のようにして作られたいくつかのテスト・スイートを実行し、その結果を出力するメイン・ルーチンの雛形を示します。
出力フォーマットに応じ、3種の雛形を用意しました。それぞれの出力結果をコードと併せて示します。
テキスト形式
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
int main() {
CppUnit::TextUi::TestRunner runner;
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
CppUnit::Outputter* outputter =
new CppUnit::TextOutputter(&runner.result(),std::cout);
runner.setOutputter(outputter);
return runner.run() ? 0 : 1;
}
!!!FAILURES!!! Test Results: Run: 6 Failures: 6 Errors: 0 1) test: XXXTest::test_one (F) line: 49 XXXTest.cpp assertion failed - Expression: 0 == 1 2) test: XXXTest::test_two (F) line: 53 XXXTest.cpp assertion failed - 0 is not equal to 1 3) test: XXXTest::test_three (F) line: 57 XXXTest.cpp forced failure - never reached here! 4) test: XXXTest::test_four (F) line: 61 XXXTest.cpp equality assertion failed - Expected: 0 - Actual : 1 5) test: XXXTest::test_five (F) line: 65 XXXTest.cpp equality assertion failed - Expected: 0 - Actual : 1 - 1 is not equal to 0 6) test: XXXTest::test_six (F) line: 69 XXXTest.cpp equality assertion failed - Expected: 1.23 - Actual : 1.24
コンパイラ出力形式
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
int main() {
CppUnit::TextUi::TestRunner runner;
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
CppUnit::Outputter* outputter =
new CppUnit::CompilerOutputter(&runner.result(),std::cout);
runner.setOutputter(outputter);
return runner.run() ? 0 : 1;
}
XXXTest.cpp(44):Assertion Test name: XXXTest::test_one assertion failed - Expression: 0 == 1 XXXTest.cpp(48):Assertion Test name: XXXTest::test_two assertion failed - 0 is not equal to 1 XXXTest.cpp(52):Assertion Test name: XXXTest::test_three forced failure - never reached here! XXXTest.cpp(56):Assertion Test name: XXXTest::test_four equality assertion failed - Expected: 0 - Actual : 1 XXXTest.cpp(60):Assertion Test name: XXXTest::test_five equality assertion failed - Expected: 0 - Actual : 1 - 1 is not equal to 0 XXXTest.cpp(64):Assertion Test name: XXXTest::test_six equality assertion failed - Expected: 1.23 - Actual : 1.24 Failures !!! Run: 6 Failure total: 6 Failures: 6 Errors: 0
XML形式
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
int main() {
CppUnit::TextUi::TestRunner runner;
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
CppUnit::Outputter* outputter =
new CppUnit::XmlOutputter(&runner.result(),std::cout);
runner.setOutputter(outputter);
return runner.run() ? 0 : 1;
}
<?xml version="1.0" encoding='ISO-8859-1' standalone='yes' ?>
<TestRun>
<FailedTests>
<FailedTest id="1">
<Name>XXXTest::test_one</Name>
<FailureType>Assertion</FailureType>
<Location>
<File>XXXTest.cpp</File>
<Line>49</Line>
</Location>
<Message>assertion failed
- Expression: 0 == 1
</Message>
</FailedTest>
<FailedTest id="2">
<Name>XXXTest::test_two</Name>
<FailureType>Assertion</FailureType>
<Location>
<File>XXXTest.cpp</File>
<Line>53</Line>
</Location>
<Message>assertion failed
- 0 is not equal to 1
</Message>
</FailedTest>
<FailedTest id="3">
<Name>XXXTest::test_three</Name>
<FailureType>Assertion</FailureType>
<Location>
<File>XXXTest.cpp</File>
<Line>57</Line>
</Location>
<Message>forced failure
- never reached here!
</Message>
</FailedTest>
<FailedTest id="4">
<Name>XXXTest::test_four</Name>
<FailureType>Assertion</FailureType>
<Location>
<File>XXXTest.cpp</File>
<Line>61</Line>
</Location>
<Message>equality assertion failed
- Expected: 0
- Actual : 1
</Message>
</FailedTest>
<FailedTest id="5">
<Name>XXXTest::test_five</Name>
<FailureType>Assertion</FailureType>
<Location>
<File>XXXTest.cpp</File>
<Line>65</Line>
</Location>
<Message>equality assertion failed
- Expected: 0
- Actual : 1
- 1 is not equal to 0
</Message>
</FailedTest>
<FailedTest id="6">
<Name>XXXTest::test_six</Name>
<FailureType>Assertion</FailureType>
<Location>
<File>XXXTest.cpp</File>
<Line>69</Line>
</Location>
<Message>equality assertion failed
- Expected: 1.23
- Actual : 1.24
</Message>
</FailedTest>
</FailedTests>
<SuccessfulTests></SuccessfulTests>
<Statistics>
<Tests>6</Tests>
<FailuresTotal>6</FailuresTotal>
<Errors>0</Errors>
<Failures>6</Failures>
</Statistics>
</TestRun>