0

I am learning CTest over the following code:

// A program that echoes lines on stdin back.
#include <iostream>
#include <string>

int main()
{
    std::string line;
    do
    {
        std::getline(std::cin, line);
        std::cout << line << std::endl;
    }while(! line.empty());
}

Now I need to perform a system test. How can my tests.cpp refer to standard input and output of the compiled binary? The test should obviously invoke it, produce some input and verify the output mirrors it. What's the CTest way of doing that?

My current CMakeLists.txt stanza, though probably completely irrelevant:

enable_testing()
add_executable(tests tests.cpp)
add_test(NAME Tests
         COMMAND tests)

Conclusion after reading the linked question(also closed).

  • CTest can't do that. See @Tsyvarev 's comment below on how to do it in C++ in a non-portable way.
  • There are various frameworks that can do it, my favourite was not mentioned unfortunately.
  • A simple solution would be transform the tool into a non-interactive one.
Vorac
  • 8,726
  • 11
  • 58
  • 101
  • If your module cannot be unit-tested that's just bad code tbh. You should split your code to methods that accept an `std::ostream`. Then in your unit test you can pass in an `std::stringstream` instead and check the value in there. – theWiseBro Dec 31 '21 at 04:55
  • 1
    Testing is checking if a program or its subroutine does what it is specified to do. What is your program specified to do? – Öö Tiib Dec 31 '21 at 06:21
  • 1
    CTest provides none abilities for the test itself. From the view of CTest, a test is just a binary file which can be executed. It is up to your test to communicate with the tested command line utility. Aside from using specific tools for create such tests, you could create multiprocess test using `fork`, redirect child's input and output into some parent's pipe (using `dup`) and make the child to execute your command line tool. That way, the parent can affect on the tool's input and may read from the tool's output. – Tsyvarev Dec 31 '21 at 08:34
  • 1
    `add_test` may not provide you with a platform-independent way of providing input, but you could create a function that uses `configure_file` to generate a cmake script file that uses `execute_process` to do this and check the output; you can use this script file as test command `add_test(NAME Tests COMMAND ${CMAKE_COMMAND} -D "MY_TESTED_EXECUTABLE=$" -P /path/to/generated_test_script.cmake)`. (Or maybe just hardcode everything directly instead of using a function, If you don't want to reuse this functionality.) – fabian Dec 31 '21 at 08:44

0 Answers0