GUI 和无头浏览器测试

本指南涵盖的内容 #

本指南涵盖了使用 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_USERNAMESAUCE_ACCESS_KEY 环境变量,并将连接到集线器 URL 的连接转发回 Sauce Labs。

这就是您在 Sauce Labs 上运行 Selenium 测试所需的一切。但是,您可能希望仅在 Travis CI 构建中使用 Sauce Labs,而不是在本地构建中使用。为此,您可以使用 CITRAVIS 环境变量来有条件地更改您正在使用的驱动程序(有关检测您是否在 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: xenialdist: 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.ymlbefore_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 构建上的 stablebeta,以及 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 配置文件 文档。