ヘッダ1つでgoogle testっぽくテストが書けるpicotest書いた
以下に修正BSDライセンスで公開しておきます:
一応VC10/VC11(Win7),gcc4.6.2(Ubuntu)で動作確認。
これは何?
C++向けのユニットテスティングフレームワークです。ちょっとしたコードに対してテストを書きたいなー、でもわざわざテストのためにGoogle Testをリンクするのも、Boost.Testを引っ張り出すのも大げさ*1…みたいな時に使えるかもしれません。ヘッダだけで使えるテスティングフレームワークは他にもあります*2が、picotestは以下のような特徴があります。
サンプル
#include "picotest.h" int Factorial(int n) { return n == 0 ? 1 : n * Factorial(n - 1); } // 0 の階乗をテスト TEST(FactorialTest, HandlesZeroInput) { EXPECT_EQ(1, Factorial(0)); } // 正の数の階乗をテスト TEST(FactorialTest, HandlesPositiveInput) { EXPECT_EQ(1, Factorial(1)); EXPECT_EQ(2, Factorial(2)); EXPECT_EQ(6, Factorial(3)); EXPECT_EQ(40320, Factorial(8)); } int main(int argc, char **argv) { RUN_ALL_TESTS(); }
サンプルコードはgoogle testのドキュメントからほぼそのまま持ってきました。違いは(1)gtest.hの代わりにpicotest.hをインクルードしている点、(2)main関数でのtesting::InitGoogleTestの呼び出しが無い点、の2つのみです。逆にこの2点を修正すればpicotestからgoogle testに乗り換えることが可能です。
フィクスチャを使ったテストも、google testっぽく書けます。
template <typename E> // E is the element type. class Queue { public: Queue(); void Enqueue(const E& element); E* Dequeue(); // Returns NULL if the queue is empty. size_t size() const; ... }; class QueueTest : public ::testing::Test { protected: virtual void SetUp() { q1_.Enqueue(1); q2_.Enqueue(2); q2_.Enqueue(3); } // virtual void TearDown() {} Queue<int> q0_; Queue<int> q1_; Queue<int> q2_; }; TEST_F(QueueTest, IsEmptyInitially) { EXPECT_EQ(0, q0_.size()); } TEST_F(QueueTest, DequeueWorks) { int* n = q0_.Dequeue(); EXPECT_EQ(NULL, n); n = q1_.Dequeue(); ASSERT_TRUE(n != NULL); EXPECT_EQ(1, *n); EXPECT_EQ(0, q1_.size()); delete n; n = q2_.Dequeue(); ASSERT_TRUE(n != NULL); EXPECT_EQ(2, *n); EXPECT_EQ(1, q2_.size()); delete n; }
対応しているアサーション
マクロ | 式 |
ASSERT_TRUE(cond) | cond==true |
ASSERT_FALSE(cond) | cond==false |
ASSERT_EQ(expected, actual) | expected == actual |
ASSERT_NE(expected, actual) | expected != actual |
ASSERT_LT(expected, actual) | expected < actual |
ASSERT_GT(expected, actual) | expected > actual |
ASSERT_LE(expected, actual) | expected <= actual |
ASSERT_GE(expected, actual) | expected >= actual |
ASSERT_STREQ(expected_str, actual_str) | expected_str == actual_str(C文字列の比較) |
ASSERT_STRNE(expected_str, actual_str) | expected_str != actual_str(C文字列の比較) |
ASSERT_STRCASEEQ(expected_str, actual_str) | expected_str == actual_str(C文字列/大小文字を同一視) |
ASSERT_STRCASENE(expected_str, actual_str) | expected_str != actual_str(C文字列/大小文字を同一視) |
ASSERT_FLOAT_EQ(expected, actual) | expected == actual |
ASSERT_DOUBLE_EQ(expected, actual) | expected != actual |
ASSERT_FLOAT_NE(expected, actual) | expected == actual |
ASSERT_DOUBLE_NE(expected, actual) | expected != actual |
すべてのマクロに対して、失敗するとテストケースを即座に抜けるASSERT_XXと、テストを続行するEXPECT_XXが用意されています。
できないこと
あくまで小規模コードをさくっとテストしたい場合を想定しているので、以下のような機能には対応していません。
あと、google test「っぽく」書けるとは言え、同じ挙動を保障するようなものでは無いことは一応書いておきます。
*1:google testはfused-src/以下に巨大な.ccと.hがあり、こいつらをプロジェクトに放り込めばリンクは不要になりますが、やっぱり個人的には面倒
*2:Boost.Test(boost/test/included以下)とか、CATCH(https://github.com/philsquared/Catch)とか