c++ unit testing check output is correct
Asked Answered
P

2

8

If I want to write my own test.cpp that checks if another .cpp file is outputting the way I want it to output, is there anyway to do it without explicitly printing it?

In other words, is there anything such as

assert(output_of_file_being_tested, "this is the correct output");

where output_of_file_being_tested is something that's supposed to be "cout"ed.

Pretonic answered 28/10, 2016 at 3:52 Comment(2)
You can do something similar to this: #10150968Doerrer
Code is more testable if you avoid writing to things like std::cout directly and write to std::ostream& references. Then the testing framework can pass in std::ostringstream objects while the application passes in std::cout.Zelma
L
9

The solution is not to hard-code the output stream. Pass a reference to std::ostream to your code somehow, and use std::stringstream to collect the output in test environment.

For example, this is the content of your "another .cpp" file:

void toBeTested(std::ostream& output) {
        output << "this is the correct output";
}

So in your production/release code you may pass std::cout to the function:

void productionCode() {
        toBeTested(std::cout);
}

while in the test environment you may collect the output to a sting stream and check it for correctness:

// test.cpp
#include <sstream>
#include <cassert>

void test() {
        std::stringstream ss;
        toBeTested(ss);
        assert(ss.str() == "this is the correct output");
}
Loblolly answered 28/10, 2016 at 4:17 Comment(0)
P
0

In addition to Sergey's great answer above, you may choose to have std::cout as a default parameter.
So, if you have a code:

// Only need console output
using std::cout;
...
void toBeTested()
{
    cout << "This is the correct output.";
}

And it is used (or may be frequently used in the future) in many places:

int main()
{
    ...
    toBeTested();
    ...
    toBeTested();
    ...
    // And so on...
    return 0;
}

In order to avoid breaking a lot of code and maintaining a simple interface,
you can convert the above function to:

using std::cout;
...
void toBeTested(std::ostream& cout = std::cout)
{
    cout << "This is the correct output.";
}

And your main does not need to be touched.
Note that cout of the function now overshadows cout of the global scope. Therefore, this cout can be any output stream, and does not interfere with the global cout.

And now you can test this as above!

#include <sstream>
#include <cassert>

...

void testMyFunctionDisplay()
{
    // Arrange
    std::ostringstream output_buffer;

    // Act
    toBeTested(output_buffer);

    // Assert
    assert(output_buffer.str() == "This is the correct output.");
}

However. it is not necessary to make every function in this way.


It is useful if we want to redirect that function's output to other output streams:

  • Stringstreams: If you want to use the output somewhere, perhaps for testing the module, or for other purposes in the program.
  • Files: If you want to maintain the output even after the program termination.
Peen answered 17/12, 2019 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.