C++ 単体テストツール CppUnitの使い方
Sponsored Links
皆さんこんにちは
お元気ですか?私は元気です。
今日はCppUnitについて解説していきたいと思います。
インストール
Homebrewを使いましょう。
brew install cppunit
CppUnitの使い方
サンプルコード
今回、Functionの内部が正確かどうかチェックします。
#include <cppunit/BriefTestProgressListener.h> #include <cppunit/CompilerOutputter.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/TestResult.h> #include <cppunit/TestResultCollector.h> #include <cppunit/TestRunner.h> #include <cppunit/extensions/HelperMacros.h> //テスト対象のクラス class Function{ public: int add(int a,int b); double diff(double a,double b); double mul(double a,double b); }; int Function::add(int a,int b){ return a + b; } double Function::diff(double a,double b){ return 100.0; } double Function::mul(double a,double b){ return 200.0; } class FunctionTest : public CPPUNIT_NS::TestFixture{ //テストクラス CPPUNIT_TEST_SUITE(FunctionTest);//登録のスタート CPPUNIT_TEST(test_add);//メンバ関数の登録 CPPUNIT_TEST(test_diff);//メンバ関数の登録 CPPUNIT_TEST(test_mul);//メンバ関数の登録 CPPUNIT_TEST_SUITE_END();//登録の終了 protected: Function *func; void test_add(); void test_diff(); void test_mul(); public: void setUp(); void testDown(); }; CPPUNIT_TEST_SUITE_REGISTRATION(FunctionTest); //テスト起動時に実行 void FunctionTest::setUp(){ func = new Function(); } //テスト終了時に実行 void FunctionTest::testDown(){ delete func; } void FunctionTest::test_add(){ //正しいので通過 CPPUNIT_ASSERT_EQUAL(3+2,func->add(3,2)); } void FunctionTest::test_diff(){ //ダミーで100を入れたので通過 CPPUNIT_ASSERT_EQUAL(100.0,func->diff(3.0, 2.0)); //assertで止まる CPPUNIT_ASSERT_EQUAL(1.0,func->diff(3.0, 2.0)); } void FunctionTest::test_mul(){ //差が200以下なのでテストを通過する。 CPPUNIT_ASSERT_DOUBLES_EQUAL(6.0,func->mul(3, 2),200.0); } int main(int argc, char const *argv[]){ CPPUNIT_NS::TestResult controller; //結果収集 CPPUNIT_NS::TestResultCollector result; controller.addListener(&result); //途中結果の収集 CPPUNIT_NS::BriefTestProgressListener progress; controller.addListener(&progress); //テストを走らせる。テストを入れて走る CPPUNIT_NS::TestRunner runner; runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() ); runner.run(controller); //結果を標準出力にする。 CPPUNIT_NS::CompilerOutputter outputter(&result,CPPUNIT_NS::stdCOut()); outputter.write(); return result.wasSuccessful() ? 0 : 1; }
流れとしては、テストするためのクラスを生成→内部でテストを書き、mainで実行を行う形です。
以下のFunctionTestがテストをするためのクラス生成であり、TestFixtureを継承しています。
class FunctionTest : public CPPUNIT_NS::TestFixture{ //テストクラス CPPUNIT_TEST_SUITE(FunctionTest);//登録のスタート CPPUNIT_TEST(test_add);//メンバ関数の登録 CPPUNIT_TEST(test_diff);//メンバ関数の登録 CPPUNIT_TEST(test_mul);//メンバ関数の登録 CPPUNIT_TEST_SUITE_END();//登録の終了 protected: Function *func; void test_add(); void test_diff(); void test_mul(); public: void setUp(); void testDown(); };
内部にあるCPPUNIT_TEST_SUITE(FunctionTest)〜CPPUNIT_TEST_SUITE_END();までがテストへの登録を行っている箇所です。ここに登録されたメンバ関数のテストが行われます。
また、setUp,testDown()はテスト起動時に及び終了時に実行されるメンバ関数です
void FunctionTest::test_add(){ //正しいので通過 CPPUNIT_ASSERT_EQUAL(3+2,func->add(3,2)); } void FunctionTest::test_diff(){ //ダミーで100を入れたので通過 CPPUNIT_ASSERT_EQUAL(100.0,func->diff(3.0, 2.0)); //assertで止まる CPPUNIT_ASSERT_EQUAL(1.0,func->diff(3.0, 2.0)); } void FunctionTest::test_mul(){ //差が200以下なのでテストを通過する。 CPPUNIT_ASSERT_DOUBLES_EQUAL(6.0,func->mul(3, 2),200.0); }
テストメンバ関数の内部ですが、
CPPUNIT_ASSERT_EQUAL=その値が正しいかどうか。
CPPUNIT_ASSERT_DOUBLES_EQUAL=その値が一定以上の誤差がないか
CPPUNIT_ASSERT=boolの値を判定
などなど様々なテストケースに対応ができます。
出力はこんな感じ
FunctionTest::test_add : OK FunctionTest::test_diff : assertion FunctionTest::test_mul : OK main.cpp:68: Assertion Test name: FunctionTest::test_diff equality assertion failed - Expected: 1 - Actual : 100 Failures !!! Run: 3 Failure total: 1 Failures: 1 Errors: 0
走っている関数3つ、失敗1ですね。因みに関数内部でいくつもテストを行う場合
死んだ最初の関数の表示とともにAssertが出るようです。
このような関数を組みながら実装すると、テストを作りながら行えるので、実行時の動作をある程度保証しやすくなります。