僕のお仕事はもちろんプログラマなんですけど、お客様の手元に届くプロダクトに直接携わることはそんなになくて、どちらかといえば前線で奮闘する連中のサポート/後方支援に近いお仕事が多いかな。新規採用となるライブラリの事前調査やドキュメント/サンプル書いたりとか。「LinuxとWindowsで使えるUnit Test Frameworkを見繕ってほしい」との依頼を受けて、いつものように事前調査と試運転を兼ねたサンプル・コードの実装に着手した次第。
前準備
googletest(Google Test)はGoogle Codeから入手できます。2012/07時点ではversion 1.6.0: gtest-1.6.0.zipが最新のようです。テキトーなディレクトリにダウンロード/展開し、ライブラリを作ります。
Linux/g++だと:
% unzip gtest-1.6.0.zip % cd gtest-1.6.0 % mkdir lib % g++ -c -Iinclude -I. src/gtest-all.cc % ar -rv lib/libgtest.a gtest-all.o
Windows/VC++ならzipを展開したディレクトリで:
> mkdir lib > cl -c -EHsc -MD -Iinclude -I. src\gtest-all.cc > lib -out:lib\gtest.lib gtest-all.obj > cl -c -EHsc -MDd -Iinclude -I. src\gtest-all.cc > lib -out:lib\gtest-md.lib gtest-all.obj
あとは必要に応じてinclude/libをどこぞにコピーして準備完了です。
テスト対象として、固定長配列を使った「StackCalc:スタック電卓」を用意しました。
/* スタック電卓 */ #ifndef STACKCALC_H_ #define STACKCALC_H_ #include <memory> #include <stdexcept> template<typename T> class StackCalc { public: StackCalc(int capacity); ~StackCalc(); // overflow/underflow時に例外をthrowする/しない StackCalc& throw_exception(bool =true); // stackは空? bool empty() const; // stackは満杯? bool full() const; // 要素数 int size() const; // 許容量 int capacity() const; /* スタックを |...> で表す。 * |←尻...頭→> */ // |... z y x> ⇒ |... z y x v> StackCalc& push(T v); // |... z y x> ⇒ |... z y> StackCalc& pop(); StackCalc& top(T& v); T top() const; // |... z y x> ⇒ |... z x y> StackCalc& swap(); // |... z y x> ⇒ |... z y x x> StackCalc& dup(); // |... z y x> ⇒ |> StackCalc& clear(); // |... z y x> ⇒ |... z y+x> StackCalc& add(); // |... z y x> ⇒ |... z y-x> StackCalc& sub(); // |... z y x> ⇒ |... z y*x> StackCalc& mul(); private: bool assert_not_empty() const; std::unique_ptr<T[]> stack_; int size_; int capacity_; bool throw_exception_; }; template<typename T> StackCalc<T>::StackCalc(int capacity) : capacity_(capacity), size_(0), throw_exception_(false) { stack_ = std::unique_ptr<T[]>(new T[capacity]); } template<typename T> StackCalc<T>& StackCalc<T>::throw_exception(bool th) { throw_exception_ = th; return *this; } template<typename T> bool StackCalc<T>::assert_not_empty() const { if ( !empty() ) return true; if ( throw_exception_ ) { throw std::domain_error("stack empty"); } return false; } template<typename T> StackCalc<T>& StackCalc<T>::pop() { if ( assert_not_empty() ) { --size_; } return *this; } ... #endif
使い方はこんなカンジ:
#include <iostream> #include "StackCalc.h" using namespace std; int main() { int result; StackCalc<int> sc(5); // スタック長:5 // 1+2=? sc.push(1).push(2).add().top(result); // 1と2を足す cout << result << endl; // (1+2)x(3+4)=? sc.push(1).push(2).add() // 1と2を足して .push(3).push(4).add() // 3と4を足して .mul().top(result); // 掛ける cout << result << endl; }