Home » hephaestus » Using pexpect to automate Python scripts

As part of my hephaestus project, I have been using pexpect to automate my integration testing. This is a rough and ready method which allows for rapid development. More rigorous unit testing is conducted in the Pythonic way: self-contained in each module.

Let’s first look at this short script, demo.py:

#!/usr/bin/env python
import pexpect
import sys
# Spawn the process we wish to automate
child = pexpect.spawn('python hephaestus.py')
# Tell pexpect to write to stdout, else point to a file
child.logfile = sys.stdout
# Don't echo the sendline commands as they'll be written to stdout anyway
child.setecho(False)
# When we see the process emit 'hephaestus>'...
child.expect('hephaestus>')
# ...write 'config' to its stdin
child.sendline('config')
# Wait for new prompt...
child.expect('hephaestus\(config\)#')
# ...issue next command
child.sendline('load')
# ...and so on...
child.expect('load:\r\n')
child.sendline('1')
child.expect('hephaestus\(config\)#')
child.sendline('exit')
child.expect('hephaestus>')
child.sendline('scan')
child.expect('hephaestus\(scan\)>')
child.sendline('autoscan')
child.expect('hephaestus\(scan\)>')
child.sendline('exit')
child.expect('hephaestus>')
child.sendline('exit')

Now, what does it do? It simulates user input to the program hephaestus.py, and the resultant output looks like this:

niall@concrescence ~/Code/CSC3002/HEAD/code $ ./demo.py
Welcome to hephaestus, the stateless firewall configuration parser for JunOS.

Command help with 'help' or '?', auto-completion is available, shell commands available by prefixing with '!', eg: '!ls -lf'

hephaestus> config
You are now in configuration mode, different commands are available.
Command help with 'help' or '?'

hephaestus(config)# load
The following configuration files are available:
0 acme.conf
1 acmenew.conf
2 acmefoo.conf
Enter the number of the file you wish to load:
1
hephaestus(config)# exit

hephaestus> scan
You are now in scan mode, different commands are available.
Command help with 'help' or '?'

hephaestus(scan)> autoscan
Using current configuration:
The wonderful and amazing network known as ACME, AS65000
Scanning for routers in prefixes 172.16.100.0/28 192.168.88.0/28 using SNMP community $nMpC0mmun1ty
172.16.100.2    : connecting...
172.16.100.1    : connecting...
172.16.100.3    : connecting...
172.16.100.4    : connecting...
172.16.100.5    : connecting...
172.16.100.6    : connecting...
172.16.100.8    : connecting...
172.16.100.7    : connecting...
172.16.100.9    : connecting...
172.16.100.10   : connecting...
172.16.100.10   : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.10 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.2    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.2 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.3    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.3 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.5    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.5 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.6    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.6 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.1    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.1 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.8    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.8 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.9    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.9 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.4    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.4 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.7    : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.7 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.8    : waiting...
172.16.100.5    : waiting...
172.16.100.4    : waiting...
172.16.100.1    : waiting...
172.16.100.10   : waiting...
172.16.100.2    : waiting...
172.16.100.3    : waiting...
172.16.100.6    : waiting...
172.16.100.9    : waiting...
172.16.100.7    : waiting...
172.16.100.5    : is a Juniper MX960 Internet Backbone Router
172.16.100.11   : connecting...
172.16.100.6    : is a Juniper MX480 Midplane Internet Backbone Router
172.16.100.2    : is a Juniper MX960 Internet Backbone Router
172.16.100.12   : connecting...
172.16.100.4    : is a Juniper MX960 Internet Backbone Router
172.16.100.13   : connecting...
172.16.100.14   : connecting...
172.16.100.3    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.1    : connecting...
172.16.100.7    : is a Juniper MX960 Internet Backbone Router
192.168.88.2    : connecting...
172.16.100.9    : is a Juniper MX960 Internet Backbone Router
192.168.88.3    : connecting...
172.16.100.11   : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.11 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.13   : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.13 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.12   : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.12 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.14   : executing snmpget -v 2c -c $nMpC0mmun1ty 172.16.100.14 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.1    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.1 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.11   : waiting...
172.16.100.13   : waiting...
172.16.100.12   : waiting...
172.16.100.14   : waiting...
192.168.88.2    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.2 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.1    : waiting...
172.16.100.11   : is a Juniper MX960 Internet Backbone Router
192.168.88.4    : connecting...
172.16.100.10   : is a Juniper MX960 Internet Backbone Router
192.168.88.5    : connecting...
192.168.88.3    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.3 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.2    : waiting...
172.16.100.14   : is a Juniper MX960 Internet Backbone Router
192.168.88.6    : connecting...
192.168.88.1    : is a Juniper MX480 Midplane Internet Backbone Router
172.16.100.1    : is a Juniper MX960 Internet Backbone Router
192.168.88.7    : connecting...
192.168.88.8    : connecting...
192.168.88.3    : waiting...
192.168.88.2    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.9    : connecting...
192.168.88.3    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.10   : connecting...
192.168.88.4    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.4 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.5    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.5 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.6    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.6 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.7    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.7 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.4    : waiting...
192.168.88.5    : waiting...
192.168.88.9    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.9 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.6    : waiting...
192.168.88.7    : waiting...
172.16.100.13   : is a Juniper MX960 Internet Backbone Router
192.168.88.11   : connecting...
192.168.88.9    : waiting...
192.168.88.10   : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.10 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.6    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.12   : connecting...
192.168.88.5    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.9    : is a Juniper MX960 Internet Backbone Router
192.168.88.13   : connecting...
192.168.88.14   : connecting...
192.168.88.10   : waiting...
192.168.88.7    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.11   : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.11 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.12   : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.12 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.11   : waiting...
192.168.88.14   : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.14 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.13   : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.13 1.3.6.1.4.1.2636.3.1.2.0
172.16.100.12   : is a Juniper MX960 Internet Backbone Router
192.168.88.12   : waiting...
192.168.88.14   : waiting...
192.168.88.13   : waiting...
192.168.88.12   : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.10   : is a Juniper MX960 Internet Backbone Router
192.168.88.4    : is a Juniper MX480 Midplane Internet Backbone Router
192.168.88.14   : is a Juniper MX480 Midplane Internet Backbone Router
172.16.100.8    : is not a router
192.168.88.13   : is a Juniper MX960 Internet Backbone Router
192.168.88.8    : executing snmpget -v 2c -c $nMpC0mmun1ty 192.168.88.8 1.3.6.1.4.1.2636.3.1.2.0
192.168.88.8    : waiting...
192.168.88.11   : is not a router
192.168.88.8    : is not a router

Scanned      : 28 IPs
Found        : 25 routers
Wall time    : 18.874931097 seconds
hephaestus(scan)> exit

hephaestus> exit
niall@concrescence ~/Code/CSC3002/HEAD/code $