2

Let's say I have a simple HelloWorld class with a hi() method with the following single line of code:

void HelloWorld::hi(){
    printf("Hi!\n");
}

Now let's say I want to test that method with CppUnit.

void HelloWorldTests::testHi() {
    HelloWorld hw;
    hw.hi(); // <------ ????
    // <------ ?????
    CPPUNIT_ASSERT(/*????*/);
}

How would I catch the output of the hi() method so that I can compare it to a fixed value in CppUnit?

alexandernst
  • 14,352
  • 22
  • 97
  • 197
  • There is no output of `hi()`. Do you want to catch `"Hi\n"`? – herohuyongtao Oct 27 '14 at 00:18
  • @herohuyongtao Yes, that is correct. I want to catch the `Hi\n` so I can compare it. – alexandernst Oct 27 '14 at 00:19
  • @herohuyongtao I'd rather avoid having to change all methods in the project. Isn't there a way to catch the output? – alexandernst Oct 27 '14 at 00:20
  • possible duplicate of [How to test code that writes to stdout?](http://stackoverflow.com/questions/26144614/how-to-test-code-that-writes-to-stdout) – Deduplicator Oct 27 '14 at 00:21
  • It's CUnit instead of CPPUnit, but otherwise the same question. – Deduplicator Oct 27 '14 at 00:21
  • That answer is rubbish. I refuse to believe there isn't anything better :/ – alexandernst Oct 27 '14 at 00:26
  • @Deduplicator not quite the same, C++ is nowhere near C – alexandernst Oct 27 '14 at 00:29
  • 1
    @alexandernst Calling a +12 answer rubbish while using `printf` in c++ and giving yourself troubles is ... courageous. And it's actually a proper answer for a `printf`. – luk32 Oct 27 '14 at 00:29
  • @luk32 Since when `printf` is not recommended in C++? Maybe I missed something here... In this example (iirc) `std::cout` and `printf` will behave exactly the same, so what is your point? – alexandernst Oct 27 '14 at 01:15
  • @alexandernst Since `std::cout`. My point is, for example, `cout` can be easily swapped for something else. There are multiple and easy ways to solve your problem just by using `cout`. That is why I said you give the problem to yourself, and you reject the answer for it. `printf` is harder to "hack". – luk32 Oct 27 '14 at 01:42

1 Answers1

3

There is no standard way to capture the output to stdout within a program. You can redirect the output to stdout to a file using freopen(filename, "w", stdout) and then compare the content of the file. The main problem with this approach is that there is no standard approach to restore the original destination.

I'd recommend changing the code to use std::cout instead as this can be easily redirected to a suitable std::streambuf, e.g., an std::stringbuf, using the rdbuf() member. The original stream buffer can be kept and restored once the method writing to std::cout is done:

struct HelloWorld {
    void hi() {
        std::cout << "hi";
    }
};

bool test_hi() {
    std::ostringstream out;
    std::streambuf* orig_buf(std::cout.rdbuf(out.rdbuf()));

    HelloWorld hw;
    hw.hi();

    std::cout.rdbuf(orig_buf);

    return out.str() == "hi";
}
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • I don't know CppUnit but the approach posted should work rather independent of the test framework. It may be refined to automatically install/uninstall the stream buffer and avoid the string stream using a custom comparing stream buffer but the fundamental approach won't change. – Dietmar Kühl Oct 27 '14 at 00:34