C++で簡易単体テスト。assert、静的解析

#単体テスト書いてますか？

C++では一度も単体テスト書いたことありません・・・申し訳ございません・・
反省しこれから　単体テストをちゃんと作ろうと思います

理想形は Jenkinsおじさんをこき使って　Gitと連携です
C++には boost.testやCppTest、GoogleTest等があります

ただし、Jenkinsの設定が面倒だったり、クライアントサーバ型の場合はモックも作る必要が出るので
今回は 超お手軽にテストができる
assert、static_assert　を使うことに！　お手軽！！

##assert
assert(exp)
プログラム実行時に、引数の条件式が trueの時は何も行わない
falseの場合は、　ファイル名、行番号、関数名等をprintoutし プログラムを終了します

ただし　#define NDEBUG が定義されている場合は、この部分はコンパイル対象にならないので
リリース時は makefileに -DNDEBUGを定義しましょう！

```cpp:assert
#include<assert.h>
#include<iostream>

int main(){    
    int hoge = 4;
    int hoge2 = 5;
    
    std::cout << "check hog2" << std::endl;
    assert(hoge==4);
    std::cout << "check hoge2" << std::endl;
    assert(hoge2==4);
    std::cout << "fin" << std::endl;
    
    return 1;
}



結果

check hog2
check hoge2
prog.exe: prog.cc:11: int main(): Assertion `hoge2==4' failed.
Aborted
```

assert(hoge2==4);
で　Abortし finが表示されてませんね。

ちなみに　#include<assert.h> 以前に #define NDEBUG　を書くと
assert無視され　finまで到達します


例えば関数の入力値の範囲チェックや、配列数等のチェックを
リリースビルド時には無視されるので　好きなだけ追加しましょう！


##static_assert
static_assert(exp,msg);

コンパイル時に 条件式expを評価し、falseの場合はmsgを表示しコンパイルエラーを吐きコンパイルを中断する

コンパイル時assertですね

```cpp:static_assert
#include<assert.h>
#include<iostream>

int main(){    
    const int hoge = 4;
    const int hoge2 = 5;
    
    std::cout << "check hog2" << std::endl;
    static_assert(hoge==4, "error");
    std::cout << "check hoge2" << std::endl;
    static_assert(hoge2==4, "error" );
    std::cout << "fin" << std::endl;
    
    return 1;
}


結果

prog.cc: In function 'int main()':
prog.cc:11:5: error: static assertion failed: error
     static_assert(hoge2==4, "error" );
     ^~~~~~~~~~~~~
```

コンパイル時にエラーが出ました
使う場所が限定されますが、コンパイル時にわかる不具合はここで潰すと良いと思います

一例でいうと
・intやfloatの大きさのチェック
・バイトオーダーのチェック
・キャスト時の継承関係チェック

など。
今回私は　バイトオーダーチェックなどに使っています



assert、static_assertを使うと、単体テストフレームワークを使うより
簡単にテストが行えますね


#静的解析&lint使ってますか？？
C++では、メモリリーク、２重開放など色々な不具合が発生するけど
それをコンパイル時に見つけるのが　静的解析ツールで
思った以上に　見つけてくれるので使いましょう

cppcheck、splint、scan-build
等あります。

コンパイラをclangにしている場合は、デフォルトでscan-buildが使えるので
時々実行してみましょう

静的解析ツールは、誤認識率も多少あるので、できれば沢山使うといいと思ってます


##scan-build (clang)

clangに最初からついているので　scan-buildが便利です！

$ scan-build make -B
とすると、プロジェクト全体の静的解析を行ってくれます
scan-viewで　レポートファイルを開けば、問題点をGUIで表示できるので
とても便利です

以前は　scan-build make　で、プロジェクトの全ファイルの静的解析が出来ていたのですが
なぜか今行なうと ちゃんと動かなくなっており
１ファイルずつ解析しか出来なく・・・
なぜだろう・・・


##cppcheck
パッケージあるいはソースからビルドして
cppcheck --enable=all ファイル名
あるいは
cppcheck --enable=all folder フォルダ名
で、チェック結果をコンソールに出力します

enableを指定しないと何も出力されません
チェックしたい項目のみ指定すると便利です

folderは再帰的に呼んでくれるので便利です
特定ファイルの除外、特定ファイルの追加等の柔軟な設定も可能です


##splint
http://www.splint.org/faq.html#quest5
>Does Splint handle C++?
>
>No, Splint does not check C++ code. We don't have the resources (or the >research justification) to build a C++ front end, but if you are interested in >building a C++ front end the source code is available, and I will certainly be >willing to help.

ということで、C++には対応してないっぽいので　ザンネン





#結果
現在わたしは、単体テストとして
static_assert、assert　をメインで使っています
boost.TestやJenkins連携は 今度トライしようと・・

静的解析としては
scan-buildが便利だったのですが、うまくプロジェクトファイルを読み込めなくなり
原因を探っています。。

ので、現在はメインで cppcheckで特定フォルダごとにチェックしています

scan-buildは見やすいし便利だったので、なんとかして動くようにしたいですね・・