15

Like in:

void f()
{
  cout << "blah" << endl;
}

BOOST_AUTO_TEST_CASE(f)
{
  f();
  // This would be a beauty
  // BOOST_CHECK_PROGRAM_OUTPUT_MATCH("blah");
}
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
rturrado
  • 7,699
  • 6
  • 42
  • 62

2 Answers2

26

Yes, you can do it by redirecting std::cout to a boost::test_tools::output_test_stream, which provides special methods to compare the output. To make sure std::cout is always restored correctly, you can use a custom struct, like shown in the following example.

#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>
#include <iostream>

BOOST_AUTO_TEST_SUITE( TestSuite1 )

struct cout_redirect {
    cout_redirect( std::streambuf * new_buffer ) 
        : old( std::cout.rdbuf( new_buffer ) )
    { }

    ~cout_redirect( ) {
        std::cout.rdbuf( old );
    }

private:
    std::streambuf * old;
};

BOOST_AUTO_TEST_CASE( test1 )
{
    boost::test_tools::output_test_stream output;
    {
        cout_redirect guard( output.rdbuf( ) );

        std::cout << "Test" << std::endl;
    }

    BOOST_CHECK( output.is_equal( "Test\n" ) );
}

BOOST_AUTO_TEST_SUITE_END()
Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • Beautiful, Space_C0wb0y. So let's see if I get what's going on there. In cout_redirect constructor we set cout stream buffer to boost output test stream buffer. And we save old cout stream buffer. Whatever is written from there on in cout, and until cout_redirect is destroyed, is actually written into boost stream buffer. When cout_redirect gets destroyed, we reset cout stream buffer to its previous value, and we have a boost stream buffer with all the program output we wanted. – rturrado Mar 23 '11 at 13:06
  • I guess, what we could also do to is to set boost stream buffer to cout stream buffer. In that case, we would still get output in cout, and we could be able to check it using boost stream. – rturrado Mar 23 '11 at 13:09
  • 1
    @rturrado: I do not know if this would work as expected. Once `std::cout` is flushed, the buffer will be empty, and the `output_test_stream` would not be able to check the contents later. – Björn Pollex Mar 23 '11 at 13:12
4

I have followed @Björn Pollex 's answer for some days. But one day I found that it's not necessary to do it like that. Just use boost::test_tools::output_test_stream.

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>

BOOST_AUTO_TEST_SUITE(TestSuite1)

BOOST_AUTO_TEST_CASE(test1)
{
    boost::test_tools::output_test_stream output;
    output << "Test";

    BOOST_CHECK(output.is_equal("Test"));
}

BOOST_AUTO_TEST_SUITE_END()

For more information, read the official documentation.

Hank
  • 517
  • 2
  • 13
  • 3
    in your example, you can only test for `operator<<` implementations. The OP wants to explicitly capture `std::cout`, therefore @Björn Pollex's answer is correct. However, if any stream is required, not just `std::cout`, then you are right about just using `output_test_stream`. – David Bellot Aug 21 '19 at 23:51