Test static resources in Django tests

02 June 2011   3 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>',
                          re.M|re.DOTALL)
STYLES_REGEX = re.compile('<link.*?href=["\']([^"\']+)["\'].*?>',
                         re.M|re.DOTALL)

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
         self.assert_all_embeds(response)

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!

Comments

Alex
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!
Joshua Blum
Hey! This seems super cool but I can't get any static embed to load without 404ing with the Djagno testing client. Any advice?
Thank you for posting a comment

Your email will never ever be published


Related posts

Previous:
A script tag's type in HTML5 10 May 2011
Next:
Google teething problems still with duplicated content 03 June 2011
Related:
Advanced Closure Compiler vs UglifyJS2 20 January 2016
Almost premature optimization 02 January 2015
XHTML, HTML and CSS compressor 07 April 2004