Skip to main content
1 of 4
acjay
  • 346
  • 2
  • 12

Unit testing in Django

I'm really struggling to write effective unit tests for a large Django project. I have reasonably good test coverage, but I've come to realize that the tests I've been writing are definitely integration/acceptance tests, not unit tests at all, and I have critical portions of my application that are not being tested effectively. I want to fix this ASAP.

Here's my problem. My schema is deeply relational, and heavily time-oriented. Many of my model methods query based on time intervals, and I've got a lot of auto_now_add going on in timestamped fields. So take a method that looks like this for example:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()
    
    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.method() for object in objects)

How does one approach testing something like this?

Mocking datetime.now() is straightforward enough, but how can I unit test the rest of the functionality? I've heard pros and cons of using fixtures for building my data (poor maintainability being a con that hits home for me). I could also setup my data through the ORM, but that can be limiting as well, because then I have to create related objects as well. Mocking is another option, but to me, it seems to make the test really dependent on the internals and dependencies of the function-under-test.

The toughest nuts to crack seem to be the functions that sit on a few layers of models and lower-level functions, even though these functions are not super complicated. My overall problem is that no matter how I seem to slice it, my tests are looking way more complex than the functions they are testing. I think I've gone off-track someplace, because I don't think it should be like that.

acjay
  • 346
  • 2
  • 12