django-3t

Django 3T is a Django Template Testing Tool which aims to help developers to write better tests where the Django template engine is involved.


Keywords
django, template, test, unittest, templates, testing
License
MIT
Install
pip install django-3t==1.0.0a1

Documentation

PyPI Version Travis Build Code Coverage License

Django 3T

Django 3T is a Django Template Testing Tool which aims to help developers to write better tests where the Django template engine is involved.

Some of the things you can do with Django 3T include:

  • Ensure a specific template, node or block is rendered
  • Ensure a specific template, node or block is rendered a specific amount of times
  • Ensure a specific template is rendered with a specific context subset
  • Ensure a specific node is rendered with specific arguments
  • Ensure a specific template, node or block results in a specific content or includes it

Installation

pip install django-3t

Usage

Django 3T uses the watch_templates context manager to intercept template and node renderings.

Suppose your project implements the following template called homepage.html:

{% load say_hello from project_tags %}

<h1>The most useful website ever</h1>

{% say_hello request.user %}

A test that makes sure your template and template tag are rendered correctly would roughly look like this:

from django.contrib.auth import get_user_model
from django.test import Client

# 1. Import the context manager
from d3t.watcher import watch_templates

User = get_user_model()

def test_homepage():
    user = User.objects.get(username='Billy')
    client = Client()
    client.force_login(user)

    # 2. Wrap the code where the rendering happens
    with watch_templates as rendered:
        client.get('/')

    # 3. Assert!
    assert rendered.template('homepage.html')
    assert rendered.node('say_hello').with_arguments(user)

The first assertion makes sure the template homepage.html was rendered, the second assertion makes sure the template tag say_hello was rendered and it was done using user as argument.

For a comprehensive list of available methods, check the API section.

API

You can check that a template, node or block has been rendered and that it did under specific conditions

Template API

Check that it has been rendered

rendered.template('template-name.html')

Check that it has been rendered with a specific context subset

rendered.template('template-name.html').with_context({'answer': 42})

Check that it has been rendered and the output contains a specific string

rendered.template('template-name.html').contains('content')

Check that it has been rendered and the output equals a specific string

rendered.template('template-name.html').equals('full content')

Node API

Check that it has been rendered

rendered.node('node_name')

Check that it has been rendered with specific arguments

rendered.node('node_name').with_arguments(42, type='answer')

Check that it has been rendered and the output contains a specific string

rendered.node('node_name').contains('content')

Check that it has been rendered and the output equals a specific string

rendered.node('node_name').equals('full content')

Block API

Check that it has been rendered

rendered.block('block-name')

Check that it has been rendered and the output contains a specific string

rendered.block('block-name').contains('content')

Check that it has been rendered and the output equals a specific string

rendered.block('block-name').equals('full content')

Handling multilpe renderings

A template, node or block could be rendered any number of times, Django 3T allows you to take control of this giving support for the not operator and for the len, all and any built-in functions:

Check that a template/node/block has not been rendered

not rendered.template('template-name.html')

Check that a template/node/block has been rendered a specific amount of times

len(rendered.node('node_name')) == 3

Check that all the template/node/block renderings happened under a specific condition

all(rendered.block('block-name').contains('content'))

Check that any of the template/node/block renderings happened under a specific condition

any(rendered.template('template-name.html').equals('specific content'))

Signals

template_rendered

d3t.signals.template_rendered

This is sent immediately after a template is rendered.

Arguments sent with this signal:

  • sender
    The Template class.
  • instance
    The actual template instance being rendered.
  • context
    The context used to render the template.
  • result
    The resulting rendered output.

node_rendered

d3t.signals.node_rendered

This is sent immediately after a node is rendered.

Arguments sent with this signal:

  • sender
    The Node class.
  • instance
    The actual node instance being rendered.
  • result
    The resulting rendered output.