CUnitでCプログラムの単体テストをする


チュートリアルを鵜呑みにしたらハマったのでメモ。

## インストール

チュートリアルに従い、以下のコマンドを打つことで`/usr/local/`以下にCUnit関連がインストールされます。

```bash:Bash
$ wget http://jaist.dl.sourceforge.net/project/cunit/CUnit/2.1-2/CUnit-2.1-2-src.tar.bz2
$ tar xvf CUnit-2.1-2-src.tar.bz2
$ cd CUnit-2.1-2
$ ./configure
$ make
$ sudo make install
```

## 事前準備

LD_LIBRARY_PATHを明示的に指定しないと共有オブジェクトファイルがないと怒られるのであらかじめ指定しておきます。大事です。
<font color="E0E0E0">ここで1時間弱はまりました。</font>

```bash:Bash
$ export LD_LIBRARY_PATH=/usr/local/lib
```

永続化するには`.bashrc`あたりに追記しておきます。

```bash:.bashrc
export LD_LIBRARY_PATH=/usr/local/lib
```

追記した結果を反映させるには下記いずれかのコマンドを打ってください。

```bash:Bash
$ source ~/.bashrc
$ . ~/.bashrc
```

## 動作確認

チュートリアルに従って`main.c`を作成します。

```c:main.c
//=============================================================================
// ファイル : main.c
//=============================================================================
#include <CUnit/CUnit.h>
#include <CUnit/Console.h>

//-----------------------------------------------------------------------------
// プロトタイプ宣言
//-----------------------------------------------------------------------------
void sort(int array[], int num);
void test_sort_001(void);
void test_sort_002(void);
void test_sort_003(void);
void test_sort_004(void);
void test_sort_005(void);

//-----------------------------------------------------------------------------
// main() 関数
//-----------------------------------------------------------------------------
int main() {
  CU_pSuite sort_suite;

  CU_initialize_registry();
  sort_suite = CU_add_suite("Sort", NULL, NULL);
  CU_add_test(sort_suite, "test_001", test_sort_001);
  CU_add_test(sort_suite, "test_002", test_sort_002);
  CU_add_test(sort_suite, "test_003", test_sort_003);
  CU_add_test(sort_suite, "test_004", test_sort_004);
  CU_add_test(sort_suite, "test_005", test_sort_005);
  CU_console_run_tests();
  CU_cleanup_registry();

  return(0);
}

//-----------------------------------------------------------------------------
// テスト対象のソート関数
//-----------------------------------------------------------------------------
void sort(int array[], int num) {
  int i;
  int j;
  int val;

  for(i=0; i<(num-1); i++) {
    for(j=(num-1); j>i; j--) {
      if (array[j-1] > array[j]) {
        val = array[j];
        array[j] = array[j-1];
        array[j-1] = val;
      }
    }
  }
}

//-----------------------------------------------------------------------------
// テスト関数１
//-----------------------------------------------------------------------------
void test_sort_001(void) {
  int array[] = {3};

  sort(array, 1);
  CU_ASSERT(array[0] == 3);
}

//-----------------------------------------------------------------------------
// テスト関数２
//-----------------------------------------------------------------------------
void test_sort_002(void) {
  int array[] = {11, 7, 5, 3, 2};

  sort(array, 5);
  CU_ASSERT(array[0] == 2);
  CU_ASSERT(array[1] == 3);
  CU_ASSERT(array[2] == 5);
  CU_ASSERT(array[3] == 7);
  CU_ASSERT(array[4] == 11);
}

//-----------------------------------------------------------------------------
// テスト関数３
//-----------------------------------------------------------------------------
void test_sort_003(void) {
  int array[] = {7, 11, 3, 2, 5};

  sort(array, 5);
  CU_ASSERT(array[0] == 2);
  CU_ASSERT(array[1] == 3);
  CU_ASSERT(array[2] == 5);
  CU_ASSERT(array[3] == 7);
  CU_ASSERT(array[4] == 11);
}

//-----------------------------------------------------------------------------
// テスト関数４
//-----------------------------------------------------------------------------
void test_sort_004(void) {
  int array[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

  sort(array, 10);
  CU_ASSERT(array[0] == 1);
  CU_ASSERT(array[1] == 2);
  CU_ASSERT(array[2] == 3);
  CU_ASSERT(array[3] == 4);
  CU_ASSERT(array[4] == 5);
  CU_ASSERT(array[5] == 6);
  CU_ASSERT(array[6] == 7);
  CU_ASSERT(array[7] == 8);
  CU_ASSERT(array[8] == 9);
  CU_ASSERT(array[9] == 10);
}

//-----------------------------------------------------------------------------
// テスト関数５
//-----------------------------------------------------------------------------
void test_sort_005(void) {
  int array[] = {2, 9, 3, 6, 10, 5, 8, 4, 1, 7};

  sort(array, 10);
  CU_ASSERT(array[0] == 1);
  CU_ASSERT(array[1] == 2);
  CU_ASSERT(array[2] == 3);
  CU_ASSERT(array[3] == 4);
  CU_ASSERT(array[4] == 5);
  CU_ASSERT(array[5] == 6);
  CU_ASSERT(array[6] == 7);
  CU_ASSERT(array[7] == 8);
  CU_ASSERT(array[8] == 9);
  CU_ASSERT(array[9] == 10);
}

//=============================================================================
// ファイルエンド
//=============================================================================
```

コンパイルして実行します。

```bash:Bash
$ gcc main.c -Wall -L/usr/local/lib -lcunit
$ ./a.out
```

チュートリアル通りに以下の画面が出れば成功です。
出ない場合はエラーメッセージをググってください。

```bash:Bash
     CUnit - A Unit testing framework for C - Version 2.1-0
     http://cunit.sourceforge.net/


*************** CUNIT CONSOLE - MAIN MENU ***********************
(R)un all, (S)elect suite, (L)ist suites, Show (F)ailures, (Q)uit
Enter Command :
```

## 参考
- [CUnit チュートリアル](http://homepage3.nifty.com/kaku-chan/cunit/index.html)
- [サンプル - ProgrammersHandbook](https://sites.google.com/site/programmershandbook/home/software-test/unit-test/cunit/sanpuru)