Lazy test loading to deal with conflicting django settings

At work I have a bunch (ok, 3) different django projects in the same big code tree. Yes, I know we should split them up, thanks for pointing that out. Anyway, we are running python unit tests using the trial testrunner from twisted, because it’s very nice and we also have some twisted servers in this same code tree.

I have a problem with Django settings. There are some conflicting settings in the settings file used by different Django servers. The solution seems easy – run tests for each Django server in a separate subprocess. The excellent subunit library should do just the trick, it even has IsolatedTestSuite and IsolatedTestCase classes that take care of forking and running in a separate process.

Except this doesn’t work. Because when python modules are imported for test discovery, they also indirectly end up importing django.settings, and when the IsolatedTestSuite forks to run tests in a separate subprocess, that subprocess inherits the already polluted python environment that has the (sometimes wrong) django.settings imported already.

I am convinced that this must be solvable, but have been banging my head against it for a while and don’t understand unittest discovery well enough to solve it. I’ve created a self-contained little example that demonstrates the problem in isolation here: https://code.edge.launchpad.net/~statik/+junk/subunit-demo/

I will gladly endure your taunts if you teach me a solution.

Comments

2 Comments so far. Leave a comment below.
  1. To channel Mr. Collins, mutable global state is bad?

  2. Ferringb,

    Realistically what is needed here is for django.settings to 'swivel' it's configuration on the fly- this is the best you can do when dealing w/ globals like this (realistically avoiding said globals is better).Meanwhile, the issue is partially y'alls doing- y'all pull django.settings in as an import after all. I'd probably shift the django.settings import, and a sys.modules wipe of anything django related into a self.setUp() method…Not great but with some minor finessing it ought to do the trick. Not a perfect long term thing though- a long term approach you might want to look into is adding a func for importing django targets into global(), one that proxies and is switchable, controlled by setUp().Personally I'd just go fix that !@*#ing global crap and make it switchable- had patches in the past for django for this, although I don't recall ever seeing them get integrated upstream…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 445 other followers

%d bloggers like this: