c++ unit testing check output is correct - c++

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.

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");
}

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.

Related

Copy all std::cout messages to log file? [duplicate]

I need redirect the copy of std::cout to the file. I.e. I need see the output in console, and in file. If I use this:
// redirecting cout's output
#include <iostream>
#include <fstream>
using namespace std;
int main () {
streambuf *psbuf, *backup;
ofstream filestr;
filestr.open ("c:\\temp\\test.txt");
backup = cout.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
cout.rdbuf(psbuf); // assign streambuf to cout
cout << "This is written to the file";
cout.rdbuf(backup); // restore cout's original streambuf
filestr.close();
return 0;
}
then I write string to the file, but I see the nothing in console. How can I do it?
The simplest you can do is create an output stream class that does this:
#include <iostream>
#include <fstream>
class my_ostream
{
public:
my_ostream() : my_fstream("some_file.txt") {}; // check if opening file succeeded!!
// for regular output of variables and stuff
template<typename T> my_ostream& operator<<(const T& something)
{
std::cout << something;
my_fstream << something;
return *this;
}
// for manipulators like std::endl
typedef std::ostream& (*stream_function)(std::ostream&);
my_ostream& operator<<(stream_function func)
{
func(std::cout);
func(my_fstream);
return *this;
}
private:
std::ofstream my_fstream;
};
See this ideone link for this code in action: http://ideone.com/T5Cy1M
I can't currently check if the file output is done correctly though it shouldn't be a problem.
You could also use boost::iostreams::tee_device. See C++ "hello world" Boost tee example program for an example.
Your code does not work, because it is the streambuf that determines where the output written to a stream end up, not the stream itself.
C++ does not have any streams or streambufs that support directing the output to multiple destinations, but you could write one yourself.

Checking printf output in CppUnit

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?
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";
}

Strange behavior of stringstream passed by reference

For a project, I'd like to use stringstream to carry on data. To achieve this goal, I have to pass some stringstream as parameter to some function, but when I output the stringstreams, I see something like an address.
The code :
#include <iostream>
#include <sstream>
void doStuff(const std::iostream& msg)
{
std::cerr << msg << std::endl;
}
int main(void)
{
doStuff(std::stringstream("av"));
}
The output is :
0xbff4eb40
Can someone explains why I get an address when passing an rvalue ?
And why can't I pass a stringstream by value ?
You probably want to access the string on which the stringstream is storing its data:
void doStuff(const std::stringstream& msg)
{
std::cerr << msg.str() << std::endl;
}
What is happening in your code is that iostreams contain a void* operator which returns 0 if the stream contains any error or has reached EOF, and another value otherwise. This is usefull for error checking.
When you try to write you stream to std::cerr, the compiler realizes that the stream can be converted to a void* using that operator, and that a void* can be written to a ostream(the operator<< has been defined), and therefore uses it.
Note that i changed the method's signature so that it receives an std::stringstream as an argument, since std::iostream::str is not defined(this method is only available on string streams).
You get an address because it (like other streams) has a conversion to void * (which is primarily useful as a Boolean, to see whether reading/writing the stream has failed).
You can't pass it by value, because streams (again, in general, not just stringstreams) don't support copying and/or assigning.
To print the content of the stream, you could do something like:
void dostuff(std::iostream &msg) {
std::cerr << msg.rdbuf() << "\n";
}
Edit: Here's a complete demo program:
#include <iostream>
#include <sstream>
void show(std::ostream &os) {
std::cout << os.rdbuf() << "\n";
}
int main(){
std::stringstream test("whatever");
show(test);
return 0;
}
When I execute it, the output I get is the expected "whatever".

just want to know whether there is a possible data loss?

