views:

284

answers:

4

I'm adding a set of template tags to a Django application and I'm not sure how to test them. I've used them in my templates and they seem to be working but I was looking for something more formal. The main logic is done in the models/model managers and has been tested. The tags simply retrieve data and store it in a context variable such as

{% views_for_object widget as views %}
"""
Retrieves the number of views and stores them in a context variable.
"""
# or
{% most_viewed_for_model main.model_name as viewed_models %}
"""
Retrieves the ViewTrackers for the most viewed instances of the given model.
"""

So my question is do you typically test your template tags and if you do how do you do it?

A: 

Strings can be rendered as templates, so you could write a test that includes a simple 'template' using your templatetag as a string and just make sure it renders correctly given a certain context.

Josh Ourisman
These tags only render an empty string and instead change the context but I should be able to test for that as well.
Mark Lavin
A: 

When I was testing my template tags, I would have the tag, itself, return a string containing the text or dict I was working with ... sort of along the lines of the other suggestion.

Since tags can modify the context and/or return a string to be rendered -- I found it was fastest just to view the rendered string.

Instead of:

return ''

Have it:

return str(my_data_that_I_am_testing)

Until you are happy.

thornomad
+1  A: 

You guys got me on the right track. It's possible to check that the context was correctly changed after the render:

class TemplateTagsTestCase(unittest.TestCase):        
    def setUp(self):    
        self.obj = TestObject.objects.create(title='Obj a')

    def testViewsForOjbect(self):
        ViewTracker.add_view_for(self.obj)
        t = Template('{% load my_tags %}{% views_for_object obj as views %}')
        c = Context({"obj": self.obj})
        t.render(c)
        self.assertEqual(c['views'], 1)
Mark Lavin
+3  A: 

This is a short passage of one of my test files, where self.render_template a simple helper method in the TestCase is:

    rendered = self.render_template(
        '{% load templatequery %}'
        '{% displayquery django_templatequery.KeyValue all() with "list.html" %}'
    )
    self.assertEqual(rendered,"foo=0\nbar=50\nspam=100\negg=200\n")

    self.assertRaises(
        template.TemplateSyntaxError,
        self.render_template,
        '{% load templatequery %}'
        '{% displayquery django_templatequery.KeyValue all() notwith "list.html" %}'
    )

It is very basic and uses blackbox testing. It just takes a string as template source, renders it and checks if the output equals the expected string.

Gregor Müllegger
How do you test this outside of a project scope, say, for a reusable app? Rendering a template string that include `{% load custom_tag %}` does not seem to work, at least without additional work?
Santa
Answered my own question: use `register = template.Library(); template.libraries['django.templatetags.mytest'] = register; register.tag(name='custom_tag', compile_function=custom_tag)`.
Santa