Вопрос

I have a view unit test that is failing and I can't figure out the reason why. I believe it has something to do with the test database. The view in question is the default Django login view, django.contrib.auth.views.login. In my project, after the user logs in, they are redirected to a page that show which members are logged in. I've only stubbed out that page.

Here is the unit test:

from django.test import TestCase
from django.contrib.auth.models import User
from django.test.client import Client, RequestFactory
from django.core.urlresolvers import reverse
from utils.factories import UserFactory

class TestSignInView(TestCase):
    def setUp(self):
        self.client = Client()
        # self.user = UserFactory()
        self.user = User.objects.create_user(username='jdoe', password='jdoepass')

    def tearDown(self):
        self.user.delete()

    def test_user_enters_valid_data(self):
        response = self.client.post(reverse('login'), {'username': self.user.username, 'password': self.user.password}, follow=True)
        print response.context['form'].errors
        self.assertRedirects(response, reverse('show-members-online'))

Here is the error I get:

File "/Users/me/.virtualenvs/sp/lib/python2.7/site-packages/django/test/testcases.py", line 576, in assertRedirects
(response.status_code, status_code))
AssertionError: Response didn't redirect as expected: Response code was 200 (expected 302)
<ul class="errorlist"><li>__all__<ul class="errorlist"><li>Please enter a correct username and password. Note that both fields may be case-sensitive.</li></ul></li></ul>

The test fails with the same error whether I create the user manually with the create_user function or if I use this factory_boy factory:

from django.contrib.auth.models import User
class UserFactory(factory.DjangoModelFactory):
    FACTORY_FOR = User
    username = 'jdoe'
    # password = 'jdoepass'
    password = factory.PostGenerationMethodCall('set_password', 'jdoepass')
    email = 'jdoe@example.com'  

Here's the view I'm redirecting the user to after they log in successfully:

from django.shortcuts import render
def show_members_online(request, template):
    return render(request, template)

I printed out the error which shows that the test isn't recognizing the username/password pair. I've also printed out the username and password inside the test to confirm that they're the same values as what I initialize them to in setUp. At first, when I was utilizing the User factory, I thought it was because I wasn't encrypting the password when I created the user. That's when I did some research and learned that I needed to use the PostGenerationMethodCall to set the password.

I also looked at Django's testcases.py file. I don't understand everything that it's doing but it prompted me to try setting 'follow=True' when I do the post but that didn't make a difference. Can anyone tell me what I'm doing wrong? By the way, I'm using nosetests as my test runner.

Thanks!

Это было полезно?

Решение

In your test test_user_enters_valid_data, you are passing the password as self.user.password. This will be the SHA of the password because Django stores the sha of password on db. That's why you can never read the password for a particular user using user.password.

So, change your test_user_enters_valid_data.

def test_user_enters_valid_data(self):
    response = self.client.post(reverse('login'), {'username': self.user.username, 'password': 'jdoepass'}, follow=True)
    #### 
    ####

And it should work then.

Другие советы

Your test is sending {'username': self.user.username, 'password': self.user.password} in the POST. However, self.user.password is the hashed password not the plain text password which is why they aren't matching and you are seeing the form error rather than the redirect. Changing this to {'username': self.user.username, 'password': 'jdoepass'} should validate the username/password combination.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top