Django StaticLiveServerTestCase有时以以下结尾:远程主机强制关闭了现有连接



在我刚创建的Django应用程序中,我将其更改为使用PostgreSQL,并创建了一个应用程序,我有以下测试:

from django.contrib.auth.models import User
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

class TestWebBrowser(StaticLiveServerTestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.webdriver = webdriver.Chrome()
        cls.webdriver.implicitly_wait(10)
    @classmethod
    def tearDownClass(cls):
        cls.webdriver.close()
        cls.webdriver.quit()
        super().tearDownClass()
    def setUp(self):
        self.admin = User.objects.create_superuser(username="username", password="password",
                                                   email="example@example.com")
    def test_log_in(self):
        self.webdriver.get(f"{self.live_server_url}/admin")
        self.webdriver.find_element_by_id("id_username").send_keys("username")
        self.webdriver.find_element_by_id("id_password").send_keys("password")
        self.webdriver.find_element_by_id("id_password").send_keys(Keys.RETURN)
        self.webdriver.find_element_by_link_text("Users").click()

测试总是运行,Chrome启动,按照测试的要求进行,但在最后,有时会抛出以下错误:

Exception happened during processing of request from ('127.0.0.1', 55283)
Traceback (most recent call last):
  File "C:Userspupenoscoopappspythoncurrentlibsocketserver.py", line 647, in process_request_thread
    self.finish_request(request, client_address)
  File "C:Userspupenoscoopappspythoncurrentlibsocketserver.py", line 357, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:Userspupenoscoopappspythoncurrentlibsocketserver.py", line 717, in __init__
    self.handle()
  File "C:UserspupenoTemporaryuntitledvenvlibsite-packagesdjangocoreserversbasehttp.py", line 139, in handle
    self.raw_requestline = self.rfile.readline(65537)
  File "C:Userspupenoscoopappspythoncurrentlibsocket.py", line 589, in readinto
    return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

所有测试都通过了。我只是把它拿到STDERR。有什么想法吗?我是不是错过了一些撕扯?

如果我将tearDownClass更改为:

@classmethod
def tearDownClass(cls):
    cls.webdriver.quit()

我在相同的频率下得到了相同的误差(据我所能观察到的,没有测量过(。

我正在运行:

Django==2.1.2
selenium==3.141.0

> chromedriver.exe --version
ChromeDriver 2.43.600210 (68dcf5eebde37173d4027fa8635e332711d2874a)

Google Chrome Version 70.0.3538.102 (Official Build) (64-bit)

运行测试的完整输出如下所示:

Testing started at 15:33 ...
C:UserspupenoTemporaryuntitledvenvScriptspython.exe "C:Program FilesJetBrainsPyCharm 2018.2.4helperspycharmdjango_test_manage.py" test foo.tests.TestImportCRMData C:UserspupenoTemporaryuntitled
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 49825)
Traceback (most recent call last):
  File "C:Userspupenoscoopappspythoncurrentlibsocketserver.py", line 647, in process_request_thread
    self.finish_request(request, client_address)
  File "C:Userspupenoscoopappspythoncurrentlibsocketserver.py", line 357, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:Userspupenoscoopappspythoncurrentlibsocketserver.py", line 717, in __init__
    self.handle()
  File "C:UserspupenoTemporaryuntitledvenvlibsite-packagesdjangocoreserversbasehttp.py", line 139, in handle
    self.raw_requestline = self.rfile.readline(65537)
  File "C:Userspupenoscoopappspythoncurrentlibsocket.py", line 589, in readinto
    return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
----------------------------------------
Destroying test database for alias 'default'...
Process finished with exit code 0

此错误消息。。。

ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

意味着ChromeDriver无法与网络浏览会话通信,即Chrome浏览器会话,因为它被远程主机强制关闭。


您的主要问题是webdriver.close()webdriver.quit()形式的多次调用

当根据最佳实践通过Selenium自动终止连接时,您应该始终调用tearDown(){}方法中的driver.quit()来关闭&优雅地销毁WebDriverWeb客户端实例。调用quit()方法DELETE通过发送带有{"flags":["eForceQuit"]}"quit">命令来启动当前浏览会话,并最终在/shutdownEndPoint上发送GET请求。下面是一个例子:

1503397488598   webdriver::server   DEBUG   -> DELETE /session/8e457516-3335-4d3b-9140-53fb52aa8b74 
1503397488607   geckodriver::marionette TRACE   -> 37:[0,4,"quit",{"flags":["eForceQuit"]}]
1503397488821   webdriver::server   DEBUG   -> GET /shutdown

因此,在调用quit()方法时,Web Browser会话和WebDriver实例将被完全杀死。因此,您不必包含任何额外的步骤(调用close()(,这将是主流标准的开销。


解决方案

首先,您删除以下行:

cls.webdriver.close()

下一行:

cls.webdriver.quit()

必然会以最佳方式终止连接。

在这里,您可以找到关于Selenium的详细讨论:如何在不调用driver.quit((的情况下阻止geckodriver进程影响PC内存?


更新A

根据liveservertestcase,tearDownClass()@classmethod定义为:

@classmethod
def tearDownClass(cls):
    cls.selenium.quit()
    super().tearDownClass()

根据django/django/test/testcases.py,这被称为:

@classmethod
def tearDownClass(cls):
    cls._tearDownClassInternal()
    cls._live_server_modified_settings.disable()
    super().tearDownClass()

更新B

虽然你提到过:

  • 使用ChromeDriver 2.43.600210
  • 使用Google Chrome版本70.0.3538.102

根据ChromeDriver v2.43:的发行说明

支持Chrome v69-71

  • 因此它们是兼容的,但您的机器中可能安装了多个Google Chrome,并且当执行以下行时会调用不匹配的GoogleChromebinary版本:

    cls.webdriver = webdriver.Chrome()
    

解决方案

确保:

  • 升级到当前版本3.141.59
  • ChromeDriver更新为当前ChromeDriverv79.0.3945.36版本
  • Chrome更新到当前Chrome 79.0版本。(根据ChromeDriver v79.0发布说明(
  • 通过IDE清理您的项目工作区,并仅使用所需的依赖项重建项目
  • (仅限WindowsOS(使用CCleaner工具,在执行测试套件前后清除所有操作系统杂务
  • (仅限LinuxOS(在执行测试套件之前和之后,释放Ubuntu/Linux Mint中未使用的/缓存的内存
  • 如果您的基本Web客户端版本太旧,请将其卸载并安装最新的GA和发布的Web客户端版本
  • 进行系统重新启动
  • 非root用户身份执行您的@Test
  • 总是调用CCD_ 17方法中的CCD_;优雅地销毁WebDriverWeb客户端实例

参考

你可以在中找到一些相关的讨论

  • urlib3.exceptions.ProtocolError:("连接中止。",error(10054,"远程主机强制关闭了现有连接"(

相关内容

  • 没有找到相关文章

最新更新