我正在尝试编写一个使用Selenium来测试Django视图的功能测试。当用户访问页面(“page2”)时,呈现该页面的视图期望找到会话变量“uid”(用户ID)。我已经阅读了六篇关于如何做到这一点的文章,但没有一篇文章对我有用。下面的代码显示了Django documentation如何说它应该完成,但它对我也不起作用。当我运行测试时,视图永远不会完成执行,并且我收到“服务器错误发生”消息。有人可以告诉我我做错了什么吗?谢谢。
views.py:
from django.shortcuts import render_to_response
def page2(request):
uid = request.session['uid']
return render_to_response('session_tests/page2.html', {'uid': uid})
test.py:
from django.test import LiveServerTestCase
from selenium import webdriver
from django.test.client import Client
class SessionTest(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(3)
self.client = Client()
self.session = self.client.session
self.session['uid'] = 1
def tearDown(self):
self.browser.implicitly_wait(3)
self.browser.quit()
def test_session(self):
self.browser.get(self.live_server_url + '/session_tests/page2/')
body = self.browser.find_element_by_tag_name('body')
self.assertIn('Page 2', body.text)
答案 0 :(得分:2)
以下是解决此问题的方法。 James Aylett在提到上面的会话ID时暗示了解决方案。 jscn展示了如何设置会话,但他没有提到会话密钥对解决方案的重要性,他也没有讨论如何将会话状态链接到Selenium的浏览器对象。
首先,您必须了解当您创建会话密钥/值对(例如'uid'= 1)时,Django的中间件将在您选择的后端创建会话密钥/数据/到期日期记录(数据库,文件)等)。然后,响应对象将cookie中的会话密钥发送回客户端的浏览器。当浏览器发送后续请求时,它将发送一个包含该密钥的cookie,然后中间件使用该密钥查找用户的会话项。
因此,解决方案需要1.)找到一种方法来获取在创建会话项时生成的会话密钥然后; 2.)通过Selenium的Firefox webdriver浏览器对象找到一种将该密钥传递回cookie的方法。这是执行此操作的代码:
selenium_test.py:
-----------------
from django.conf import settings
from django.test import LiveServerTestCase
from selenium import webdriver
from django.test.client import Client
import pdb
def create_session_store():
""" Creates a session storage object. """
from django.utils.importlib import import_module
engine = import_module(settings.SESSION_ENGINE)
# Implement a database session store object that will contain the session key.
store = engine.SessionStore()
store.save()
return store
class SeleniumTestCase(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(3)
self.client = Client()
def tearDown(self):
self.browser.implicitly_wait(3)
self.browser.quit()
def test_welcome_page(self):
#pdb.set_trace()
# Create a session storage object.
session_store = create_session_store()
# In pdb, you can do 'session_store.session_key' to view the session key just created.
# Create a session object from the session store object.
session_items = session_store
# Add a session key/value pair.
session_items['uid'] = 1
session_items.save()
# Go to the correct domain.
self.browser.get(self.live_server_url)
# Add the session key to the cookie that will be sent back to the server.
self.browser.add_cookie({'name': settings.SESSION_COOKIE_NAME, 'value': session_store.session_key})
# In pdb, do 'self.browser.get_cookies() to verify that it's there.'
# The client sends a request to the view that's expecting the session item.
self.browser.get(self.live_server_url + '/signup/')
body = self.browser.find_element_by_tag_name('body')
self.assertIn('Welcome', body.text)
答案 1 :(得分:0)
在Django的bug追踪器中有几张关于这类问题的门票,主要的似乎是:https://code.djangoproject.com/ticket/10899几个月内没有任何动作。基本上,您需要做一些额外的设置才能使会话正常工作。这对我有用(可能不适用于您的特定设置,因为我没有使用Selenium):
def setUp(self):
from django.conf import settings
engine = import_module(settings.SESSION_ENGINE)
store = engine.SessionStore()
store.save()
self.client.cookies[settings.SESSION_COOKIE_NAME] = store.session_key
现在您应该能够访问self.client.session
,并且应该记住您对其所做的任何更改。
答案 2 :(得分:0)
这是我对django == 2.2的解决方案。
from importlib import import_module
from django.conf import settings
from django.contrib.auth import get_user_model
# create the session database instance
engine = import_module(settings.SESSION_ENGINE)
session = engine.SessionStore()
# create the user and instantly login
User = get_user_model()
temp_user = User.objects.create(username='admin')
temp_user.set_password('password')
self.client.login(username='admin', password='password')
# get session object and insert data
session = self.client.session
session[key] = value
session.save()
# update selenium instance with sessionID
selenium.add_cookie({'name': 'sessionid', 'value': session._SessionBase__session_key,
'secure': False, 'path': '/'})