Test static resources in Django tests

02 June 2011   2 comments   Django

Powered by Fusion×

At Mozilla we use jingo-minify to bundle static resources such as .js and .css files. It's not a perfect solution but it's got some great benefits. One of them is that you need to know exactly which static resources you need in a template and because things are bundled you don't need to care too much about what files it originally consisted of. For example "jquery-1.6.2.js" + "common.js" + "jquery.cookies.js" can become "bundles/core.js"

A drawback of this is if you forget to compress and prepare all assets (using the compress_assets management command in jingo-minify) is that you break your site with missing static resources. So how to test for this?

Here's a simple solution I cooked up which appears to do the trick. It's just a quick start but it works. First:

# tests/mixins.py
import re
from nose.tools import eq_, ok_

SCRIPTS_REGEX = re.compile('<script\s*[^>]*src=["\']([^"\']+)["\'].*?</script>',
STYLES_REGEX = re.compile('<link.*?href=["\']([^"\']+)["\'].*?>',

class EmbedsTestCaseMixin:
   def assert_all_embeds(self, response):
       if hasattr(response, 'content'):
           response = response.content
       response = re.sub('<!--(.*)-->', '', response, re.M)
       for found in SCRIPTS_REGEX.findall(response):
           if found.endswith('.js'):
               resp = self.client.get(found)
               eq_(resp.status_code, 200, found)

       for found in STYLES_REGEX.findall(response):
           if found.endswith('.css'):
               resp = self.client.get(found)
               eq_(resp.status_code, 200, found)

Then with this you can render a page and check that all resources are reachable:

# apps/foo/tests.py
from tests.mixins import EmbedsTestCaseMixin
from django.test import TestCase
from django.core.urlresolvers import reverse

class FooViewsTestCase(TestCase):
    def test_add_page_static_files(self):
         url = reverse('foo.views.add_page')
         response = self.client.get(url)
         assert response.status_code == 200

I know it ain't django-rocket science but it's damn useful as it quickly catches me out if I accidentally get a typo in any of the bundles which in previous projects I've become accustomed to check by simply clicking around in Firefox with Firebug (Net tab) open.

Hope it helps!


Your comment-removing regex is a bit too greedy: it will eat anything between two comments:

In [10]: re.sub('<!--(.*)-->', '', '<!-- lala -->lu<!-- blah -->', re.M)
Out[10]: ''

fix: use the non-greedy version of *:

In [11]: re.sub('<!--(.*?)-->', '', '<!-- lala -->lu<!-- blah -->', re.M)
Out[11]: 'lu'
Peter Bengtsson
Thanks! Well spotted!

Your email will never ever be published

Related posts

A script tag's type in HTML5 10 May 2011
Google teething problems still with duplicated content 03 June 2011
Related by keywords:
XHTML, HTML and CSS compressor 07 April 2004