I have written a piece of code which writes either to console or to a file depending upon the boolean value set by user.
The code looks like this.
#include <iostream>
#include <fstream>
int main()
{
bool bDump;
std::cout<<"bDump bool"<<std::endl;
std::cin>>bDump;
std::ostream* osPtr;
std::ofstream files;
if(bDump)
{
files.open("dump.txt");
osPtr = &files;
}
else
{
osPtr = &std::cout;
}
std::ostream& stream = *osPtr;
stream<<"hello";
if(bDump)
{
files.close();
}
return 0;
}
Here I am creating a std::ostream pointer and depending upon boolean value I am assinging address of either an ofstream object or std::cout. My only concern here whether the file operation like open or close are done properly or not. As I am new to c++ please help me out. Also point out if any bad programming practice is being followed here.
Its correct and works.
The main thing I would do differently is not to explicitly call close() as this is done automatically by the destructor.
You can simplify your code slightly (and get rid of the pointer) with the ternary operator;
#include <iostream>
#include <fstream>
int main()
{
bool bDump;
std::cout << "bDump bool"<<std::endl;
std::cin >> bDump;
std::ofstream files;
std::ostream& stream = (bDump) ? (files.open("dump.txt"), files)
: std::cout;
stream<<"hello";
}
There's no potential leak. However, if an exception is thrown by
stream<<"hello";
then
files.close();
will never be called, but for your specific example of code there's no concern. ofstream's destructor happens to call close() for you.
You did everything fine, but there is no need for the close() at the end, because in C++ we rely on destructors to clean up for us, and std::ofstream has one which closes the file automatically.
You can also omit the return 0; statement at the bottom of main() in C++: 0 (success, really) will be returned by default.

Unit testing a functions whose purposes is side effects

How would you unit test do_int_to_string_conversion?
#include <string>
#include <iostream>
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) {
case 1:
s="1";
break;
case 2:
s="2";
break;
default:
s ="Nix";
}
}
int main(int argc, char** argv){
std::string little_s;
do_int_to_string_conversion(1, little_s);
do_int_to_string_conversion(2, little_s);
do_int_to_string_conversion(3, little_s);
}
Instead of worrying about how to test the function as it stands, I'd redesign the function to work a bit more sensibly, and test the re-designed version instead.
Right now, the function seems to have three separate (and only slightly related) responsibilities: do a conversion, modify an externally supplied string, and write some data to a stream. The stream to which it writes (std::cout) is also hard-coded -- a problem waiting to happen (e.g., conversion to a GUI environment is likely to be non-trivial).
I'd start by 1) splitting it up into logical functions, and 2) supplying the stream as a parameter.
std::string convert_int(int val) {
switch (val) {
case 1: return "1";
case 2: return "2";
default: return "Nix";
}
}
std::ostream &write_string(std::ostream &os, std::string const &s) {
return os << s;
}
I haven't included anything to (specifically) modify an externally supplied string -- obviously you can assign the return value from convert_int as you see fit, and the value of the string that was passed in wasn't being used anyway.
Truthfully, write_string is a good candidate to be eliminated entirely, but since you had that basic kind of capability, we'll retain it for the moment. Testing these is relatively simple -- for convert_int, we look at the string it returns, and compare to what we expect. For write_string, we can pass a stringstream instead of a normal ostream -- then we can use .str() to get that result as a string, and (again) compare to what we expect.
I assume this is just an example. Why can't you assert on the value of little_s after each call?
do_int_to_string_conversion(1, little_s);
assert_are_equal("1", little_s);
If you really need to ensure that the output has been written, you need to break your dependency on std::cout and use another std::ostream during tests.
This might be as simple as a global variable:
#if PRODUCTION
std::ostream my_output = std::cout;
#else
std::ostream my_output = std::ostringstream;
#endif
void setup()
{
my_output = std::ostringstream;
}
void print_hello()
{
my_output << "hello";
}
void test_hello_was_printed()
{
print_hello();
ASSERT("hello" == my_output.str());
}
Or something similar to that effect.
I'd change do_int_to_string_conversion so that it does just one thing (convert the in to a string).
void do_int_to_string_conversion(int i, std::string& s) {
switch(i) { ... }
}
This has no side effects, so you can write a simple unit test that verifies the output (s).
If I needed a function that printed the result of the conversion, I'd put that in a separate function, and I'd parameterize the output stream.
void output_int(int i, ostream &stream) {
std::string s;
do_int_to_string_conversion(i, s);
stream << s;
}
To unit test that, I'd pass in a std::stringstream object and check the result.
You can use something like Expect to pass it some input and verify that its output is what it should be.