Selenium在运行约500个测试后崩溃
我正在尝试运行一些动态生成的测试。这些测试在大约500次之前都运行得很好,但之后就出现了下面的错误。有没有人遇到过这种情况?
ChromeDriver executable needs to be available in the path.
我在想这可能是机器配置的问题。我有一台支持超线程的i5处理器和8GB的内存。通过观察系统监视器,我发现内存使用量从来没有超过6GB,CPU的任何核心也从未达到100%。我是在运行Linux Mint。
我尝试在浏览器关闭后添加超时设置,但似乎没有什么效果。我注意到有很多ChromeDriver进程。这个进程是不是有什么限制?
任何帮助都将不胜感激。
4 个回答
我找到了一些建议,内容在这里,说的是:
对于Linux系统,可以把chromedriver放在/usr/bin目录下。
而对于Windows系统,建议把chromedriver放在/Python27/Scripts目录下。
不过我在Windows 7上的经验是,把driver.exe文件,比如chromedriver.exe和IEDriverServer.exe直接放在/Python27/目录下就能正常工作。
我找到的解决办法可能不是最好的,但对我现在的需求来说,效果还不错。我做的就是把原来用的chromedriver换成了Firefox的驱动,现在所有的测试在Firefox上都能顺利执行,没有任何问题。
卡尔纳注意到,这听起来像是之前的测试驱动程序实例没有被清理干净。
你现在是通过以下方式关闭浏览器的吗:
driver.close()
有没有可能是这样?
如果是的话,可以试试:
driver.quit()
这样做可以同时关闭浏览器窗口和退出驱动程序。如果你已经在这样做,那我就不太明白为什么驱动程序还会留着了 :(
简短回答
更新:确认了两个错误,已经在主版本中修复,具体可以查看 这里 和 这里;这些修复在版本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 ... 打开的文件过多
出于某种原因,stdout
和stderr
没有关闭。
我可以通过以下测试文件重复多次来强制触发这个错误。
# 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个文件可以使用。