I use Mercurial for all my coding projects. Today I hit upon the idea of using mercurial precommit hooks to run django tests before committing. I didn’t really expect it to be so easy
I use postgresql on the server, but I found that on win32, running tests with postgresql is excruciatingly slow.
For comparison, 23 tests with postgresql on Vista laptop take about 193 seconds (The same tests take ~14 seconds on my linux vps). With an sqlite in memory database on the same machine they take about 13.5 seconds. Moral of the story: On Windows, use sqlite in memory databases to test django apps.
Ok, so I had to figure out a way to use sqlite only for testing while using postgresql otherwise. I decided to instrument settings.py
_TEST_DB = False
if 'DJANGO_TEST_DB' in os.environ :
_TEST_DB = True
if _TEST_DB :
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = ':memory:'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
else :
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME = 'project'
DATABASE_USER = 'projectdb'
DATABASE_PASSWORD = 'dbpassword'
DATABASE_HOST = ''
DATABASE_PORT = ''
Now I thought of using the inprocess Python hooks feature of Mercurial, but it seemed to be too much of a hassle (need to have the hook script in PYTHONPATH), so I decided to write a simple command line script
import os, sys, subprocess
PROJ_DIR = r'C:\Users\Jeethu\code\project'
def main() :
proj_dir = os.path.normpath(PROJ_DIR)
os.chdir(proj_dir)
os.environ['DJANGO_TEST_DB'] = 'True'
r = subprocess.call(['python','manage.py','test'])
return r
if __name__ == '__main__' :
sys.exit(main())
Then simply add 2 lines to the .hg\hgrc file in the repo.
[hooks] precommit.tests = c:\Users\Jeethu\code\project\hooks\test_hook.py
Hopefully, this will set the incentives right for me to write more tests.
References:
The hgrc manpage
Chapter 10 of the Mercurial Book
gruszczy on March 9th, 2010 at 3:44 AM says:
Nice. I would like to run this as postcommit and send mails to our mailing list with errors. This won’t make commits long (we have quite long tests) but everyone will see, that someone screwed the build up
Marcus Lindblom on November 27th, 2010 at 1:53 AM says:
You don’t need to have in-process python scripts in the path. Just prefix with python: to load the hook.
precommit.tests = python:c:\Users\Jeethu\code\project\hooks\test_hook.py
You do need to change your script a bit to make it work (provide a single hook function instead of running as __main__) but otherwise that works very nicely.