Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Tests: User.authenticate fails

I've been stuck on this problem for a couple hours. I'm new to django and automated testing, and I've been playing around with Selenium and django's StaticLiveServerTestCase. I've been trying to test my login form (which works fine when I use runserver and test it myself, by the way.)

Everything is working great, except I can't seem to successfully login my test user. I've narrowed down the break point to django's User.authenticate method.

The User object is created successfully in my setUp and I can confirm that by accessing it's attributes in my test method. However, authenticate fails.

I've looked at the following for help but they didn't get me very far:

  • Django Unittests Client Login: fails in test suite, but not in Shell
  • Authentication failed in Django test

Any idea why authenticate fails? Do I need to add something to my settings?

from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from django.contrib.auth.models import User

from django.contrib.auth import authenticate


class AccountTestCase(StaticLiveServerTestCase):
    def setUp(self):
        self.selenium = webdriver.Chrome()
        super().setUp()
        User.objects.create(username='test', email='[email protected]', password='Test1234', is_active=True)

    def tearDownClass(self):
        self.selenium.quit()
        super().tearDown()

    def test_register(self):
        user = authenticate(username='test', password='Test1234')
        if user is not None: # prints Backend login failed
            print("Backend login successful")
        else:
            print("Backend login failed")

    user = User.objects.get(username='test')
    print(user)
    print(user.username) # prints test
    print(user.password) # prints Test1234
like image 996
Daniel Long Avatar asked Apr 12 '26 14:04

Daniel Long


2 Answers

I found the issue. The User.authenticate() method hashes the password provided. However, I set the password directly when creating the user, which means it was stored as Test1234, so the hashed password provided during authentication did not match 'Test1234', hence the failure.

To properly store a hashed password, you need to use the set_password() method.

Updated setUp code:

def setUp(self):
    self.selenium = webdriver.Chrome()
    super().setUp()
    user = User.objects.create(username='test', email='[email protected]', is_active=True)
    user.set_password('Test1234')
    user.save()
like image 104
Daniel Long Avatar answered Apr 15 '26 05:04

Daniel Long


Using create_superuser resolved the issue. Below code resolves it.

from django.contrib.auth.models import User
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test import Client
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.webdriver import WebDriver
import time
from django.contrib.auth import authenticate

#from apps.digital.models import User


class MyTests(StaticLiveServerTestCase):

    port = 0
    host = 'my host'

    def setUp(self):
        super(MyTests, self).setUp()
        self.selenium = WebDriver()
        self.client = Client()
        self.user = User.objects.create_superuser(username='test', password='Test1234', email='[email protected]', is_active=True)
        self.user.save()

    def tearDown(self):
        self.selenium.quit()
        super(MyTests, self).tearDown()

    def test_login(self):
        self.user = authenticate(username='test', password='Test1234')
        if self.user is not None:  # prints Backend login failed
            self.user = User.objects.get(username='test')
            print(self.user.username)  # prints test
            print(self.user.password)  # prints Test1234
            self.login = self.client.login(username='test', password='Test1234')
            self.assertEqual(self.login, True)
            print("Backend login successful")

            self.selenium.get('%s%s' % (self.live_server_url, '/admin/'))
            username_input = self.selenium.find_element_by_name("username")
            username_input.send_keys(self.user.username)
            password_input = self.selenium.find_element_by_name("password")
            password_input.send_keys('Test1234')
            self.selenium.find_element_by_xpath('//input[@value="Log in"]').click()
            time.sleep(1)

        else:
            print("Backend login failed")
like image 21
kumaravel k Avatar answered Apr 15 '26 05:04

kumaravel k



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!