GUI 和无头浏览器测试
- 本指南涵盖的内容
- 使用 Sauce Labs
- 使用 xvfb 运行需要 GUI 的测试
- 使用 Chrome 插件 的无头模式
- 使用 Firefox 插件 的无头模式
- 使用 PhantomJS
- 示例
- 故障排除
本指南涵盖的内容 #
本指南涵盖了使用 Travis CI 环境 提供的工具进行的无头 GUI 和浏览器测试。大部分内容与技术无关,并且没有涵盖特定测试工具(如 Poltergeist 或 Capybara)的所有细节。我们建议您在阅读本指南之前先阅读 教程 和 构建配置 指南。
使用 Sauce Labs #
Sauce Labs 提供了一个 Selenium 云,可以访问超过 170 种不同的设备/操作系统/浏览器组合。如果您有使用 Selenium 的浏览器测试,使用 Sauce Labs 运行测试非常容易。首先,您需要注册他们的服务(开源项目免费)。
注册后,使用 Sauce Connect 设置一个隧道,以便 Sauce Labs 可以连接到您的 Web 服务器。我们的 Sauce Connect 插件 使此操作变得简单,只需将其添加到您的 .travis.yml 中即可。
addons:
sauce_connect:
username: "Your Sauce Labs username"
access_key: "Your Sauce Labs access key"
如果您愿意,可以 加密您的访问密钥。
现在 Sauce Labs 有了一种访问您的 Web 服务器的方法,但您仍然需要启动它。有关如何执行此操作的更多信息,请参见下面的 启动 Web 服务器。
最后,您需要配置您的 Selenium 测试以在 Sauce Labs 上运行而不是本地运行。这可以通过使用 远程 WebDriver 来完成。确切的代码取决于您使用的工具/平台,但对于 Python,它看起来像这样
username = os.environ["SAUCE_USERNAME"]
access_key = os.environ["SAUCE_ACCESS_KEY"]
capabilities["tunnel-identifier"] = os.environ["TRAVIS_JOB_NUMBER"]
hub_url = "%s:%s@localhost:4445" % (username, access_key)
driver = webdriver.Remote(desired_capabilities=capabilities, command_executor="http://%s/wd/hub" % hub_url)
Sauce Connect 插件导出 SAUCE_USERNAME
和 SAUCE_ACCESS_KEY
环境变量,并将连接到集线器 URL 的连接转发回 Sauce Labs。
这就是您在 Sauce Labs 上运行 Selenium 测试所需的一切。但是,您可能希望仅在 Travis CI 构建中使用 Sauce Labs,而不是在本地构建中使用。为此,您可以使用 CI
或 TRAVIS
环境变量来有条件地更改您正在使用的驱动程序(有关检测您是否在 Travis CI 上运行的更多方法,请参见 我们提供的可用环境变量列表)。
为了使 Sauce Labs 上的测试结果更易于导航,您可能希望提供更多元数据以与构建一起发送。您可以通过传递更多所需的功能来做到这一点
capabilities["build"] = os.environ["TRAVIS_BUILD_NUMBER"]
capabilities["tags"] = [os.environ["TRAVIS_PYTHON_VERSION"], "CI"]
对于我们的网站 travis-web,我们使用 Sauce Labs 在多个浏览器上运行浏览器测试。我们在我们的 .travis.yml 中使用环境变量将构建拆分为多个作业,然后使用 所需功能 将所需的浏览器传递给 Sauce Labs。在 Travis CI 方面,它最终看起来像 这样。
使用 xvfb 运行需要 GUI 的测试 #
要在 Travis CI 上运行需要图形用户界面的测试,请使用 xvfb
(X 虚拟帧缓冲区)来模拟显示器。如果您需要浏览器,您可以使用 Firefox(使用预安装的版本或 插件)或 Google Chrome(使用 插件,在 Linux Trusty 或 macOS 上)。
使用 services:
#
这仅适用于 Ubuntu 16.04(Xenial)及更高版本,即使用
dist: xenial
或dist: bionic
以下操作将启动 xvfb 并为 DISPLAY
环境变量设置正确的值
dist: xenial
services:
- xvfb
使用 xvfb-run 包装器 #
xvfb-run
是用于调用 xvfb
的包装器,以便可以更轻松地使用 xvfb
script: xvfb-run make test
设置屏幕分辨率
script: xvfb-run --server-args="-screen 0 1024x768x24" make test
直接使用 xvfb #
建议在 Ubuntu 14.04(Trusty)上使用,即使用
dist: trusty
。对于dist: xenial
,请使用上面 描述的services
关键字。
要使用 xvfb
本身,请在 .travis.yml
的 before_script
部分启动它
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start
注意:不要直接运行 xvfb
,因为它不会以这种方式处理多个并发实例。
如果需要设置屏幕大小和像素深度,则需要使用 start-stop-daemon
实用程序启动 xvfb
,而不是使用前面示例中的 init 脚本。
例如,要将屏幕分辨率设置为 1280x1024x16
before_install:
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
有关更多信息,请参见 xvfb 手册页。
启动 Web 服务器 #
如果您的项目需要运行 Web 应用程序才能进行测试,则需要在运行测试之前启动一个。通常使用 Ruby、Node.js 和基于 JVM 的 Web 服务器来提供用于运行测试套件的 HTML 页面。因为每个构建环境至少提供了一个版本的 Ruby、Node.js 和 OpenJDK,所以您可以依赖这三个选项之一。
添加一个 before_script
来启动服务器,例如
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start
- rackup # start a Web server
- sleep 3 # give Web server some time to bind to sockets, etc
如果需要 Web 服务器侦听端口 80,请记住使用 sudo
(Linux 不允许非特权进程绑定到端口 80)。对于大于 1024 的端口,不需要(也不建议)使用 sudo
。
sudo
不可用。使用 Chrome 插件 的无头模式 #
从 Linux Trusty 的版本 57 和 macOS 的版本 59 开始,Google Chrome 可以以“无头”模式使用,这适用于使用 Selenium 和其他工具驱动基于浏览器的测试。
截至 2017-05-02,这意味着 Linux 构建上的
stable
或beta
,以及 macOS 构建上的beta
。
例如,在 Linux 上
dist: xenial
addons:
chrome: stable
before_install:
- # start your web application and listen on `localhost`
- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &
⋮
在 macOS 上
language: objective-c
addons:
chrome: beta
before_install:
- # start your web application and listen on `localhost`
- "/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --headless --disable-gpu --remote-debugging-port=9222 http://localhost &"
⋮
文档 #
使用 Firefox 插件 的无头模式 #
从 Firefox 56 版本开始,可以使用“无头”模式,该模式适用于使用 Selenium 和其他工具驱动基于浏览器的测试。可以使用 MOZ_HEADLESS
环境变量启用无头模式。
env:
global:
- MOZ_HEADLESS=1
addons:
firefox: latest
或者,您可以在启动 Firefox 时传递 -headless
命令行参数。例如,以下代码演示了如何使用 Selenium 的 Python 客户端设置此参数。
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
options = Options()
options.add_argument('-headless')
firefox = Firefox(firefox_options=options)
#### 文档
使用 PhantomJS #
PhantomJS 是一个带有 JavaScript API 的无头 WebKit。它是快速无头测试、网站抓取、页面捕获、SVG 渲染器、网络监控和许多其他用例的最佳解决方案。
CI 环境 预装了 PhantomJS(在 PATH 中可用,为 phantomjs
;不要依赖于确切的位置)。由于它是完全无头的,因此无需运行 xvfb
。
一个非常简单的示例
script: phantomjs testrunner.js
如果您需要 Web 服务器来提供测试,请参阅上一节。
示例 #
真实世界项目 #
- Ember.js(以编程方式启动 Web 服务器)
- Sproutcore(使用 before_script 启动 Web 服务器)
Ruby #
RSpec、Jasmine、Cucumber #
这是一个运行 Rspec、Jasmine 和 Cucumber 测试的 rake 任务示例
task :travis do
["rspec spec", "rake jasmine:ci", "rake cucumber"].each do |cmd|
puts "Starting to run #{cmd}..."
system("export DISPLAY=:99.0 && bundle exec #{cmd}")
raise "#{cmd} failed!" unless $?.exitstatus == 0
end
end
在此示例中,Jasmine 和 Cucumber 都需要显示端口,因为它们都使用真实的浏览器。RSpec 可以无需它运行,但设置它也没有坏处。
故障排除 #
Selenium 和 Firefox 弹出窗口 #
如果您的测试套件处理模态对话框弹出窗口,例如 重定向到另一个位置,则可能需要添加自定义配置文件以抑制弹出窗口。
可以通过应用具有关闭选项的自定义 Firefox 配置文件来解决此问题:(示例使用 Capybara 在 Ruby 中)
Capybara.register_driver :selenium do |app|
custom_profile = Selenium::WebDriver::Firefox::Profile.new
# Turn off the super annoying popup!
custom_profile["network.http.prompt-temp-redirect"] = false
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => custom_profile)
end
Karma 和 Firefox 空闲超时 #
使用 Karma 和 Firefox 进行测试时,您可能会遇到由于浏览器空闲超时导致的构建错误。发生这种情况时,Karma 将输出类似于以下内容的错误
WARN [Firefox 31.0.0 (Linux)]: Disconnected (1 times), because no message in 10000 ms.
在这种情况下,您应该在 karma.conf.js
中将浏览器空闲超时增加到更高的值,例如
browserNoActivityTimeout: 30000,
有关更多信息,请参阅 Karma 配置文件 文档。