Selenium在运行约500个测试后崩溃

1 投票
4 回答
2811 浏览
提问于 2025-04-17 21:05

我正在尝试运行一些动态生成的测试。这些测试在大约500次之前都运行得很好,但之后就出现了下面的错误。有没有人遇到过这种情况?

ChromeDriver executable needs to be available in the path.  

我在想这可能是机器配置的问题。我有一台支持超线程的i5处理器和8GB的内存。通过观察系统监视器,我发现内存使用量从来没有超过6GB,CPU的任何核心也从未达到100%。我是在运行Linux Mint。

我尝试在浏览器关闭后添加超时设置,但似乎没有什么效果。我注意到有很多ChromeDriver进程。这个进程是不是有什么限制?

任何帮助都将不胜感激。

4 个回答

0

我找到了一些建议,内容在这里,说的是:
对于Linux系统,可以把chromedriver放在/usr/bin目录下。
而对于Windows系统,建议把chromedriver放在/Python27/Scripts目录下。

不过我在Windows 7上的经验是,把driver.exe文件,比如chromedriver.exe和IEDriverServer.exe直接放在/Python27/目录下就能正常工作。

0

我找到的解决办法可能不是最好的,但对我现在的需求来说,效果还不错。我做的就是把原来用的chromedriver换成了Firefox的驱动,现在所有的测试在Firefox上都能顺利执行,没有任何问题。

0

卡尔纳注意到,这听起来像是之前的测试驱动程序实例没有被清理干净。

你现在是通过以下方式关闭浏览器的吗:

driver.close()

有没有可能是这样?

如果是的话,可以试试:

driver.quit()

这样做可以同时关闭浏览器窗口和退出驱动程序。如果你已经在这样做,那我就不太明白为什么驱动程序还会留着了 :(

4

简短回答

更新:确认了两个错误,已经在主版本中修复,具体可以查看 这里这里;这些修复在版本2.46.0中发布。以下内容与2.45及之前版本相关。

看起来nose和/或selenium中有一个错误。我在使用nose运行测试时能重现这个错误;我怀疑还有其他方式也能触发它。

如果你需要在错误修复之前找到解决方案,可以尝试以下方法:

  • 增加允许打开的最大文件数量... 或者 ...
  • ... 修改你的site-packages/selenium/webdriver/chrome/service.py文件

我猜你的机器上运行ulimit -n的输出是1024。为什么这么想呢?因为500 * 2接近1024(而且这是一个常见的设置)... 继续往下看。


详细回答

这是一个微妙的错误,只有在特定的测试方式和环境限制下才会发生。

这个错误难以识别的原因是selenium的一个bug导致错误信息不正确。

错误 #1 ... 异常处理过于宽泛

selenium通过使用过于宽泛的异常来隐藏真正的错误。如果你的测试在前122次运行中都通过(就像我一样),然后在后续的每次测试中都失败,并显示ChromeDriver executable needs to be available in the path... 那么肯定有什么奇怪的事情发生了。显然,在前122(或500)次测试中,你的chromedriver是放在正确路径下的。

所以我们需要获取真正的错误信息,告诉selenium不要假设每个抛出的异常都是因为chromedriver不在PATH环境变量中。

修改site-packages/selenium/webdriver/chrome/service.py中的start方法

从:

try:
    self.process = subprocess.Popen([
      self.path,
      "--port=%d" % self.port] +
      self.service_args, env=env, stdout=PIPE, stderr=PIPE)
except:
    raise WebDriverException(
        "'" + os.path.basename(self.path) + "' executable needs to be \
        available in the path. Please look at \
        http://docs.seleniumhq.org/download/#thirdPartyDrivers \
        and read up at \
        http://code.google.com/p/selenium/wiki/ChromeDriver")

到:

try:
    self.process = subprocess.Popen([
      self.path,
      "--port=%d" % self.port] +
      self.service_args, env=env, stdout=PIPE, stderr=PIPE)
except:
    # let all exceptions reach the user, with error type and message
    # for demonstration purposes only
    raise  

现在,重新运行你的500个测试。你会得到一个更有帮助的错误信息,可能是:OSError: [Errno 24] Too many open files

错误 #2 ... 打开的文件过多

出于某种原因,stdoutstderr没有关闭。

我可以通过以下测试文件重复多次来强制触发这个错误。

# bash to duplicate: 
# for i in `seq 1 130`
# do
#    cp test_std_close.py test_std_close_$(printf %03d ${i}).py
# done

import unittest 
from selenium import webdriver

class TestStdClose(unittest.TestCase):

    def test_std_close(self):
        driver = webdriver.Chrome();
        driver.get('https://google.com');
        driver.close()

如果我在一个目录中放入130个这样的文件(test_001.py, test_002.py等),然后运行nosetests std_test/test*py

我在第122个测试时会失败,就像我正常的测试套件一样。你可能需要运行500次才能重现你的错误。

解决方案

解决方法是增加允许打开的最大文件数量,或者修改site-packages/selenium/webdriver/chrome/service.py中的stop方法

从:

try:
    if self.process:
        self.process.kill()
        self.process.wait()
except OSError:
    # kill may not be available under windows environment
    pass

到:

try:
    if self.process:
        self.process.stdout.close()  # add this line
        self.process.stderr.close()  # and this one
        self.process.kill()
        self.process.wait()
except OSError:
    # kill may not be available under windows environment
    pass

这两种方法都能确保我的160个测试在各种Mac OS配置(10.6, 10.9, 10.10)上都能执行。

我正在提交错误报告和补丁给selenium;问题的根源可能在其他地方,但这两项更改修复了我的测试套件(通过nose运行)。

结论

那么,为什么在你这里大约500次后会失败?我猜ulimit -n在你的机器上报告的是1024。一些数学计算:500 * 2(stdout, stderr)== 1000,剩下24个文件可以使用。

那么,为什么在我这里大约122次后会失败?因为在我的Mavericks MacBook Pro上,ulimit -n报告的是256。一些数学计算:122 * 2 == 244,剩下12个文件可以使用。

撰写回答