I'm struggling to get Selenium working with my Django project. I can (finally) get it to get pages during testing, but I'm unable to get it to login for some reason.

This is my (very simple) test case:

import pytest

from django.conf import settings
from django.contrib.auth import get_user_model
from django.test.client import Client

from pytest_django.live_server_helper import LiveServer
from selenium.webdriver import Remote

from users.tests.factories import UserFactory

pytestmark = pytest.mark.django_db

class TestDashboard:
    def test_site_loads(self, browser: Remote, test_server: LiveServer):

        assert 'Welcome' in browser.title

    def test_valid_login(self, browser: Remote, test_server: LiveServer, user: settings.AUTH_USER_MODEL):
        password = 'testpassword'

        browser.get(test_server.url + '/accounts/login/')

        assert f'Successfully signed in as {user.username}' in browser.page_source

test_site_loads passes, test_valid_login fails, and if I example browser.current_url it's still pointing at /accounts/login/. If I look at the page source using browser.page_source, I can see "The e-mail address and/or password you specified are not correct." in the login form's error list.

I have no idea why the login credentials are failing here and I can't think of anything else to look at.

Here's what I see in the browser.page_source (captured via a print just before the assert statement) I mentioned above:

<form action="/accounts/login/" class="login auth-form" method="post"> 
<input type="hidden" name="csrfmiddlewaretoken" value="xLRQ8nZlfocyyQDlJxgLL0PUvsYLLNYNHEZ5awn8cLseQoR2XNQm4TiKOgMvcaS9"> 
<div class="alert alert-block alert-danger">
        <li>The e-mail address and/or password you specified are not correct.</li>
<div id="div_id_login" class="form-group">
    <div class="">
        <input type="email" name="login" value="[email protected]" placeholder="E-mail address" autofocus="autofocus" class="textinput textInput form-control" required="" id="id_login">
<div id="div_id_password" class="form-group"> 
    <div class=""> 
        <input type="password" name="password" placeholder="Password" class="textinput textInput form-control" required="" id="id_password">
    <button class="btn btn-lg btn-primary btn-block" type="submit">Sign In</button> 

I've also include the relevant fixtures for the tests:

import environ
import pytest
import socket

from django.conf import settings

from selenium.webdriver import Remote
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

from pytest_django.live_server_helper import LiveServer

from users.tests.factories import UserFactory

env = environ.Env()

def browser() -> Remote:
    driver = Remote(
        command_executor=env('SELENIUM_HOST', default='http://selenium:4444/wd/hub'),
    yield driver

def test_server() -> LiveServer:
    addr = socket.gethostbyname(socket.gethostname())
    server = LiveServer(addr)
    yield server

def user() -> settings.AUTH_USER_MODEL:
    return UserFactory()

Just as a sanity check, I've tried adding a couple of extra print statements to examine everything just prior to the assert:

    print('User email: ' + user.email)
    print('User is active? ' + str(user.is_active))
    print('Password valid? ' + str(user.check_password(password)))
    print('URL: ' +browser.current_url)

Gives me:

User email: [email protected]
User is active? True
Password valid? True

I've also tried adding an extra test that bypasses Selnium, to try and isolate the issue a bit more:

class TestAccountLoginView:
    def test_valid(self, client, user: settings.AUTH_USER_MODEL, request_factory: RequestFactory):
        password = 'password'

        response = client.post('/accounts/login/', {'login': user.email, 'password': password})

        assert response.status_code == 302

This works as expected and logs me in just fine.


Looks like this may actually have something to do with pytest-django's LiveServer. Ignoring the live_server fixture, and using Django's StaticLiveServerTestCase, I can login just fine:

class TestDashboard(StaticLiveServerTestCase):

    def setUpClass(cls):
        cls.host = socket.gethostbyname(socket.gethostname())
        cls.selenium = Remote(

    def tearDownClass(cls):

    def test_login(self):
        get_user_model().objects.create_user(username='testuser', email='[email protected]', password='password')

        self.selenium.get('%s%s' % (self.live_server_url, '/accounts/login/'))
        username_input = self.selenium.find_element_by_name("login")
        username_input.send_keys('[email protected]')
        password_input = self.selenium.find_element_by_name("password")

        assert 'Successful' in self.selenium.page_source

Not quite sure why the pytest-django's LiveServer is doing this, but at least I've got somewhere to look now.

0 Answers