C++ なライブラリを書こうと思い、C++のテストってどうやるんだろうと調べたメモ。 テストフレームワークとして Google C++ Testing Framework を使用、 コンパイルにはautotoolを使ってtravis-ciでテストするところまでやってみました。
やってみた結果→ cpp-test
Testを書く
Google Test の入門ガイドに書いてあったテストをコピペしてきました。
#include "gtest/gtest.h"
int Factorial(int n);
TEST(FractionTest, hoge) {
EXPECT_EQ(1, Factorial(1));
EXPECT_EQ(2, Factorial(2));
EXPECT_EQ(6, Factorial(3));
EXPECT_EQ(40320, Factorial(8));
}
テストの対象となる関数はこちら。
// calculate 1 * 2 * 3 * ... * n
int Factorial(int n) {
if(n == 0) return 1;
return n * Factorial(n - 1);
}
テスト用実行ファイルのビルドをする
せっかくならしっかりしたものをつくろうと、Autotoolsを使ってビルドしてみました。 新しめの Autotools (Autoconf&Automake) を使ってみよう を参考に Makefileのひな形を書いていきます。
Google Test と Travice CI で、C言語で書いたライブラリの継続的インテグレーションをしてみた結果 ではGoogle Testをシステムにインストールしていますが、 システムへのインストールは推奨されていないのと、手元で動かすのが面倒だったので Fused Source File を作ってGoogle Testを自分のプロジェクトに同梱しちゃいました。
Google Testのプロジェクトでpython fuse_gtest_files.py OUTPUT_DIR
を実行すると
gtest/gtest.h
と gtest/gtest-all.cc
が作られるので、
この2つのファイルを自分のプロジェクトにコピーしてきます。
あとは Makefile.am でこれらのファイルをコンパイル&リンクするように設定します。
自分のプロジェクトでは使っていなくても、Google Test のコンパイルには pthread が必要なので忘れずに。
(clangでは無くても動くらしく、clangで試していたらgccで動かなくてちょっとはまった)
TESTS = factorial_test
check_PROGRAMS = factorial_test
factorial_test_SOURCES = factorial.cpp gtest_main.cc gtest-all.cc
factorial_test_LDADD = ../src/libfactorial.a
factorial_test_LDFLAGS = -pthread
make check
でテストが走るようになります。
Google Test のソースがプロジェクトに含まれているので、
新しくプログラムをインストールしたり、特別な設定をしたりといったことは必要ありません。
travis-ci でテストする
travisのC++のテストは、標準で./configure && make && make test
を実行してくれますが、
autotoolsで作ったMakefileだと上手く動かないので以下のように.travis.ymlを設定します。
language: cpp
script: autoreconf -fi && ./configure && make && make check
gnuなプロジェクトのお作法にしたがって、以下のように書き換えてあります。
- configureスクリプトはautotoolsで自動生成されるファイルなのでレポジトリには入れず、テスト前に生成する
- make check でテストが走るのが普通らしい
configureスクリプトを自動生成するのでautoconfのバージョンに注意してください。
autoconfは2014/05/18現在2.69が最新版ですが、travis-ciは2.68がインストールされているようです。
最新版のautoconfでconfigure.acのひな形を作るとAC_PREREQ([2.69])
のように必要バージョンが設定されてしまい、
テストのときにconfigureファイルを作れなくて死にます。
バージョン指定を削除するか、古いバージョンに書き換えましょう。
C++のお作法がよくわかっていないですが、ちょっとずつ頑張っていきます。