0

I'm trying to make unit tests with criterion for my C++ code but I can't figure out how to test a function that only print and do not return anything. Here's what I tried:

//the function to test

#include <iostream>
#include <fstream>

void my_cat(int ac, char **av)
{
    if (ac <= 1)
        std::cout << "my_cat: Usage: ./my_cat file [...]" << std::endl;
    for (unsigned i = 1; i < ac; i += 1) {
        std::ifstream file (av[i]);
        if (file.fail()) {
            std::cout << "my_cat: ";
            std::cout << av[i];
            std::cout << ": No such file or directory" << std::endl;
        }
        else if (file.is_open()) {
            std::cout << file.rdbuf() << std::endl;
        }
        file.close();
    }
}
//the test
#include  <criterion/criterion.h>
#include  <criterion/redirect.h>

void my_cat(int ac, char **av);

Test(mycat, my_cat)
{
    char *av[] = {"./my_cat", "text.txt"};
    my_cat(2, av);
}

But now that I'm here I don't know what to use to check if the print is correct.

Biffen
  • 6,249
  • 6
  • 28
  • 36
Tsirsuna
  • 130
  • 2
  • 16
  • Question is what part of logic you wish to test? IMO main problem here is that this function should be spited into smaller pieces. After such operation having test for it will be easy. – Marek R Jan 20 '22 at 09:54
  • i see you're right – Tsirsuna Jan 20 '22 at 09:57

2 Answers2

3

With gtest, I think this can help you

testing::internal::CaptureStdout();
std::cout << "My test";
std::string output = testing::internal::GetCapturedStdout();

refer from : How to capture stdout/stderr with googletest?

long.kl
  • 670
  • 4
  • 12
1

The other answer shows how to use a googletest facility. However, in general when your code is difficult to test, then that is a code smell. Consider this simpler example:

void foo(){
    std::cout << "hello";
}

This is much easier to test when don't use std::cout directly, but pass the stream to be used as parameter:

#include <iostream>
#include <sstream>

void foo(std::ostream& out){
    out << "hello";
}
    
int main() {
    std::stringstream ss;
    foo(ss);
    std::cout << (ss.str() == "hello");
}

In general, I do not recommend to use std::cout directly for anything but small toy programs. You never know if later you want to write to a file or some other stream.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185