-1

I am writing a test in pytest for a software. This test relies a lot on console output generated by the software.

The flow is something like: * start the program * send some commands to the program * wait for some output from the program * send some other commands, wait for further output

I also need to write the entire output generated to stdout, and to a file. I tried pexpect but it doesn't seem to have the capability to write to console and file.

Any other choice?

closed as off-topic by Ben Cottrell, Blrfl, gnat, ChrisF Feb 3 at 18:36

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions asking us to find or recommend tools, libraries, programming languages, resources (including books, blogs, tutorials, and examples), or projects to undertake are off-topic here as they attract opinionated answers that won't have lasting value to others. You may be able to get help in The Whiteboard, our chat room." – Ben Cottrell, Blrfl, gnat, ChrisF
If this question can be reworded to fit the rules in the help center, please edit the question.

1

The usual way to test such programs is not to intercept the input/output of the program, but to separate the core of the program from any I/O.

Instead, you define some class that manages the I/O for your program core. It could have methods like prompt_user(), log_info(), or print(). The program core depends on these methods – but not on the particular implementation that used stdin/stdout.

In your tests, you then implement and provide a mock I/O adapter. The tests can assert that the program core produced certain output and can respond with mock input. This mock adapter doesn't have to produce any real output.

This approach is related to the Onion/Hexagonal/Ports-and-Adapter architecture or the Stairway Pattern. Without such an extra I/O class there is a direct dependency from the system under test to stdin/stdout:

+-------+     +-------+
| stdio | <-- |  SUT  |
+-------+     +-------+
    ^
    |
+-------+
| tests |
+-------+

Using extra interfaces makes this more complicated, but we can break that dependency for our tests:

+-------+     +---------+     +-----------+
| stdio | <-- | default | --> |           |
+-------+     | adapter |     |           |     +-------+
              +---------+     |    I/O    | <-- |  SUT  |
              +---------+     | interface |     +-------+
              |  mock   | --> |           |
              | adapter |     |           |
              +---------+     +-----------+
                  ^
                  |
              +-------+
              | tests |
              +-------+

If you cannot modify the architecture of your program, then the best way is usually to run the program that you want to test as a separate process so that you can easily capture all I/O. You would then use Expect style software to interact with the process in an automated fashion.

Not the answer you're looking for? Browse other questions tagged or ask your own question.