With the first approach you can test python functions and methods internally but it can lead you to the over mocking problem. The second will limit you to test functionality exposed through your program's command line, as it will spawn a process and interact it externally.
Given that the TUIs are entrypoints to your program, it makes sense to test them in end-to-end tests, so I'm going to follow the second option. On the other hand, you may want to test a small part of your TUI in a unit test, if you want to follow this other path, I'd start with monkeypatch, although I didn't have good results with it.
def test_method(monkeypatch): monkeypatch.setattr('sys.stdin', io.StringIO('my input'))
This method is useful to test end to end functions as you need to all the program as a command line. You can't use it to tests python functions internally.
from prompt_toolkit import prompt text = prompt("Give me some input: ") with open("/tmp/tui.txt", "w") as f: f.write(text)
```python import pexpect
def test_tui() -> None: tui = pexpect.spawn("python source.py", timeout=5) tui.expect("Give me .*") tui.sendline("HI") tui.expect_exact(pexpect.EOF)
with open("/tmp/tui.txt", "r") as f: assert f.read() == "HI"
tui.expect_exact(pexpect.EOF)line is required so that the tests aren't run before the process has ended, otherwise the file might not exist yet.
timeout=5is required in case that the
pexpectinteraction is not well defined, so that the test is not hung forever.
Thank you Jairo Llopis for this solution.