Google Testが取り持つ縁で、このようなエントリに出会いました。
おぉ。Google Testで標準出力をテストする。ナイス!
…。でも。
名前空間を「internal」にしてあるように、そこは触れてはいけない空間ではないかという雰囲気です。ドキュメントに載ってないのもそのためかと。
とはいえ。Google Testで標準出力の内容をテストするというアイディアをほっとくのはもったいないので。記憶を頼りに標準出力について調べてみました。
と、いうわけで。仕様的にも問題ない操作で標準出力の内容を取得する方法です。
C++のストリームはstreamとstreambufからできている
C++のストリームは2段構えで、ユーザ側のインタフェースのstreamクラスと、デバイス側のインタフェースのstreambufクラスからなっています。実際にはそれぞれに対応する派生クラスが組になってストリームを実現しています。詳しくは「<iostream> - C++ Reference」などを参照してみてください。
具体的には。fstream
にはfilebuf
が、stringstream
にはstringbuf
が対応しています。標準入力・標準出力のばあいは実装が隠されているので具体的にこれとは指し示せませんが、標準入力・標準出力にも対応するstreambuf
の派生クラスがあります。
で。
ストリームクラスには[http://cplusplus.com/reference/iostream/ios/rdbuf/:title=rdbuf]
という関数があって、そのストリームが扱っているstreambuf
(の派生クラスのインスタンス)を直接操作することができます。このうち引数を指定できる形式のほうを使うと、引数で与えたstreambuf
をストリームに関連付けることができます。戻り値は現在関連付けられているstreambuf
です。
これらをふまえて。
std::cout
のstreambuf
をstringstream
のstreambuf
であるstringbuf
にすげかえてみます。
実装。
#include <gtest/gtest.h> #include <iostream> #include <sstream> TEST(StdoutTest, test1) { std::stringbuf buf; // stringstream用のstreambuf std::streambuf* prev = std::cout.rdbuf(&buf); // streambufをすげかえる std::cout << "hoge" << std::flush; // コンソールでなくbufに出力される std::cout.rdbuf(prev); // streambufを元に戻す ASSERT_EQ("hoge", buf.str()); // 結果をテスト }
実行結果。
$ g++ -o sample1 sample1.cpp gtest/gtest-all.cc gtest/gtest_main.cc $ ./sample1 Running main() from gtest_main.cc [==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 test from StdoutTest [ RUN ] StdoutTest.test1 [ OK ] StdoutTest.test1 (1 ms) [----------] 1 test from StdoutTest (3 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (14 ms total) [ PASSED ] 1 test.
(コードの内容とかビルドの内容とかは「Google Testをインストール、しないですませる方法 - エンジニアのソフトウェア的愛情」なんかを見てみてください)。
無事通りました。
ためしにstd::cout
に出力する文字列をhoge
からfuga
に変えて実行してみます。
実行結果。
$ ./sample1 Running main() from gtest_main.cc [==========] Running 1 test from 1 test case. [----------] Global test environment set-up. [----------] 1 test from StdoutTest [ RUN ] StdoutTest.test1 sample1.cpp:16: Failure Value of: buf.str() Actual: "fuga" Expected: "hoge" [ FAILED ] StdoutTest.test1 (4 ms) [----------] 1 test from StdoutTest (6 ms total) [----------] Global test environment tear-down [==========] 1 test from 1 test case ran. (63 ms total) [ PASSED ] 0 tests. [ FAILED ] 1 test, listed below: [ FAILED ] StdoutTest.test1 1 FAILED TEST
ASSERT_EQ
の引数にfuga
がわたっている、つまり標準出力へ出力した内容が文字列として扱えているのがわかります。