You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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):
    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')
            # ...其他代码
    
    Docker网络内的容器可通过服务名互相访问,避免因主机IP无法解析导致的访问问题。

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详细日志,排查页面加载问题:
    options.add_argument('--verbose')
    options.add_argument('--log-path=/tmp/chrome.log')
    
    进入Selenium容器查看/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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 00:20:35