4

So, I have a class that prints messages to cout and cerr. Sadly, refactoring it to use logging is out of the question. In my tests, I would like to capture both cout and cerr like it is described in this answer. In case the tests succeed, I really do not care what is printed. However, if the tests fail, I would like to see the output. So, what I want is something akin to:

TEST(ook, eek)
{
  // Capture cout.
  std::stringstream buffer;
  std::streambuf *sbuf = std::cout.rdbuf();
  std::cout.rdbuf(buffer.rdbuf());

  // Do test things:
  auto ret = my_weird_function(some, weird, parameters);
  EXPECT_TRUE(ret);

  // Revert the capture.
  std::cout.rdbuf(sbuf);

  // Only print if things have gone wrong...
  if (ERROR) 
  {
     std::cout << buffer.str() << std::endl;
  }
}

Clearly, I could use a fixture and the SetUp/TearDown methods for this but am still missing the failure check.

Community
  • 1
  • 1
Sardathrion - against SE abuse
  • 17,269
  • 27
  • 101
  • 156

2 Answers2

3

You need to implement a custom test listener, and use it. You can take a look how I implemented my custom listener here.

In your case, if you just want to print the error messages, and nothing else, then something like this should work :

#include "gtest/gtest.h"

class MyTestPrinter : public ::testing::EmptyTestEventListener
{

    virtual void OnTestEnd( const ::testing::TestInfo& test_info )
    {
        if ( test_info.result()->Failed() )
        {
           std::cout << test_info.test_case_name() << "   failed   " << test_info.name() << std::endl;
        }
    }
};
Community
  • 1
  • 1
BЈовић
  • 62,405
  • 41
  • 173
  • 273
3

This is what I came up with using BЈовић's answer.

class TestOOK : public ::testing::Test
{
    protected:

        virtual void SetUp()
        {
            buffer.str( std::string() ); // clears the buffer.
            sbuf = std::cout.rdbuf();
            std::cout.rdbuf( buffer.rdbuf() );
        }

        virtual void TearDown()
        {
            std::cout.rdbuf( sbuf );
            const ::testing::TestInfo* const test_info =
                ::testing::UnitTest::GetInstance()->current_test_info();
            if ( test_info->result()->Failed() )
            {
                std::cout << std::endl << "Captured output from " 
                    << test_info->test_case_name()
                    << " is:"
                    << std::endl
                    << buffer.str()
                    << std::endl;
            }
        }

        std::stringstream buffer;
        std::streambuf* sbuf;
};
Community
  • 1
  • 1
Sardathrion - against SE abuse
  • 17,269
  • 27
  • 101
  • 156