I have a CLI that can launch processes, especially interactive shells and waits for them, they can be closed using the same CLI. I need to create some end to end tests for it using bash but I cannot see how to simulate the execution in the terminal; the output should be sent to the process in the "foreground".
Suppose that executing my-cli start
launches a python script that start a subprocess (running an interactive shell) and waits to it.
in the testing script, exec(my-cli start)
will replace the current process with the process running python script and not the interactive shell, so I cannot interact with the interactive shell after.
I thought about using pipes, but I think something that can simulate using a terminal will be better, any ideas ?
Example:
Suppose the code of my CLI (cli.py
) is:
import subprocess
process = subprocess.Popen(['/bin/bash', '-i'], shell=False)
process.communicate()
Using expect
I don't know if it's possible to communicate with the interactive shell (/bin/bash -i
)
#!/usr/bin/expect -f
spawn python3 cli.py
#expect eof
send -- "echo $$\r"
As mentioned in a comment by Benjamin. I and many others have used expect
in this scenario. As long as you can tell the text that will be presented in the terminal then you can use the following web pages as a guide to creating an expect script.
Update based on the example provided. For this, I have a file foo.py:
import subprocess
process = subprocess.Popen(['/bin/bash', '-i'], shell=False)
process.communicate()
An expect file (expect-example.exp):
#!/usr/bin/expect
spawn python3 foo.py
expect "*bash*"
send "date\r"
send "exit\r"
interact
When I run this expect expect-example.exp
I get the following:
$ expect expect-example.exp
spawn python3 foo.py
bash-3.2$ date
Mon 3 Jun 2019 14:03:37 BST
bash-3.2$ exit
exit
$
It is worth mentioning, given that I am running a single command date
and I want to see the output from it I must include the interact
command at the end of the script. Otherwise, my expect script will exit as soon as it has sent the date command and won't wait for the response.