Google Testを導入してみた

GoogleがC++単体テスト用ライブラリとして開発したGoogle Testを開発で利用しようと思いインストールしました。ネットで公開されている情報は、最新のVer1.8.xに即した情報が少ない印象を受けましたので、導入方法をまとめて公開することにしました。

# インストールを試した環境
* Ubuntu 16.04 LTS (WSL版)
* macOS Mojave 10.14.6

上記どちらのOSでも下記の方法でインストール、サンプルプログラムの実行まで出来ました。

なお、本記事はGoogle Testをローカル環境にインストールして実行する方法を解説していますが、以下の記事では、より実際の開発現場での利用を想定した外部プロジェクトとしてGoogle Testを実行する方法を解説しています。

https://qiita.com/y-vectorfield/items/f69464ee5d8cd80153bd

# 前準備 : CMakeのインストール
今回はローカル環境にGoogle Testを静的ライブラリーとしてインストールする方法を実施しました。ソースコードのビルドに必要なCMakeのインストールをまず行います。

## Ubuntuの場合

```bash
sudo apt-get install cmake
```

## macOSの場合([Homebrew](https://brew.sh/index_ja)を利用)

```bash
brew install cmake
```
# ソースコードのダウンロード及びビルド
[GitHub](https://github.com/google/googletest)よりGoogle Testのソースコードをクローンし、CMakeとGNU Makeでビルドを実施します。方法は以下の通りです。(以降の行程は全てhomeディレクトリ上で実施しています)

### GitHubからソースファイルをクローン

```bash
git clone https://github.com/google/googletest.git
```
### googletestディレクトリに移動

```bash
cd googletest
```
### ビルド用ディレクトリの作成

```bash
mkdir build
```
### ビルド用ディレクトリに移動

```bash
cd build
```

### CMakeの実行

```bash
cmake ..
```
### GNU Makeの実行

```bash
make
```

<details><summary>以下の表示が出ればビルド成功です。</summary><div>

```
Scanning dependencies of target gtest 
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o 
[ 25%] Linking CXX static library ../lib/libgtest.a 
[ 25%] Built target gtest 
Scanning dependencies of target gmock 
[ 37%] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o 
[ 50%] Linking CXX static library ../lib/libgmock.a 
[ 50%] Built target gmock 
Scanning dependencies of target gmock_main 
[ 62%] Building CXX object googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o 
[ 75%] Linking CXX static library ../lib/libgmock_main.a 
[ 75%] Built target gmock_main 
Scanning dependencies of target gtest_main 
[ 87%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o 
[100%] Linking CXX static library ../lib/libgtest_main.a 
[100%] Built target gtest_main 
```

</div></details>


# 出力結果を適切なディレクトリに格納
make実行後、出力される実行ファイル・ソースファイルを適切なディレクトリに格納します。

```bash
sudo cp -r ~/googletest/googlemock/include/gmock /usr/local/include/gmock
sudo cp -r ~/googletest/googletest/include/gtest /usr/local/include/gtest
sudo cp ~/googletest/build/lib/*.a /usr/local/lib/
```
# Testの実行
実行ファイルを格納後、実際にソースファイルをビルドし、テストが実行出来るか試します。今回試したソースコードは以下のコードです。

```c++

#include <gtest/gtest.h>

TEST(TestCaseName, TestName){
    EXPECT_EQ(1, 1);
}
```

# ソースコードのビルド
上記ソースコードをビルドしました。オプションは3つです。Makefile化しておけば楽になるかと思われるため、Makefile化も今後試みるつもりです。

```bash
g++ test.cpp -pthread -lgtest_main -lgtest
```

ビルド後、生成される実行ファイルを実行

```bash
./a.out
```

<details><summary>テストが通ると以下の内容が出力されます</summary><div>

```
Running main() from /home/yuhkiyano/googletest/googletest/src/gtest_main.cc 
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from TestCaseName
[ RUN      ] TestCaseName.TestName 
[       OK ] TestCaseName.TestName (0 ms)
[----------] 1 test from TestCaseName (6 ms total)

[----------] Global test environment tear-down 
[==========] 1 test from 1 test suite ran. (46 ms total)
[  PASSED  ] 1 test.
```

</div></details>

## Google Testのサンプルの実行 (追記：2019/8/28)

前回試みたサンプルは単にテストが動くかどうかのサンプルだったので、[公式サンプル @ Git Hub](https://github.com/google/googletest/tree/master/googletest/samples)のsample1を試してみることにしました。

<strong>テスト対象のプログラム(sample1.cpp)</strong>

```cpp

#include "sample1.h"

int Factorial(int n){
    int result = 1;
    for(int i = 1; i <= n; i++){
        result *= i;
    }

    return result;
}

bool IsPrime(int n){

    if(n <= 1) return false;

    if(n % 2 == 0) return n == 2;

    for(int i = 3; ; i += 2){
        if(i > n/i) break;

        if(n % i == 0) return false;
    }

    return true;
}

```

<strong>ヘッダーファイル(sample1.h)</strong>

```cpp

#ifndef GTEST_SAMPLES_SAMPLE1_H_
#define GTEST_SAMPLES_SAMPLE1_H_

int Factorial(int n);

bool IsPrime(int n);

#endif

```

<strong>テストプログラム(test_sample1.cpp)</strong>

```cpp

#include <limits.h>
#include <gtest/gtest.h>
#include "sample1.h"

namespace{

    TEST(FactorialTest, Negative){
        EXPECT_EQ(1, Factorial(-5));
        EXPECT_EQ(1, Factorial(-1));
        EXPECT_GT(Factorial(-10), 0);
    }

    TEST(FactorialTest, Zero){
        EXPECT_EQ(1, Factorial(0));
    }

    TEST(FactorialTest, Positive){
        EXPECT_EQ(1, Factorial(1));
        EXPECT_EQ(2, Factorial(2));
        EXPECT_EQ(6, Factorial(3));
        EXPECT_EQ(40320, Factorial(8));
    }

    TEST(IsPrimeTest, Negative){
        EXPECT_FALSE(IsPrime(-1));
        EXPECT_FALSE(IsPrime(-2));
        EXPECT_FALSE(IsPrime(INT_MIN));
    }

    TEST(IsPrimeTest, Trivial){
        EXPECT_FALSE(IsPrime(0));
        EXPECT_FALSE(IsPrime(1));
        EXPECT_TRUE(IsPrime(2));
        EXPECT_TRUE(IsPrime(3));
    }

    TEST(IsPrimeTest, Positive){
        EXPECT_FALSE(IsPrime(4));
        EXPECT_TRUE(IsPrime(5));
        EXPECT_FALSE(IsPrime(6));
        EXPECT_TRUE(IsPrime(23));
    }

}

```

```bash
g++ sample1.cpp test_sample1.cpp -pthread -lgtest_main -lgtest
```

<details><summary>テストが通ると以下の内容が出力されます</summary><div>

```
Running main() from /home/yuhkiyano/googletest/googletest/src/gtest_main.cc
[==========] Running 6 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 3 tests from FactorialTest
[ RUN      ] FactorialTest.Negative
[       OK ] FactorialTest.Negative (0 ms)
[ RUN      ] FactorialTest.Zero
[       OK ] FactorialTest.Zero (0 ms)
[ RUN      ] FactorialTest.Positive
[       OK ] FactorialTest.Positive (0 ms)
[----------] 3 tests from FactorialTest (41 ms total)

[----------] 3 tests from IsPrimeTest
[ RUN      ] IsPrimeTest.Negative
[       OK ] IsPrimeTest.Negative (0 ms)
[ RUN      ] IsPrimeTest.Trivial
[       OK ] IsPrimeTest.Trivial (0 ms)[ RUN      ] IsPrimeTest.Positive
[       OK ] IsPrimeTest.Positive (0 ms)
[----------] 3 tests from IsPrimeTest (45 ms total)

[----------] Global test environment tear-down
[==========] 6 tests from 2 test suites ran. (168 ms total)
[  PASSED  ] 6 tests.
```

</div></details>

## まとめ
今回は、インストールと簡単なサンプルプログラムを実行し、Google Testのインストール及び動作確認を行いました。今後、Makefile化等も試みたいと思います。

## Reference
* [Google Test勉強録 (1) CMakeでのビルド](https://qiita.com/ktrmnm/items/667a7b7c93cd3fb78419)
* [GoogleTest (C++ テストフレームワーク) の基本的な使用方法](https://www.qoosky.io/techs/5cde719e89)
* [Google Testの使い方](https://qiita.com/shohirose/items/30e39949d8bf990b0462)