selenium.common.exceptions.InvalidCookieDomainException:消息:使用 Selenium 在 Django 中执行测试时无效的 cookie 域
selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain while executing tests in Django with Selenium
我正在使用 seleniumgrid.I 为 chrome 和 firefox 设置测试,我正在使用 docker 图像 selenium-hub 和 selenium node-chrome 以及 node-firefox 作为下面。
app:
build: .
command: gunicorn --reload --capture-output --log-level debug --access-logfile - -w 3 -b 0.0.0.0 app.wsgi
restart: always
volumes_from:
- initialize
ports:
- "8000:8000"
links:
- db
- rabbitmq
- selenium_hub
env_file: secrets.env
volumes:
- ./app/:/code/
selenium_hub:
image: selenium/hub
ports:
- 4444:4444
expose:
- 4444
tty: true
environment:
- GRID_MAX_SESSION=20
- GRID_NEW_SESSION_WAIT_TIMEOUT=60000
- GRID_BROWSER_TIMEOUT=300
- GRID_TIMEOUT=300
- TIMEOUT=300
node_1:
image: selenium/node-chrome
depends_on:
- selenium_hub
environment:
- HUB_HOST=selenium_hub
- HUB_PORT=4444
- NODE_MAX_SESSION=3
- NODE_MAX_INSTANCES=2
shm_size: 2GB
node_2:
image: selenium/node-firefox
environment:
- HUB_HOST=selenium_hub
- HUB_PORT=4444
- NODE_MAX_SESSION=3
- NODE_MAX_INSTANCES=2
shm_size: 2GB
depends_on:
- selenium_hub
当我尝试 运行 测试时,我总是 运行 遇到这个错误 InvalidCookieDomainException: Message: invalid cookie domain
。我已经将域设置为 self.live_server_url
。
下面是测试设置的完整回溯。
Traceback (most recent call last):
File "/code/frontend/tests/test_user_auth.py", line 75, in setUp
"port": "8082",
File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/webdriver.py", line 894, in add_cookie
self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict})
File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain
(Session info: chrome=77.0.3865.75)
class TestUserCreate(StaticLiveServerTestCase):
fixtures = ["test.json"]
port = 8082
@classmethod
def setUpClass(cls):
super().setUpClass()
caps = {
"browserName": os.getenv("BROWSER", "chrome"),
"javascriptEnabled": True,
}
cls.driver = webdriver.Remote(
command_executor="http://selenium_hub:4444/wd/hub",
desired_capabilities=caps,
)
cls.driver.implicitly_wait(10)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
super().tearDownClass()
def setUp(self):
# Login the user
self.assertTrue(self.client.login(username="james", password="changemequick"))
# Add cookie to log in the browser
cookie = self.client.cookies["sessionid"]
self.driver.get(self.live_server_url + reverse("find_patient"))
self.driver.add_cookie(
{
"name": "sessionid",
"value": cookie.value,
"domain": "localhost"
}
)
super().setUp()
def test_form_loader(self):
# test forms loader is functioning properly
driver = self.driver
driver.get(self.live_server_url + "/accounts/login/")
driver.find_element_by_xpath("//input[@type='submit']").click()
driver.get_screenshot_as_file("login.png")
assert len(driver.find_elements_by_css_selector(".loading")) == 0
这个错误信息...
selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain
...表示非法尝试在与当前文档不同的域下设置 cookie。
详情
根据 HTML-Living Standard Specs,在以下情况下,Document Object
可能被归类为 cookie-averse Document 对象:
- 没有
Browsing Context
. 的文档
- URL 方案不是网络方案的文档。
深入探讨
根据 Invalid cookie domain 如果当前域为 example.com
,则可能会发生此错误,将无法为域 example.org
添加 cookie。
举个例子:
示例代码:
from selenium import webdriver
from selenium.common import exceptions
session = webdriver.Firefox()
session.get("https://example.com/")
try:
cookie = {"name": "foo",
"value": "bar",
"domain": "example.org"}
session.add_cookie(cookie)
except exceptions.InvalidCookieDomainException as e:
print(e.message)
控制台输出:
InvalidCookieDomainException: https://example.org/
解决方案
如果您存储了来自域 example.com
的 cookie,这些存储的 cookie 不能 通过 webdriver 会话推送到任何其他不同的域,例如example.edu
。存储的 cookie 只能在 example.com
内使用。此外,为了将来自动登录用户,您只需要存储 cookie 一次,即用户登录时。在添加回 cookie 之前,您需要浏览到收集 cookie 的同一域。
例子
例如,您可以在用户登录应用程序后存储 cookie,如下所示:
from selenium import webdriver
import pickle
driver = webdriver.Chrome()
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
driver.find_element_by_name("username").send_keys("abc123")
driver.find_element_by_name("password").send_keys("123xyz")
driver.find_element_by_name("submit").click()
# storing the cookies
pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
driver.quit()
以后如果你想让用户自动登录,你需要先浏览到特定的域/url然后你必须添加cookie如下:
from selenium import webdriver
import pickle
driver = webdriver.Chrome()
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
# loading the stored cookies
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
# adding the cookies to the session through webdriver instance
driver.add_cookie(cookie)
driver.get('http://demo.guru99.com/test/cookie/selenium_cookie.php')
额外考虑
您似乎在使用 chrome=77.0.3865.75。理想情况下,您需要确保:
- Selenium 已升级到当前级别 Version 3.141.59。
- Chrome驱动程序 已更新至当前 ChromeDriver v79.0.3945.36 级别。
- Chrome 已更新为当前 Chrome 版本 79.0 级别。 (根据 ChromeDriver v79.0 release notes)
参考
您可以在以下位置找到详细讨论:
- Error when loading cookies into a Python request session
在 selenium 中我们必须使用测试服务器的 URL 默认情况下这是 localhost,以启用对外部可访问服务器地址的访问,该地址是我们需要使用的托管 docker 容器的地址服务器机器的IP地址,
所以设置如下,
class BaseTestCase(StaticLiveServerTestCase):
"""
Provides base test class which connects to the Docker
container running Selenium.
"""
host = '0.0.0.0' # Bind to 0.0.0.0 to allow external access
@classmethod
def setUpClass(cls):
super().setUpClass()
# Set host to externally accessible web server address
cls.host = socket.gethostbyname(socket.gethostname())
引用here
我运行遇到了同样的问题。我的解决方案只是避免在 cookie 中设置 domain
值(wich is optional,顺便说一句)。
class MyTestCase(StaticLiveServerTestCase):
host = os.environ['DJANGO_CONTAINER_NAME']
def test_logged_in(self):
self.client.login(username="integration", password="test")
self.selenium.get(self.live_server_url)
self.selenium.add_cookie({"name": settings.SESSION_COOKIE_NAME,
"value": self.client.cookies[settings.SESSION_COOKIE_NAME].value})
post = Post.objects.first()
self.selenium.get(f"{self.live_server_url}{reverse('post', args=(post.slug, ))}")
这里的要点是让 Django 客户端(此处 self.client
)登录,然后将其会话 cookie 复制到 Selenium 浏览器会话,该会话应该已经从您的实时服务器访问过一个页面 - 在其他情况下话说,先让Selenium浏览器打开一个页面,然后设置cookie(跳过domain
),然后,selenium浏览器就登录了。
我正在使用 seleniumgrid.I 为 chrome 和 firefox 设置测试,我正在使用 docker 图像 selenium-hub 和 selenium node-chrome 以及 node-firefox 作为下面。
app:
build: .
command: gunicorn --reload --capture-output --log-level debug --access-logfile - -w 3 -b 0.0.0.0 app.wsgi
restart: always
volumes_from:
- initialize
ports:
- "8000:8000"
links:
- db
- rabbitmq
- selenium_hub
env_file: secrets.env
volumes:
- ./app/:/code/
selenium_hub:
image: selenium/hub
ports:
- 4444:4444
expose:
- 4444
tty: true
environment:
- GRID_MAX_SESSION=20
- GRID_NEW_SESSION_WAIT_TIMEOUT=60000
- GRID_BROWSER_TIMEOUT=300
- GRID_TIMEOUT=300
- TIMEOUT=300
node_1:
image: selenium/node-chrome
depends_on:
- selenium_hub
environment:
- HUB_HOST=selenium_hub
- HUB_PORT=4444
- NODE_MAX_SESSION=3
- NODE_MAX_INSTANCES=2
shm_size: 2GB
node_2:
image: selenium/node-firefox
environment:
- HUB_HOST=selenium_hub
- HUB_PORT=4444
- NODE_MAX_SESSION=3
- NODE_MAX_INSTANCES=2
shm_size: 2GB
depends_on:
- selenium_hub
当我尝试 运行 测试时,我总是 运行 遇到这个错误 InvalidCookieDomainException: Message: invalid cookie domain
。我已经将域设置为 self.live_server_url
。
下面是测试设置的完整回溯。
Traceback (most recent call last):
File "/code/frontend/tests/test_user_auth.py", line 75, in setUp
"port": "8082",
File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/webdriver.py", line 894, in add_cookie
self.execute(Command.ADD_COOKIE, {'cookie': cookie_dict})
File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain
(Session info: chrome=77.0.3865.75)
class TestUserCreate(StaticLiveServerTestCase):
fixtures = ["test.json"]
port = 8082
@classmethod
def setUpClass(cls):
super().setUpClass()
caps = {
"browserName": os.getenv("BROWSER", "chrome"),
"javascriptEnabled": True,
}
cls.driver = webdriver.Remote(
command_executor="http://selenium_hub:4444/wd/hub",
desired_capabilities=caps,
)
cls.driver.implicitly_wait(10)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
super().tearDownClass()
def setUp(self):
# Login the user
self.assertTrue(self.client.login(username="james", password="changemequick"))
# Add cookie to log in the browser
cookie = self.client.cookies["sessionid"]
self.driver.get(self.live_server_url + reverse("find_patient"))
self.driver.add_cookie(
{
"name": "sessionid",
"value": cookie.value,
"domain": "localhost"
}
)
super().setUp()
def test_form_loader(self):
# test forms loader is functioning properly
driver = self.driver
driver.get(self.live_server_url + "/accounts/login/")
driver.find_element_by_xpath("//input[@type='submit']").click()
driver.get_screenshot_as_file("login.png")
assert len(driver.find_elements_by_css_selector(".loading")) == 0
这个错误信息...
selenium.common.exceptions.InvalidCookieDomainException: Message: invalid cookie domain
...表示非法尝试在与当前文档不同的域下设置 cookie。
详情
根据 HTML-Living Standard Specs,在以下情况下,Document Object
可能被归类为 cookie-averse Document 对象:
- 没有
Browsing Context
. 的文档
- URL 方案不是网络方案的文档。
深入探讨
根据 Invalid cookie domain 如果当前域为 example.com
,则可能会发生此错误,将无法为域 example.org
添加 cookie。
举个例子:
示例代码:
from selenium import webdriver from selenium.common import exceptions session = webdriver.Firefox() session.get("https://example.com/") try: cookie = {"name": "foo", "value": "bar", "domain": "example.org"} session.add_cookie(cookie) except exceptions.InvalidCookieDomainException as e: print(e.message)
控制台输出:
InvalidCookieDomainException: https://example.org/
解决方案
如果您存储了来自域 example.com
的 cookie,这些存储的 cookie 不能 通过 webdriver 会话推送到任何其他不同的域,例如example.edu
。存储的 cookie 只能在 example.com
内使用。此外,为了将来自动登录用户,您只需要存储 cookie 一次,即用户登录时。在添加回 cookie 之前,您需要浏览到收集 cookie 的同一域。
例子
例如,您可以在用户登录应用程序后存储 cookie,如下所示:
from selenium import webdriver
import pickle
driver = webdriver.Chrome()
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
driver.find_element_by_name("username").send_keys("abc123")
driver.find_element_by_name("password").send_keys("123xyz")
driver.find_element_by_name("submit").click()
# storing the cookies
pickle.dump( driver.get_cookies() , open("cookies.pkl","wb"))
driver.quit()
以后如果你想让用户自动登录,你需要先浏览到特定的域/url然后你必须添加cookie如下:
from selenium import webdriver
import pickle
driver = webdriver.Chrome()
driver.get('http://demo.guru99.com/test/cookie/selenium_aut.php')
# loading the stored cookies
cookies = pickle.load(open("cookies.pkl", "rb"))
for cookie in cookies:
# adding the cookies to the session through webdriver instance
driver.add_cookie(cookie)
driver.get('http://demo.guru99.com/test/cookie/selenium_cookie.php')
额外考虑
您似乎在使用 chrome=77.0.3865.75。理想情况下,您需要确保:
- Selenium 已升级到当前级别 Version 3.141.59。
- Chrome驱动程序 已更新至当前 ChromeDriver v79.0.3945.36 级别。
- Chrome 已更新为当前 Chrome 版本 79.0 级别。 (根据 ChromeDriver v79.0 release notes)
参考
您可以在以下位置找到详细讨论:
- Error when loading cookies into a Python request session
在 selenium 中我们必须使用测试服务器的 URL 默认情况下这是 localhost,以启用对外部可访问服务器地址的访问,该地址是我们需要使用的托管 docker 容器的地址服务器机器的IP地址, 所以设置如下,
class BaseTestCase(StaticLiveServerTestCase):
"""
Provides base test class which connects to the Docker
container running Selenium.
"""
host = '0.0.0.0' # Bind to 0.0.0.0 to allow external access
@classmethod
def setUpClass(cls):
super().setUpClass()
# Set host to externally accessible web server address
cls.host = socket.gethostbyname(socket.gethostname())
引用here
我运行遇到了同样的问题。我的解决方案只是避免在 cookie 中设置 domain
值(wich is optional,顺便说一句)。
class MyTestCase(StaticLiveServerTestCase):
host = os.environ['DJANGO_CONTAINER_NAME']
def test_logged_in(self):
self.client.login(username="integration", password="test")
self.selenium.get(self.live_server_url)
self.selenium.add_cookie({"name": settings.SESSION_COOKIE_NAME,
"value": self.client.cookies[settings.SESSION_COOKIE_NAME].value})
post = Post.objects.first()
self.selenium.get(f"{self.live_server_url}{reverse('post', args=(post.slug, ))}")
这里的要点是让 Django 客户端(此处 self.client
)登录,然后将其会话 cookie 复制到 Selenium 浏览器会话,该会话应该已经从您的实时服务器访问过一个页面 - 在其他情况下话说,先让Selenium浏览器打开一个页面,然后设置cookie(跳过domain
),然后,selenium浏览器就登录了。