Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Unitest or Doctest?

I'm about to begin my third medium-sized project and would like (for the first time in my life i admit) to start using unittests. I have no idea though, which method to use, unitests or doctests. Which of the methods is the most efficient, or which should a beginner choose to implement? Thanks

like image 346
avlnx Avatar asked Jan 17 '23 20:01

avlnx


1 Answers

I happen to prefer unittests, but both are excellent and well developed methods of testing, and both are well-supported by Django (see here for details). In short, there are some key advantages and disadvantages to each:

Pros of unittests

  • unittests allows for easy creation of more complicated tests. If you have a test that involves calling multiple helper functions, iterations, and other analyses, doctests can feel limiting. unittests, on the other hand, is just writing Python code- anything you can do in Python you can do comfortably there. Take this code (a modified version of a unittest I once wrote):

    def basic_tests(self, cacheclass, outer=10, inner=100, hit_rate=None):
        c = cacheclass(lambda x: x + 1)
        for n in xrange(outer):
            for i in xrange(inner):
                self.assertEqual(c(i), i + 1)
        if hit_rate != None:
            self.assertEqual(c.hit_rate(), hit_rate)
    
    def test_single_cache(self):
        self.basic_tests(SingleCache, outer=10, inner=100, hit_rate=0)
        sc = SingleCache(lambda x: x + 1)
        for input in [0, 1, 2, 2, 2, 2, 1, 1, 0, 0]:
            self.assertEqual(sc(input), input + 1)
        self.assertEqual(sc.hit_rate(), .5)
    

    I use the basic_tests method to run some tests on a class, then run an assertion within a for loop. There are ways to do this in doctests, but they require a good deal of thought- doctests are best at checking that specific individual calls to a function return the values they should. (This is especially true within Django, which has fantastic tools for unit testing (see django.test.client).

  • doctests can clutter up your code. When I'm writing a class or method, I put as much documentation into the docstrings as I need to to make it clear what the method does. But if your docstrings are 20+ lines long, you can end up having as much documentation within your code as you have code. This adds to the difficulty of reading and editing it (one of my favorite things about Python as a programming language is its compactness).

Pros of docstrings

  • Your tests are associated with particular classes and methods. This means that if a test fails, you immediately know which class and method failed. You can also use tools to determine the coverage of your tests across your classes. (Of course, this can be limiting as well, if you want a test to cover many different parts of your code).

  • Your tests are right next to the code, meaning it is easier to keep them in sync. When I make changes to a class or method, I often forget to make the corresponding changes to the test cases (though of course I am soon helpfully reminded when I run them). Having the doctests right next to your method declaration and code makes this easy.

  • Tests serve as a kind of documentation. People who look through your code can have pre-included examples of how to call and use each method.

Conclusion: I certainly prefer unittests, but there is a great case to be made for either.

like image 88
David Robinson Avatar answered Jan 24 '23 16:01

David Robinson