eriksmartt.com>Selected Archives

Resetting a Django environment

For one of my Django-based projects, I decided to setup an automated functional-testing system using Selenium to add content to the Admin tool and verify that it works in the site. In order to use this in a "continuous-integration"-like manner, I needed a way to automate the tear-down, initialization, and setup of a fresh installation of the app.

I use a few more tricks to get this all working, but I wanted to share a couple scripts I wrote to handle the database re-initialization. I gather from some of the Django discussions that similar functionality may be working it's way into the mainline already, but for the time being, here's what I'm doing.

I broke the process into two scripts, not because it's the best thing to do, but because doing the first part as a shell script made sense, and doing the second part in Python was easier.

This first script take a brute-force approach at pulling the database settings from the project's settings.py file, and using them to delete the existing database and create a new one by driving the command-line 'mysqladmin' tool. (There's also some voodoo done elsewhere which results in the script using a different database name if it's in the testing environment, but that's for another post.)

#!/bin/bash

# Extract the user/passwd from the settings file
username=`grep DATABASE_USER settings.py | awk -F\' '{print $2}'`
password=`grep DATABASE_PASSWORD settings.py | awk -F\' '{print $2}'`
database=`grep DATABASE_NAME settings.py | awk -F\' '{print $2}'`

echo 'Clearing the database...'
echo 'y' | mysqladmin --host=localhost --user=$username --password=$password drop $database
mysqladmin --host=localhost --user=$username --password=$password create $database

echo 'Setting up the database and test account...'
./dbinit.py

echo 'Done.'
`</pre>

This second script (called 'dbinit.py', and called from the script above) uses [pexpect](http://pexpect.sourceforge.net/) (an Expect-like module for Python) to drive the 'syncdb' function of Django's manage.py tool.  When using pexpect, the thing to remember is that you have to "expect" the full, and exact string that the child process outputs.  I got hung up on this at first, which is why you'll see me using the more crude ".*" pattern below:

<pre>`
#!/usr/bin/python

import sys
import pexpect

child = pexpect.spawn('python manage.py syncdb')
child.logfile = sys.stdout

#child.expect('Would you like to create one now.*:')
child.expect('.*:')
child.sendline('yes')

child.expect('Username.*:')
child.sendline('SOMEUSERNAME')

child.expect('E-mail address:')
child.sendline('SOMEUSERNAME@foo.com')

child.expect('Password:')
child.sendline('NOTSOSECRETPASSWORD')

child.expect('Password.*:')
child.sendline('NOTSOSECRETPASSWORD')

child.expect(pexpect.EOF)

With these scripts in place, not only have I been able to setup an automated testing solution, but I also use them in early development when I'm still flushing out a data-model. This approach allows me to quickly reinitialize an environment -- although you should use with caution since it also deletes all content from the database.