Search code examples
pythondjangopython-2.7django-templatesdjango-testing

Django: django.test TestCase self.assertTemplateUsed


Working on Hello Web App.

Please help with TestCase: test_edit_thing.

Here's the error details:

The error in case of '/things/django-book/edit/':

# AssertionError: No templates used to render the response
response = self.client.get('/things/django-book/edit/')
self.assertTemplateUsed(response, 'things/edit_thing.html')

The error in case of '/things/django-book/':

# AssertionError: Template 'things/edit_thing.html' was not a template used to render the response. Actual template(s) used: things/thing_detail.html, base.html
response = self.client.get('/things/django-book/')
self.assertTemplateUsed(response, 'things/edit_thing.html')

Code Snippet:

from django.contrib.auth.models import AnonymousUser, User
from django.test import TestCase, RequestFactory

from collection.models import Thing
from .views import *

class SimpleTest(TestCase):
    def setUp(self):
        # Every test needs access to the request factory.
        self.factory = RequestFactory()
        self.user = User.objects.create_user(username='Foo', password='barbaz')        
        self.thing = Thing.objects.create(name="Django Book",
                                     description="Learn how to build your first Django web app.",
                                     slug="django-book",
                                     user=self.user)

    def test_index(self):
        request = self.factory.get('/index/')
        response = index(request)
        print(response.status_code)
        self.assertEqual(response.status_code, 200)        
        response = self.client.get('/')
        self.assertTemplateUsed(response, 'base.html')

    def test_thing_detail(self):
        django_book = Thing.objects.get(name="Django Book")        
        request = self.factory.get('/things/django-book/')
        response = thing_detail(request, django_book.slug)
        print(response.status_code) 
        self.assertEqual(response.status_code, 200)
        response = self.client.get('/things/django-book/')
        self.assertTemplateUsed(response, 'things/thing_detail.html')

    def test_edit_thing(self):
        django_book = Thing.objects.get(name="Django Book")
        request = self.factory.get('/things/django-book/edit/')
        request.user = django_book.user
        response = edit_thing(request, django_book.slug)
        print(response.status_code) 
        self.assertEqual(response.status_code, 200)

        # AssertionError: No templates used to render the response
        #response = self.client.get('/things/django-book/edit/')

        # AssertionError: Template 'things/edit_thing.html' was not a template used to render the response. Actual template(s) used: things/thing_detail.html, base.html
        #response = self.client.get('/things/django-book/')
        #self.assertTemplateUsed(response, 'things/edit_thing.html')

        # Right?
        response = self.client.get('/things/django-book/')        
        self.assertTemplateUsed(response, 'things/thing_detail.html')

views.py

from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import render, redirect
from django.template.defaultfilters import slugify

from collection.forms import ThingForm
from collection.models import Thing


def index(request):
    things = Thing.objects.all()
    return render(request, 'index.html', {
        'things': things,
    })


def thing_detail(request, slug):
    # grab the object...
    thing = Thing.objects.get(slug=slug)

    # and pass to the template
    return render(request, 'things/thing_detail.html', {
        'thing': thing,
    })


@login_required
def edit_thing(request, slug):
    # grab the object...
    thing = Thing.objects.get(slug=slug)

    # grab the current logged in user and make sure they're the owner of the thing
    if thing.user != request.user:
        raise Http404

    # set the form we're using...
    form_class = ThingForm

    # if we're coming to this view from a submitted form,  
    if request.method == 'POST':
        # grab the data from the submitted form
        form = form_class(data=request.POST, instance=thing)

        if form.is_valid():
            # save the new data
            form.save()
            return redirect('thing_detail', slug=thing.slug)

    # otherwise just create the form
    else:
        form = form_class(instance=thing)

    # and render the template
    return render(request, 'things/edit_thing.html', {
        'thing': thing,
        'form': form,
    })


def create_thing(request):
    form_class = ThingForm

    # if we're coming from a submitted form, do this
    if request.method == 'POST':
        # grab the data from the submitted form and apply to the form
        form = form_class(request.POST)

        if form.is_valid():
            # create an instance but do not save yet
            thing = form.save(commit=False)

            # set the additional details
            thing.user = request.user
            thing.slug = slugify(thing.name)

            # save the object
            thing.save()

            # redirect to our newly created thing
            return redirect('thing_detail', slug=thing.slug)

    # otherwise just create the form
    else:
        form = form_class()

    return render(request, 'things/create_thing.html', {
        'form': form,
    })


def browse_by_name(request, initial=None):
    if initial:
        things = Thing.objects.filter(
             name__istartswith=initial).order_by('name')
    else:
        things = Thing.objects.all().order_by('name')

    return render(request, 'search/search.html', {
        'things': things,
        'initial': initial,
    })

Thanks


Solution

  • So the problem that you was having is that your user wasn't authenticated, and if user is not the same as user of the thing you raise Http404

    It in your edit_thing view

    if thing.user != request.user:
        raise Http404
    

    So you needed to be authenticated. And that could be made with login

    def test_edit_thing(self):
        django_book = Thing.objects.get(name="Django Book")
        request = self.factory.get('/things/django-book/edit/')
        request.user = django_book.user
        response = edit_thing(request, django_book.slug)
        print(response.status_code)
        self.assertEqual(response.status_code, 200)
        self.client.login(username='Foo', password='barbaz')
        response = self.client.get('/things/django-book/edit/')        
        self.assertTemplateUsed(response, 'things/edit_thing.html')