How to test interactive commands

This document demonstrates how to develop integration tests for interactive commands with the expect tool.

Contents:

Install the expect tool

See also: expect

First, install the expect tool:

sudo apt install expect

Choose an interactive command and prepare an expect script

See also: expect, Basic principles of using TCL-Expect scripts

Second, choose an interactive command that you want to test and prepare an expect script for it.

As an example, let’s choose juju change-user-password. On its most basic usage, this command prompts the user to type in a password. Once it receives an input, it prompts the user to type that password again and it checks whether the two inputs match.

Now, let’s prepare an expect (.exp) script to test this behavior. This can be done as shown below. The beginning and the end are always the same—we just need to edit the script body. Below we use the expect (== wait for output) and send (=send a reply to the program) keywords to simulate the behavior of the juju change-user-password command.

The expect tool provides a lot of keywords, but the expect and send keywords will suffice for most of our purposes.

#!/usr/bin/expect

# Start the interactive script:
spawn ./interactive_script.sh

# Use expect tool keywords to fill in the expect script body. 
expect "new password: " {
   send "test-password\r"
   expect "type new password again: " {
   	send "test-password\r"
   }
}

# End the expect script:
expect eof

Use the expect_that function to test the command against the script

See also: expect_that

Finally, test the command against the expect script by passing the command and the body of the script (with the quote characters escaped) as string arguments to the expect_that function, as shown below. If the test passes successfully, this should output “OK”.

The expect_that function comes with your installation of Juju.

expect_that "juju change-user-password" "
expect \"new password: \" {
	send \"test-password\r\"
	expect \"type new password again: \" {
		send \"test-password\r\"
	}
}" | check "OK"