WSLでCppUTestを試してみた

# 読者対象
Linux/Cの開発目線で試したので

- LinuxにてC/C++で開発しているがテストコードを書いていない人
- CppUTestを使ってみたいがインストールしたことがない人

となります。かなり優しい内容ですのですでに使用されている方は対象外な記事となります。

# 環境
タイトル通りWSLでの構築となります。

- Windows10
    - WSL(Ubuntu 18.04)

# ダウンロード & インストール
- オフライン/オンプレミス環境も考慮し、今回はサイトからdownloadしました。
    - git cloneできるなら、そちらのほうが簡単です。<br>`git clone git://github.com/cpputest/cpputest.git`
- WSLがまっさらな場合、以下はインストールしておきましょう<br>`sudo apt install git gcc g++ build-essential cmake`
    - git
    - gcc
    - g++
    - build-essential
    - cmake

- また、実験にてtreeコマンドを使用しているので、同様にコマンドを使用する場合は、treeコマンドもインストールしておいてください。<br>`sudo apt install tree`

## ダウンロード
[Cpputest](https://cpputest.github.io/)
「Download Release 3.8 as tar.gz」をクリックして保存します。
保存物をUSBメモリ等で持ち込んでから開始となります。(同PCの場合はそのまま継続)

## インストール
- ダウンロードした圧縮ファイルを任意のフォルダに格納します。<br>
ここでは`/usr/local/src`とします。

```bash:Command
cd /usr/local/src
tar xvfzp cpputest-3.8.tar.gz
cd cpputest-3.8
cd cpputest_build
cmake ..
make
sudo make install
cd ../script
chmod +x NewProject.sh
```

`make install `は管理者権限が必要でしたので`sudo`をつけて回避しました。

- 環境変数に`CPPUTEST_HOME`を設定し、`PATH`に追加を行います。<br>今回は`.bash_profile`で設定しました。

```bash:.bash_profile
#!/bin/bash
  
export CPPUTEST_HOME=/usr/local/src/cpputest-3.8
export PATH=$PATH:${CPPUTEST_HOME}/scripts
```

# 実験開始
構築は完了なので、テストしてみます。

- プロジェクトを作成します。練習用としてPracticeプロジェクトとします。<br>`NewProject.sh Practice`
- 以下のように階層ができます。

``` bash:tree
.
└── Practice
    ├── Makefile
    ├── include
    │   └── util
    │       └── PracticeBuildTime.h
    ├── src
    │   └── util
    │       └── PracticeBuildTime.cpp
    └── tests
        ├── AllTests.cpp
        └── util
            └── PracticeBuildTimeTest.cpp
```

- 何も考えずにPracticeディレクトリで`make`するとテストできます。(今は空なのでOKになる)
- includeにファイルを追加するとコンパイルで失敗します。<br>`Makefile`の`INCLUDE_DIRS`に定義されている`include/*`を`include/util`に変更しておくとよいでしょう。
- include/srcの下に作成するヘッダ・ソースを格納します。(ここはCでもOKです。)
    - テストNGにしたいので足す・引くの関数で掛ける・割るにしておきます。

``` c:include/practice.h
#ifndef _PRACTICE_H_
#define _PRACTICE_H_

int plus(int, int);
int minus(int, int);

#endif // _PRACTICE_H_
```

``` c:src/plus.c
#include "practice.h"

int plus(int a, int b)
{
    return a * b; // あ、掛け算
}
```

``` c:src/minus.c
#include "practice.h"

int minus(int a, int b)
{
    return a / b; // あ、割り算
}
```

- testsの下にテストコードを書きます。<br>**C++で作成することを忘れずに**<br>テストソース名は`*_test.cpp`にしました。

``` c:tests/plus_test.cpp
#include "CppUTest/TestHarness.h"

extern "C"
{
#include "practice.h"
}

TEST_GROUP(plus)
{
    void setup(){};

    void teardown(){};
};

TEST(plus, InputPlusValue)
{
    int ret = plus(5, 6);
    CHECK_EQUAL(11, ret);
}
```

``` c:tests/minus_test.cpp
#include "CppUTest/TestHarness.h"

extern "C"
{
#include "practice.h"
}

TEST_GROUP(minus)
{
    void setup(){};

    void teardown(){};
};

TEST(minus, InputPlusValue)
{
    int ret = minus(10, 2);
    CHECK_EQUAL(8, ret);
}
```


では、コンパイルしてみます。

```:NGpattern
compiling plus_test.cpp
compiling PracticeBuildTimeTest.cpp
compiling plus.c
compiling minus.c
compiling PracticeBuildTime.cpp
Building archive lib/libPractice.a
a - objs/src/plus.o
a - objs/src/minus.o
a - objs/src/util/PracticeBuildTime.o
Linking Practice_tests
Running Practice_tests
.
tests/plus_test.cpp:18: error: Failure in TEST(plus, InputPlusValue)
        expected <11>
        but was  <30>
        difference starts at position 0 at: <          30        >
                                                       ^

.
tests/minus_test.cpp:18: error: Failure in TEST(minus, InputPlusValue)
        expected <8>
        but was  <5>
        difference starts at position 0 at: <          5         >
                                                       ^

.
Errors (2 failures, 3 tests, 3 ran, 3 checks, 0 ignored, 0 filtered out, 1 ms)
```

しっかりエラーになりましたので、足し算・引き算に直して再度実施すると

```:OKpattern
compiling plus.c
compiling minus.c
Building archive lib/libPractice.a
r - objs/src/plus.o
r - objs/src/minus.o
r - objs/src/util/PracticeBuildTime.o
Linking Practice_tests
Running Practice_tests
...
OK (3 tests, 3 ran, 3 checks, 0 ignored, 0 filtered out, 0 ms)
```

OKになりました。
これでTDD始められますね！

### 補足
- src以下やtests以下にディレクトリ配置しても（階層化しても）Makefileを修正することなくテスト対象として認識されました。<br>拡張が簡単です！