Django Code Coverage Support

Coming from the Java world, I'm used to easily-available code metrics as part of my build process. Ant can do it, Maven can do it and life was good. About two years ago, I realized I started using Python for a lot of things and so it was only natural to use Python for a simple web-based management tool I was prototyping. I decided to go with Django and again, life was good. As my prototype got larger, primarily due to me having to write my own model-validation framework, I began to worry about the integrity of my unit tests. I immediately Google for "Python Code Coverage" and find coverage.py. This excellent and simple script/module made code coverage instantly available but with no integration into Django's manage.py, I had to run coverage.py manually on top of the Django test cycle. Again, I turn to Google and I found a great article on exactly what I wanted: Code Coverage for Your Django Code. The only problem was that Siddhi's post assumed I wanted HTML reports, which I didn't, and his suggestion was to modify the actual Django test code, which can be very volatile. Not being 100% satisfied, I embarked on my own journey to allow for a simple and safe way to integrate coverage.py into Django.

With Django 0.97+, there is a setting available to settings.py called TEST_RUNNER. This setting allows you to write your own test runner and have Django use that test runner in place of its own. Since I can write my own test runner now, anything is possible and that is where Siddhi's post gave me an idea: Why not extend the settings.py to have the stuff I need for coverage.py and use the TEST_RUNNER setting to run my test runner instead? With that approach, I have the following samples of code:

settings.py

...
# Specify your custom test runner to use
TEST_RUNNER='sample.tests.test_runner_with_coverage'
 
# List of modules to enable for code coverage
COVERAGE_MODULES = ['sample.views', 'sample.urls',]
...

tests.py

import os, shutil, sys, unittest
 
# Look for coverage.py in __file__/lib as well as sys.path
sys.path = [os.path.join(os.path.dirname(__file__), "lib")] + sys.path
 
import coverage
from django.test.simple import run_tests as django_test_runner
 
from django.conf import settings
 
def test_runner_with_coverage(test_labels, verbosity=1, interactive=True, extra_tests=[]):
  """Custom test runner.  Follows the django.test.simple.run_tests() interface."""
  # Start code coverage before anything else if necessary
  if hasattr(settings, 'COVERAGE_MODULES') and not test_labels:
    coverage.use_cache(0) # Do not cache any of the coverage.py stuff
    coverage.start()
 
  test_results = django_test_runner(test_labels, verbosity, interactive, extra_tests)
 
  # Stop code coverage after tests have completed
  if hasattr(settings, 'COVERAGE_MODULES') and not test_labels:
    coverage.stop()
 
    # Print code metrics header
    print ''
    print '----------------------------------------------------------------------'
    print ' Unit Test Code Coverage Results'
    print '----------------------------------------------------------------------'
 
  # Report code coverage metrics
  if hasattr(settings, 'COVERAGE_MODULES') and not test_labels:
    coverage_modules = []
    for module in settings.COVERAGE_MODULES:
      coverage_modules.append(__import__(module, globals(), locals(), ['']))
 
    coverage.report(coverage_modules, show_missing=1)
 
    # Print code metrics footer
    print '----------------------------------------------------------------------'
 
  return test_results
 
# test_runner_with_coverage()

With the code above in place, now when I run 'python manage.py test', I now get get a code coverage report that looks like this:

.....
------------------------------------------------------------------
 Unit Test Code Coverage Results
------------------------------------------------------------------
Name           Stmts   Exec  Cover   Missing
--------------------------------------------
sample.urls        2      0     0%   1-3
sample.views       3      0     0%   1-5
--------------------------------------------
TOTAL              5      0     0%
------------------------------------------------------------------

