Continuous Integration of a Django Project
I have developed a CMS for managing this website and for use as a component in any other Django projects that needs it. The CMS (I called it Mingus in the tradition of using the names of jazz musicians) has unit tests for functionality and regression testing but up until now I had to run the tests manually. I've decided that it is time to sort out continuous integration (CI).
The first challenge is to pick the CI platform. There are several possibilities but after looking through them all I settled on Bitten, mostly because I already have a Trac server for the project and Bitten plugs straight in.
Installation
The instructions on the Bitten site are simple to follow and worked without issues. The process is:
$ sudo python setup.py install
$ python setup.py test
[components]
bitten.* = enabled
$ trac-admin /path/to/projenv upgrade
$ trac-admin /path/to/projenv permission add build_slave BUILD_EXEC
$ trac-admin /path/to/projenv permission add anonymous BUILD_VIEW
Operation
After that the only thing remaining is to write some recipes and commit a new revision to ensure everything works. Here is the recipe I use to checkout the latest revision and run the unit tests:
<build xmlns:sh='http://bitten.edgewall.org/tools/sh'
xmlns:svn='http://bitten.edgewall.org/tools/svn'
xmlns:python='http://bitten.edgewall.org/tools/python'>
<step id='checkout'>
<svn:checkout url='http://path.to.repos'
path='${path}' username='user'
password='password'/>
</step>
<step id='tests'>
<python:exec file='manage.py' args='test -v0'/>
</step>
<step id='coverage'>
<python:exec file='/usr/local/bin/figleaf' args='-i manage.py test -v0'/>
<python:exec file='fix_fig.py'/>
<python:figleaf summary=".figleaf" include="*.py" />
</step>
</build>
$ bitten-slave --work-dir=/tmp --build-dir=mingus \
-u build-slave -p build-pass http://path.to.trac/builds
Measuring Test Coverage
The recipe above includes a step to measure test code coverage. Although this is a useful measurement it shouldn't become a primary measure of whether your tests are sufficient.
I initially struggled to get Bitten to parse my figleaf results correctly. I worked out that this is due to figleaf's output having slightly weird paths for the referenced files. I've written a script to fix the paths in the output file and attached it below.
#! /usr/bin/env python
import cPickle as pickle
import os.path
f = open('.figleaf')
d = pickle.load(f)
f.close()
d2 = {}
for key,val in d.items():
if key.endswith('.py'):
key = os.path.normpath(key)
d2[key] = val
f = open('.figleaf', 'w')
pickle.dump(d2, f)
f.close()


