Test static resources in Django tests

02 June 2011   3 comments   Django

Mind That Age!

This blog post is 6 years old! Most likely, its content is outdated. Especially if it's technical.

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!

Follow @peterbe on Twitter

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 by Keyword:
Advanced Closure Compiler vs UglifyJS2 20 January 2016
Almost premature optimization 02 January 2015
XHTML, HTML and CSS compressor 07 April 2004
Related by Text:
Goodies from tornado-utils - part 1: TestClient 20 September 2011
Django test optimization with no-op PIL engine 27 October 2016
How to unit test the innards of a Django view function 15 November 2008
Goodies from tornado-utils - part 2: tornado_static 22 September 2011
Hosting Django static images with Amazon Cloudfront (CDN) using django-static 09 July 2010