8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

(続) Google Testを導入してみた

Last updated at Posted at 2019-10-08

以前投稿したGoogle Testを導入してみたという記事をではGoogle Testをローカルにインストールして実行する方法を試みました。今回はGoogle Test勉強録 (1) CMakeでのビルドという記事で紹介されている外部プロジェクトとしてダウンロードしてテストを実行する方法を最新版のGoogle Testで試みたいと思います。

実施の動機

  • 複数人で開発を行う時にGoogle Testのバージョンの違いを考慮しなくても済む様にしたい。
  • ローカルに置くスタイルはHomebrewとの相性が良くないため @ macOS

インストールを試した環境

前回の記事とは検証環境が一部異なります。

  • Ubuntu 18.04.2 LTS
  • macOS Mojave 10.14.6
  • ビルドに使用するCMakeはVer3.10.x以降のバージョンが必要です。

:pensive: Ubuntu 16.04.xはVer3.5までの対応となります。
:sweat_smile: macOSの場合、(ビルド時に)別途追加設定が必要になります。

CMakeのバージョンの確認方法

$ cmake /V
cmake version 3.15.3

現段階で上記どちらのOSでも下記の方法でインストール、サンプルプログラムの実行まで出来ました。因みに前回の記事ではGoogle Test Ver1.8.xが最新版でしたが、現在はGoogle Test Ver1.10.xが最新版です。

前準備 : CMakeのインストール(念のため記載)

ソースコードのビルドに必要なCMakeのインストールをまず行います。

Ubuntuの場合

sudo apt-get install cmake

macOSの場合(Homebrewを利用)

brew install cmake

前準備2 : gcc, g++最新版のインストール

Ubuntuの場合

sudo apt-get update && sudo apt-get install build-essential

macOSの場合(Homebrewを利用)

Google TestはC++11をベースに実装されている様です。故に、macOSデフォルトのgccやg++(試した環境ではVer4.2)ではビルドエラーが発生し、ビルドすることが出来ません。(∵ C++11で導入された新しい構文等に対応していないため)

brew install gcc
ln -s /usr/local/bin/gcc-9 /usr/local/bin/gcc
ln -s /usr/local/bin/g++-9 /usr/local/bin/g++

~/.bash_profileに以下を記載し、有効化します。

export PATH=$PATH:/usr/local/bin
. ~/.bash_profile

これで、gcc, g++双方とも最新版が利用出来ます。(試したmacOSの環境ではVer9.x)

テストプロジェクトの作成

今回は以下の様なテストプロジェクトを用意しました。


test_project/ 
├── cmake
├── CMakeLists.txt
├── src
│   ├── CMakeLists.txt
│   ├── sample1.cpp
│   └── sample1.h
└── test
    ├── CMakeLists.txt
    └── test_sample1.cpp

各ディレクトリの作成

mkdir test_project
cd test_googletest_project
mkdir src test cmake

テストソースの作成

以下の様なサンプルソースを用意しました。Google Testの公式チュートリアルから作成したサンプルソースです。(一部のソースは前回の記事でも利用したものです)

CMakelists.txt
cmake_minimum_required(VERSION 3.10)
project(Sample1)
enable_testing()
add_subdirectory(src)
add_subdirectory(test)
src/CMakelists.txt
cmake_minimum_required(VERSION 3.10)
add_library(Sample1 STATIC sample1.cpp)
src/sample1.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;
}
src/sample1.h
#ifndef GTEST_SAMPLES_SAMPLE1_H_
#define GTEST_SAMPLES_SAMPLE1_H_

int Factorial(int n);

bool IsPrime(int n);

#endif
test/CMakelists.txt
cmake_minimum_required(VERSION 3.10)

include(${PROJECT_SOURCE_DIR}/cmake/DownloadProject/DownloadProject.cmake)
download_project(PROJ googletest
                GIT_REPOSITORY https://github.com/google/googletest.git
                GIT_TAG master
                UPDATE_DISCONNECTED 1
)

add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})

add_executable(TestSample1 test_sample1.cpp)
target_link_libraries(TestSample1 Sample1 gtest_main)
include_directories(${PROJECT_SOURCE_DIR}/src)
# C++11をオプションに加える
target_compile_features(TestSample1 PUBLIC cxx_std_11)

include(GoogleTest)
gtest_add_tests(TARGET TestSample1)
  • 2019/10/11訂正: @shohirose さんから御教授頂いた点を追加しました。御教授ありがとう御座いました。
