C++のユニットテスト


以前はプログラムを作成してユニットテストの仕事をしたことがないので、後期には誤り訂正に多くの時間がかかります.これはソフトウェアエンジニアリングの2:8の法則です.最近1つのプロジェクトを完成して、システムの中の主なクラスと主な関数に対してユニットのテストの保证をすることを要求して、やっと関连する方面の资料を探して、后でユニットのテストが工事の中で少なくない1つだと感じて、以下はC++のユニットのテストについて1つの简単な绍介をして、本人がまだシステムの理解する関连する方面の内容がないため、簡単な応用と簡単な原理を紹介するだけで、いくつかの点は指摘してください.
1)ユニットテストとは
ユニットテスト(unit test、モジュールテストはホワイトボックステストとも呼ばれる)は、開発者が作成した小さなコードであり、被測定コードの小さな、明確な機能が正しいかどうかを検出するために使用され、作成ユニットテストを通じて、符号化段階でプログラム符号化エラー、さらにはプログラム設計エラーを発見することができる.今、私たちが普段プログラミングしているプロセスを思い出します.論理を整理する->コードを書く->バグを調整するサイクルプロセスです.デバッグは時間がかかるプロセスであり、バグの山を調整した後、私たちは自分のプログラムに対する信頼度を下げ続けています.バグが出るかどうか分からないからです.これは私たちがデバッグしたバグが現在現れているだけで、現れていないので、私たちはよく言えません.プログラムの簡単なifを知っていますelse...文はすべてデータストリームに対して1回分類して、異なるクラスのデータストリームの対応する操作は異なって、これらを考えてみるとあなたは自分のコードがまだどれだけのバグを出すか分からないと感じます.ユニットテストはこの問題をよく解決しました.あなたがしなければならないのは、コアの関数、コアの論理、すべての可能なデータストリームをリストし、フルオーバーライドテストを行うことです.そうすれば、コードの丈夫さが強くなります.
2)ユニットテストの書き方
最も簡単な方法は、コアの関数を自分で抽出し、プロジェクトを再構築し、可能なすべてのデータストリームエントリを提供し、関数をテストすることです.このようにするには2つの欠陥がある:1、簡単なプロジェクトしか処理できず、論理が複雑で、データの分岐が多いと操作できない.2、良いフレームワークがなく、書かれたコードには統一的なルールがなく、可読性が強くない.そのため、既存のテストフレームワークに頼る必要があります.CppUnitはxunitファミリーの一員であり、xunitはテストフレームワークであり、最初はsmalltalkで実現されたが、その後様々な言語で広く実現された.CppunitのほかにNUnit(c#バージョン)phpunit(phpバージョン)とCppUnitに似たgtest(googleのC++テストツールがあり、応用上CppUnitより優れていると言われているが、使ったことがないので、試してみてください)cmockery(c言語テストツール、googleのものでもあります).cppunitはソースコードで配布されるので、このツールを使用するには自分でダウンロードしてコンパイルする(後述する)とともに、windowsの下でCppUnitにはMFCプロジェクトがあり、グラフィックインタフェースでコンパイル状況を報告することができます.
3)CppUnitのコンパイル方法
私のコンパイル環境はwin 7、vs 2010です.
 
1:ダウンロードソースパッケージの最新バージョンは1.21.1(2008年最終更新)
 
アドレス:http://sourceforge.net/projects/cppunit/またはhttp://sourceforge.net/projects/cppunit/files/cppunit/1.12.1/cppunit-1.12.1.tar.gz/downloadを直接クリック
 
2:cppunt-1.12.1をc:解凍取得ディレクトリC:cppunit-1.12.1にコピー
 
3:C:cppunit-1.12.1srcに入り、VS 2010でCppUnitLibrariesを開きます.dswヒント変換、変換
 
4:プロジェクトリストに多数のプロジェクトが表示され、デフォルトではDebugでコンパイルされます.このようにコンパイルするには、ターゲットファイル名を変更する必要があります.
 
