Django测试中Docker Selenium无法跳转页面问题求助
问题:Docker环境下Django Selenium测试表单提交后URL等待超时
本地使用Operadriver的Selenium测试时,表单提交后页面跳转正常,但在Docker环境的Django Selenium测试中,执行WebDriverWait(driver, 10).until(EC.url_changes(current_url))时出现selenium.common.exceptions.TimeoutException: Message:超时错误。
测试代码如下:
import os import socket import shutil # from pyvirtualdisplay import Display from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.chrome.options import Options from django.test import LiveServerTestCase from django.conf import settings # Create your tests here. class LandFormTest(LiveServerTestCase): host = socket.gethostbyname(socket.gethostname()) def setUp(cls): selenium_url = 'http://selenium:4444/wd/hub' options = Options() options.add_argument('--no-sandbox') options.add_argument('--headless') options.add_argument("--disable-dev-shm-usage") options.add_argument("--ignore-certificate-errors") # options.add_argument("My user agent") options.add_argument(f"window-size=1920,1080") cls.driver = webdriver.Remote( command_executor=selenium_url, desired_capabilities=DesiredCapabilities.CHROME, options=options ) def test_form(self): try: driver = self.driver domain = self.live_server_url.split('//')[1].split(':')[0] if not settings.BASE_DIR.joinpath(f'templates/lands/{domain}').is_dir(): src = f'templates/lands/quantum.localhost' dest = f'templates/lands/{domain}' shutil.copytree(src, dest) driver.get(f'{self.live_server_url}/api/v1/test/?ai=2&gi=5') user_firstname = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.NAME, "firstname")) ) current_url = driver.current_url user_firstname = driver.find_element(By.NAME, 'firstname') user_lastname = driver.find_element(By.NAME, 'lastname') user_email = driver.find_element(By.NAME, 'email') user_phone = driver.find_element(By.NAME, 'phone') user_firstname.send_keys('test') user_lastname.send_keys('test') user_email.send_keys('test@gmail.com') user_phone.send_keys('+(846)411-36-00') user_phone.submit() WebDriverWait(driver, 10).until(EC.url_changes(current_url)) print(driver.current_url) print(driver.page_source) assert 'Hello World' in driver.page_source except Exception as e: raise(e) def tearDown(self): self.driver.quit()
注:/api/v1/test/路由会根据域名获取静态文件和模板,已复制默认的"quantum.localhost"文件夹并重命名为Docker的IP,且尝试过Firefox Selenium,问题依旧。
排查与解决方案
1. 确认Docker容器间的网络可达性
- 确保Selenium容器和Django容器在同一个Docker网络内,否则Selenium容器无法访问Django服务的主机IP。
- 修改
LiveServerTestCase的host为0.0.0.0,并在测试中使用Docker服务名拼接URL(假设Django服务在docker-compose中名为web):
Docker网络内的容器可通过服务名互相访问,避免因主机IP无法解析导致的访问问题。class LandFormTest(LiveServerTestCase): host = '0.0.0.0' def test_form(self): # ...其他代码 driver.get(f'http://web:8000/api/v1/test/?ai=2&gi=5') # ...其他代码
2. 验证表单提交后的实际行为
- 临时注释
url_changes等待逻辑,直接打印提交后的driver.current_url和page_source,确认页面是否真的发生跳转。如果表单是AJAX异步提交,不会触发URL变化,此时url_changes会一直超时。 - 若为AJAX提交,改为等待目标内容出现:
# 替换原url_changes等待 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//*[contains(text(), 'Hello World')]")) )
3. 调整等待逻辑与日志排查
- 暂时延长等待时间至30秒,排除网络延迟影响:
WebDriverWait(driver, 30).until(EC.url_changes(current_url)) - 开启Chrome详细日志,排查页面加载问题:
进入Selenium容器查看options.add_argument('--verbose') options.add_argument('--log-path=/tmp/chrome.log')/tmp/chrome.log,确认是否有页面加载失败、资源报错等信息。
4. 检查模板复制逻辑
- 打印
domain值,确认模板文件夹是否正确复制:
若路径不存在,会返回错误页面,导致无跳转行为。print(f"当前域名:{domain}") print(f"模板路径存在:{settings.BASE_DIR.joinpath(f'templates/lands/{domain}').is_dir()}")
5. 更换表单提交方式
- 避免使用元素
submit()方法,改为直接点击表单提交按钮(若页面存在):
部分场景下,非提交按钮元素的# 替换原user_phone.submit() submit_btn = driver.find_element(By.CSS_SELECTOR, 'button[type="submit"]') submit_btn.click()submit()方法可能无法正确触发表单提交。
内容的提问来源于stack exchange,提问作者Banderosik
相关产品推荐
相关产品推荐