test/test_sample1.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));
    }

}

ビルドの準備

cmake, makeでビルドを行うための準備をします。プロジェクトのルートディレクトリ下にビルド用ディレクトリを作成します。

mkdir build

以下の様なディレクトリ構造となりました。

test_project/
├── CMakelists.txt
├── build
├── cmake
├── src
│   ├── CMakelists.txt
│   ├── sample1.cpp
│   └── sample1.h
└── test
    ├── CMakelists.txt
    └── test_sample1.cpp

DownloadProjectをGitHubからクローン

GitHubからDownloadProjectをクローンします。これはCMake実行時に指定した外部プロジェクト(ここではライブラリ群など)をGitHubからクローンしてくれるツールです。

git clone https://github.com/Crascit/DownloadProject.git cmake/DownloadProject

DownloadProject/DownloadProject.cmakeDownloadProject/DownloadProject.CMakeLists.cmake.inのみビルドに必要なので、この2種類のファイルのみを取り出してプロジェクトに格納するという方法でも良いと思います。test/CMakelists.txtは以下を参考に修正して下さい。

修正版 : test/CMakelists.txt
test/CMakelists.txt
cmake_minimum_required(VERSION 3.10)

include(${PROJECT_SOURCE_DIR}/cmake/DownloadProject.cmake)
download_project(PROJ googletest
                GIT_REPOSITORY https://github.com/google/googletest.git
                GIT_TAG master
                UPDATE_DISCONNECTED 1
)

add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})

add_executable(TestSample1 test_sample1.cpp)
target_link_libraries(TestSample1 Sample1 gtest_main)
include_directories(${PROJECT_SOURCE_DIR}/src)

include(GoogleTest)
gtest_add_tests(TARGET TestSample1)

ソースコードのビルド及びGoogle Testによるテストの実行

以下のコマンドを実行し、Google Testによるテストを実行します。

cd build

Ubuntuの場合は以下のコマンドを実行します。

cmake ..

macOSはgcc, g++のパス情報をオプションで渡す必要が有ります。オプションを渡さずに実行するとデフォルトのgcc, g++(試した環境ではVer4.2)がコンパイラとして認識されてしまいます。

cmake -DCMAKE_C_COMPILER=/usr/local/bin/gcc -DCMAKE_CXX_COMPILER=/usr/local/bin/g++ ..

オプション付きのcmakeのコマンドを.bashrcにaliasとして登録しておけば、つらつらとオプションを入力しなくても済みます。

alias cmake='cmake -DCMAKE_C_COMPILER=/usr/local/bin/gcc -DCMAKE_CXX_COMPILER=/usr/local/bin/g++'

以下の二種類の結果を比較するとCのコンパイラやC++のコンパイラのPathが異なっていることが分かります。

オプションを渡さず実行した場合 @ macOS
$ cmake ..
-- The C compiler identification is AppleClang 11.0.0.11000020
-- The CXX compiler identification is AppleClang 11.0.0.11000020
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Downloading/updating googletest
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/User/google-test-download-test/test_project/build/googletest-download
Scanning dependencies of target googletest-download
[ 11%] Creating directories for 'googletest-download'
[ 22%] Performing download step (git clone) for 'googletest-download'
Cloning into 'googletest-src'...
Already on 'master'
Your branch is up to date with 'origin/master'.
[ 33%] No patch step for 'googletest-download'
[ 44%] Skipping update step for 'googletest-download'
[ 55%] No configure step for 'googletest-download'
[ 66%] No build step for 'googletest-download'
[ 77%] No install step for 'googletest-download'
[ 88%] No test step for 'googletest-download'
[100%] Completed 'googletest-download'
[100%] Built target googletest-download
-- Found PythonInterp: /Users/User/anaconda3/bin/python (found version "3.7.3") 
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/User/google-test-download-test/test_project/build
オプションを渡して実行した場合 @ macOS
$ cmake -DCMAKE_C_COMPILER=/usr/local/bin/gcc -DCMAKE_CXX_COMPILER=/usr/local/bin/g++ ..
-- The C compiler identification is GNU 9.2.0
-- The CXX compiler identification is GNU 9.2.0
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/local/bin/gcc
-- Check for working C compiler: /usr/local/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Check for working CXX compiler: /usr/local/bin/g++
-- Check for working CXX compiler: /usr/local/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Downloading/updating googletest
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/yuhkiyano/developing/google-test-download-test/test_project/build/googletest-download
Scanning dependencies of target googletest-download
[ 11%] Creating directories for 'googletest-download'
[ 22%] Performing download step (git clone) for 'googletest-download'
Cloning into 'googletest-src'...
Already on 'master'
Your branch is up to date with 'origin/master'.
[ 33%] No patch step for 'googletest-download'
[ 44%] Skipping update step for 'googletest-download'
[ 55%] No configure step for 'googletest-download'
[ 66%] No build step for 'googletest-download'
[ 77%] No install step for 'googletest-download'
[ 88%] No test step for 'googletest-download'
[100%] Completed 'googletest-download'
[100%] Built target googletest-download
-- Found PythonInterp: /Users/yuhkiyano/anaconda3/bin/python (found version "3.7.3") 
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/yuhkiyano/developing/google-test-download-test/test_project/build
make