cppunit                $(ProjectName)   ->   $(ProjectName)dcppunit_dll           $(ProjectName)   ->   cppunitd_dllDllPlugInTester     $(ProjectName)   ->   $(ProjectName)d_dllTestPlugInRunner $(ProjectName)   ->   $(ProjectName)dTestRunner          $(ProjectName)  ->   $(ProjectName)d
 
対象ファイル名を変更する必要があるのは、上記の項目に生成イベントが設定されているため、生成後に生成されたファイルをlibディレクトリにコピーする場合、個人判断dはテスト版を意味するはずであり、Releaseバージョンで生成された対象ファイルがすべて項目名であれば変更する必要はない
 
5:DSPlugIn入口の属性を修正して、属性を配置して、リンク、高級で、入口の点の設定がありません
 
6:変更不可ロードタイプライブラリ(コンパイルTestPlugInRunner,TestRunner)7.0が8.0#import"libid:80 cc 9 f 66-e 7 d 8-4 ddd-85 b 6-d 9 e 6 cd 0 e 93 e 2"version("7.0")lcid("0")raw_interfaces_only named_guids
 
以上の設定がすべて完了すると、ソリューション全体をコンパイルできます(ここでは、上記のすべての構成を実装してからコンパイルし、プロジェクトごとに個別にコンパイルしないように注意してください.そうしないと、「ファイルに関連するプログラムが1つもありません...」という質問)
4)Cppunitの使い方
まずテストのDemoを書いて、初歩的にCppunitの使い方を体験します
1、vs 2010ファイル項目を開き、新しいVC++空の項目:cppUnitTest
2、環境変数を設定する;システム変数PATHの尻尾に「C:cppunit-1.12.1」(これは私のアドレス)を追加します.
3、[プロジェクトcppUnitTest]-[プロパティ]-[構成プロパティ]-[C/C+]-[一般]-[追加含むディレクトリ]:「.../include」
4、[プロジェクトcppUnitTest]-[プロパティ]-[構成プロパティ]-[リンク]-[一般]-[ライブラリカタログを添付]:「.../lib」
5、[プロジェクトcppUnitTest]-[プロパティ]-[構成プロパティ]-[リンク]-[入力]-[依存項目]:[cppunitd.lib]
6、新規ファイルmain.cpp
#include <cppunit/TestCase.h>

#include <cppunit/TestResult.h>

#include <cppunit/TestResultCollector.h>

#include <cppunit/TextOutputter.h>

#include <cppunit/TestCaller.h>

#include <cppunit/TestRunner.h>



//      

class StringTest : public CppUnit::TestFixture

{

public:

    void setUp() //    

    {

        m_str1 = "Hello, world";

        m_str2 = "Hi, cppunit";

    }



    void tearDown() //   

    {

    }



    void testSwap() //     1

    {

        std::string str1 = m_str1;

        std::string str2 = m_str2;

        m_str1.swap(m_str2);

        

        CPPUNIT_ASSERT(m_str1 == str2);

        CPPUNIT_ASSERT(m_str2 == str1);

    }



    void testFind() //     2

    {

        int pos1 = m_str1.find(',');

        int pos2 = m_str2.rfind(',');



        CPPUNIT_ASSERT_EQUAL(5, pos1);

        CPPUNIT_ASSERT_EQUAL(2, pos2);

    }



protected:

    std::string     m_str1;

    std::string     m_str2;

};



int main(int argc, char* argv[])

{

    CppUnit::TestResult r; 

    CppUnit::TestResultCollector rc;

    r.addListener(&rc); //          



    CppUnit::TestRunner runner; //       

    runner.addTest(new CppUnit::TestCaller<StringTest>("testSwap", &StringTest::testSwap)); //       1

    runner.addTest(new CppUnit::TestCaller<StringTest>("testFind", &StringTest::testFind)); //       2

    runner.run(r); //     



    CppUnit::TextOutputter o(&rc, std::cout);

    o.write(); //      



    return rc.wasSuccessful() ? 0 : -1;

}

以上のコードの場合、Cppunitフレームワークを使用してstringクラスの2つの関数をテストし、testFind()でstringのfind関数を呼び出し、CPPUNIT_を通過します.ASSERTは結果をテストする;