为什么我的单元测试在 Chrome 驱动程序上工作,而不是 PhantomJS?

Why do my unittest work on Chrome driver, but not PhantomJS?

我正在 Selenium Pychon Bindings document 下编写我的第一个单元测试。

我使用 Chrome 驱动程序编写测试如下:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest

class PythonOrgSearch(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome(r"C:\chromedriver_win32\chromedriver")

    def test_search_in_python_org(self):
        driver = self.driver
        driver.get(r"http://www.python.org")
        self.assertIn("Python", driver.title)
        el = driver.find_element_by_name("q")
        el.send_keys("pycon")
        el = driver.find_element_by_id("submit")
        el.click()
        assert "No results found." not in driver.page_source

    def tearDown(self):
        self.driver.close()

if __name__ == "__main__":
    unittest.main()

运行 它在终端上运行。航站楼 returns:

.
----------------------------------------------------------------------
Ran 1 test in 7.873s

OK

但是如果我替换

self.driver = webdriver.Chrome(r"C:\chromedriver_win32\chromedriver")

self.driver = webdriver.PhantomJS(r"C:\phantomjs-2.1.1\bin\phantomjs")

代码如下

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest


class PythonOrgSearch(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.PhantomJS(r"C:\phantomjs-2.1.1\bin\phantomjs")


    def test_search_in_python_org(self):
        driver = self.driver
        driver.get(r"http://www.python.org")
        self.assertIn("Python", driver.title)
        el = driver.find_element_by_name("q")
        el.send_keys("pycon")
        el = driver.find_element_by_id("submit")
        el.click()
        assert "No results found." not in driver.page_source

    def tearDown(self):
        self.driver.close()


if __name__ == "__main__":
    unittest.main()

我的终端给我一个错误:

E
======================================================================
ERROR: test_search_in_python_org (__main__.PythonOrgSearch)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_python_org_search.py", line 24, in test_search_in_python_org
    el.click()
  File "C:\Program Files (x86)
    self._execute(Command.CLICK_ELEMENT)
  File "C:\Program Files (x86)
    return self._parent.execute(command, params)
  File "C:\Program Files (x86)
    self.error_handler.check_response(response)
  File "C:\Program Files (x86)    
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotVisibleException: Message: {"errorMessage":"Element is not   
"Content-Length":"81","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:50294",   
67e-433b649e227d\"}","url":"/click","urlParsed":{"anchor":"","query":"","file":"click",    
elative":"/click","port":"","host":"","password":"","user":"","userInfo":"","authority":"",    
","queryKey":{},"chunks":["click"]},    
46/click"}}
Screenshot: available via screen

----------------------------------------------------------------------
Ran 1 test in 6.214s

FAILED (errors=1)

有人能告诉我为什么我不能在 PhantomJS 中使用 click 吗?

使用 PhantomJS 时,屏幕截图是最有用的调试工具之一。我修改了您的脚本以在失败时记录屏幕截图:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import unittest


class PythonOrgSearch(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.PhantomJS()


    def test_search_in_python_org(self):
        driver = self.driver
        driver.get(r"http://www.python.org")
        self.assertIn("Python", driver.title)
        el = driver.find_element_by_name("q")
        el.send_keys("pycon")
        el = driver.find_element_by_id("submit")
        try:
            el.click()
        except:
            screenshot = driver.get_screenshot_as_png()
            with open('screenshot.png', 'wb') as w:
                w.write(screenshot)
        assert "No results found." not in driver.page_source

    def tearDown(self):
        self.driver.close()


if __name__ == "__main__":
    unittest.main()

当我 运行 它时,我得到 this screenshot

您会注意到该页面的呈现方式就像在移动浏览器上一样。使用 phantomjs 时,您应该设置浏览器 window 大小:

def setUp(self):
    self.driver = webdriver.PhantomJS()
    self.driver.set_window_size(800, 1000)

执行此操作并比较 chrome 和 phantom 渲染后,您会发现 phantom 未正确加载到提交按钮中:

一种解决方法是发送 ENTER 键,而不是单击按钮:

def test_search_in_python_org(self):
    driver = self.driver
    driver.set_window_size(800, 1000)
    driver.get(r"http://www.python.org")
    self.assertIn("Python", driver.title)
    el = driver.find_element_by_name("q")
    el.send_keys("pycon")
    el.send_keys(Keys.ENTER)
    screenshot = driver.get_screenshot_as_png()
    with open('screenshot2.png', 'wb') as w:
        w.write(screenshot)

通过上面的代码,我现在看到了结果:

值得注意的是,这就是为什么包括我在内的许多人不使用 PhantomJS 进行测试的原因。我发现使用 Chrome and/or Firefox 会更好,方法是 运行 将它们设置为自己的无头模式,或者使用虚拟帧缓冲区(如 Xvfb)。

我个人在基于云的 linux 实例上进行测试,并使用 pyvirtualdisplay with Xvfb 来管理我的虚拟显示器。两者都安装后,pyvirtualdisplay 将完全管理您的虚拟显示会话。要将它与上面的脚本一起使用,我将执行以下操作:

from pyvirtualdisplay import Display

class PythonOrgSearch(unittest.TestCase):

    def setUp(self):
        self.display = Display(visible=False, size=(1200, 1500))
        self.display.start()
        self.driver = webdriver.Chrome()


    def test_search_in_python_org(self):
        # Do test

    def tearDown(self):
        self.driver.close()
        self.display.stop()

综上所述,我没有使用 Windows 的经验,但我相信 OS

存在类似的配置