As you can see, for ever module added to COVERAGE_MODULES in settings.py, you get a report telling the number of executable statements, the number executed, the percentage executed and a list of code lines not executed. (Obviously I've not written any tests.) Being able to see your code coverage is not a way to guarantee better tests but they sure let you know what code is being executed as part of running your unit tests.

The most important parts about my approach as opposed to other approaches is that my approach does the following:

  • It does not require modifying Django core code, which can be volatile in the event that you're running Django from the non-released 0.97 trunk.
  • It is very simple to maintain since you pretty much separate your specific needs from Django's internal needs.
  • It works as part of Django meaning no extra work required on your part to get the metrics you need.
  • You now have access to code coverage metrics by running the same Django test command you're use to.

In then end, you have easily integrated code coverage metrics via coverage.py into Django. I hope this information is as useful to you as it has been for me.

iTunes on Vista Causes iPod Audio/Video Crashing

Due to my crazy schedule recently, I've not really had time to blog about my wonderful toy called the iPod Touch. All has been well since I got it last November until I upgraded to firmware 1.1.3. Before the upgrade, I had a boat-load of content on my Touch that played crash/skip free. After the upgrade, every movie on my Touch would crash and ironically, all music on the device that I purchased from iTunes would crash as well. Since upgrading to 1.1.3 was no picnic and my content all the sudden was worthless, I started to feel like I had wasted $399 plus tax. That is when I went on my Google tour to find a solution.

Google had been treating me fine but as usual with these search terms, false positives were everywhere. I decided to post a thread on the Apple Discussion Site and before I got an actual answer, or even guess, to my problem, I found what may be the solution. While googling, I had found some random threads about this being a Vista issue. While not a Microsoft fan, other than the XBox 360, I didn't believe these threads. The problem is that I felt like I had tried everything so I decided to give this Vista-caused issue a test.

What I did was I took the same problematic content from my Vista box to my PowerBook, synced to my iPod Touch via iTunes and to my amazement, all content played flawlessly. All the sudden I felt this sense of joy come over me since now my $399 plus tax Touch was great again. Sure the Application Pack released in January made these problems seem more like hiccups but now, the device was as it should be. I'm not sure if this is some anomaly or if it is in fact an iTunes on Vista issue. I just know that I now have working content on my iPod Touch and this might fix someone else's problems too.

P.S. - If this is an iTunes on Vista issue, I hope that Apple fixes it sooner rather than later. I do have to admit that this juggling of content is quite the pain.

AIX Subversion 1.4.6 Binaries on openCollabNet

I recently released a Subversion binary for AIX on openCollabNet . Since I blogged about the release on openCollabNet, I'll be brief but there are a few things worth discussing here since I maintain it.

The AIX binary on openCollabNet is a build of Subversion 1.4.6. It includes all repository access layers and all repository backends. The Python bindings are also included in this binary along with the Apache 2.2.x server modules. Put this all together and you can now use Subversion as a consumer from an AIX box or you can build a completely feature-full Subversion server for your project(s) or enterprise. All of this without having to build a single line of code, install a special binary or track down problems with building Subversion and/or it's dependencies on the AIX platform. For more details about the binary, it's build instructions and other related materials, please visit the AIX portion of the svnbinaries project.

If you find the binary from this page, please remember to use the svnbinaries project on openCollabNet for feedback, bug reports, feature requests and/or help.

Universal Subversion OSX Binary Grows in Popularity

A few months back, I decided to create and maintain a Universal Subversion OSX Binary. The idea was to create a single package that included Subversion and all features supported by the core Subversion development team. The reasons behind this were many but largely in part to a colleague that wanted an easier way to get Subclipse via JavaHL running on his new Mac. Once built and tested, it was released and the feedback has been very good. Working at CollabNet, whom I work for and who sponsors Subversion and the site that my binaries are hosted on, I have access to the download metrics for this binary. Last week, I heard the binary had been downloaded over 26K times and has become the single-most downloaded artifact on openCollabNet. I was shocked to hear this information while ultimately excited at how a weekend project, which has become more obviously due to demand, has had such an impact. If you're on a Mac and you need Subversion, I'd suggest you give my binary a try. Here are the details:

Welcome to ThoughtSpark.org

ThoughtSpark.org is a site I created a while back with this great idea of becoming an information portal about things I'm into. As many people find, there isn't enough time in the day sometimes to keep a site up to date as you'd had originally intended. It also doesn't help that my daytime job requires that I post blogs to other sites like Dev2Dev and openCollabNet . What I have decided to do was remove all previous posts, since it hadn't been updated since March anyways, and start fresh. Before I close, let me link to a few of my external blog entries here:

From now on, I will follow up any openCollabNet blog with an entry here and I will hopefully be blogging more regularly about other stuff as well. Enjoy.

Syndicate content