正常にビルドが完了した場合、以下の様に表示されます。

$ make
Scanning dependencies of target Sample1
[  8%] Building CXX object src/CMakeFiles/Sample1.dir/sample1.cpp.o
[ 16%] Linking CXX static library libSample1.a
[ 16%] Built target Sample1
Scanning dependencies of target gtest
[ 25%] Building CXX object googletest-build/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 33%] Linking CXX static library ../../lib/libgtest.a
[ 33%] Built target gtest
Scanning dependencies of target gtest_main
[ 41%] Building CXX object googletest-build/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[ 50%] Linking CXX static library ../../lib/libgtest_main.a
[ 50%] Built target gtest_main
Scanning dependencies of target TestSample1
[ 58%] Building CXX object test/CMakeFiles/TestSample1.dir/test_sample1.cpp.o
[ 66%] Linking CXX executable TestSample1
[ 66%] Built target TestSample1
Scanning dependencies of target gmock
[ 75%] Building CXX object googletest-build/googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 83%] Linking CXX static library ../../lib/libgmock.a
[ 83%] Built target gmock
Scanning dependencies of target gmock_main
[ 91%] Building CXX object googletest-build/googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[100%] Linking CXX static library ../../lib/libgmock_main.a
[100%] Built target gmock_main
cmakeでオプションを渡さずに実行した場合 @ macOS

以下の様なエラー終了になります。

$ make

...

fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
make[2]: *** [test/CMakeFiles/TestSample1.dir/test_sample1.cpp.o] Error 1
make[1]: *** [test/CMakeFiles/TestSample1.dir/all] Error 2
make: *** [all] Error 2
make test

無事テストが通ると以下の様に表示されます。

$ make test
Running tests...
Test project /Users/yuhkiyano/developing/google-test-download-test/test_project/build
    Start 1: FactorialTest.Negative
1/6 Test #1: FactorialTest.Negative ...........   Passed    0.03 sec
    Start 2: FactorialTest.Zero
2/6 Test #2: FactorialTest.Zero ...............   Passed    0.01 sec
    Start 3: FactorialTest.Positive
3/6 Test #3: FactorialTest.Positive ...........   Passed    0.01 sec
    Start 4: IsPrimeTest.Negative
4/6 Test #4: IsPrimeTest.Negative .............   Passed    0.01 sec
    Start 5: IsPrimeTest.Trivial
5/6 Test #5: IsPrimeTest.Trivial ..............   Passed    0.01 sec
    Start 6: IsPrimeTest.Positive
6/6 Test #6: IsPrimeTest.Positive .............   Passed    0.01 sec

100% tests passed, 0 tests failed out of 6

Total Test time (real) =   0.08 sec

まとめ

本記事ではGoogle Testを外部プロジェクトとして取り込む方法に挑戦しました。今後はMakefileによる自動化にも挑戦したいと思います。OSSの常とはいえ、前回の記事で試したUbuntu16.04.xでエラーが続出して苦戦したり、macOSのCMakeのオプション渡しによるエラー回避等トラブル解決に苦戦させられた挑戦となりました。

Reference

https://qiita.com/ktrmnm/items/667a7b7c93cd3fb78419
https://github.com/Crascit/DownloadProject
https://qiita.com/wawawa/items/50c2c612b0937f28d92b
https://qiita.com/tamorieeeen/items/94c9eac62093f039dab6
https://qiita.com/yoyomion/items/7974bb093038c21db26d
https://stackoverflow.com/questions/24380456/how-can-i-make-cmake-use-gcc-instead-of-clang-on-mac-os-x

8
4
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?