为什么 PhantomJS 无法在 Travis CI 基于容器的基础设施上工作?

Why might PhantomJS fail to work on the Travis CI container-based infrastructure?

我正在使用 Spiderling 和 PHPUnit 对 PHP 项目进行功能测试,通常使用 PhantomJS 作为底层浏览器。这在使用遗留基础设施的 Travis CI 中完全正常。

我已在 .travis.yml 中切换到 sudo: false 以尝试迁移到基于 Docker 的基础架构,但所有基于 PhantomJS 的测试都失败了。事实上,我添加了两个新的简单测试,发现如果将 Spiderling 切换为简单的基于 cURL 的获取,一切都很好:

/**
 * Check to see if any tests are working on Travis containers
 * 
 * (This succeeds)
 * 
 * @driver simple
 */
public function testAnythingAtAllSimple()
{
    $text = $this->visit(self::DOMAIN)->find('.container')->text();
    $this->assertContains('Questions about this site', $text);
}

/**
 * Check to see if any tests are working on Travis containers
 * 
 * (This fails - identical except for the driver)
 * 
 * @driver phantomjs
 */
public function testAnythingAtAllPhantom()
{
    $text = $this->visit(self::DOMAIN)->find('.container')->text();
    $this->assertContains('Questions about this site', $text);
}

我的 Travis YAML 配置是这样的:

language: php
sudo: false
php:
  - "5.6"
notifications:
  email: false
before_script:
  - phantomjs --help
  - composer self-update
  - COMPOSER=composer.travis.json composer install
  - git submodule init
  - git submodule update
  - npm install bower
  - bower install
  - mysql -u root < test/build/create-user.sql
  - export PATH=`pwd`/bin:$PATH
  - cp config/env-config.php.example config/env-config.php
  - touch /tmp/phantom-awooga.log
script:
  - phpunit --coverage-clover=coverage.clover
  - wget https://scrutinizer-ci.com/ocular.phar
  - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
  - cat /tmp/phantom-awooga.log
  - cat /tmp/awooga-screenshot-data.log

我添加了 phantomjs --help 以证明 PhantomJS 在这个新的基础架构中确实可用,并且这会按预期呈现通常的帮助输出。我不是自己安装它 - 它是 Travis 构建机器中的默认安装。

在另一个测试中,我在 $this->visit() 之后尝试了 sleep(3),这没有区别。我想知道 Phantom 是否只是需要更多时间在新环境中安顿下来。

我也试过 Spiderling/Phantom 截屏功能,我只得到一个大的透明图像(它是一个有效的 PNG,但上面没有任何内容)。

我想知道 Spiderling 是否不小心抑制了导致困难的 PhantomJS 中的一些错误? PhantomJS 确实启动正确,只是不会呈现。我已经以编程方式打开连接日志记录,并且记录正常,但没有明显的错误消息:

Starting server on port 4516
Recieved command  POST /url http://localhost:8090
  Executing command  POST /url http://localhost:8090
http://localhost:8090 fail
Recieved command  POST /elements .//descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' container ')]
  Executing command  POST /elements .//descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' container ')]
Recieved command  POST /elements .//descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' container ')]
  Executing command  POST /elements .//descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' container ')]
Recieved command  POST /elements .//descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' container ')]
  Executing command  POST /elements .//descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' container ')]

http://localhost:8090 fail看起来不太好,但并不能说明问题所在

我对新基建的理解有限,只是sudo是不允许的。但是我在构建中的任何地方都没有使用 root 权限。

这个问题不太重要,因为测试在遗留基础设施上运行良好。然而,由于它是 "legacy",我认为它会在某个时候被撤回,所以如果可能的话让它工作是有意义的。

PhantomJS 提供了一个 --debug 开关,但不幸的是 Spiderling 没有提供一种干净的方式来添加它。因此,我使用 post-Composer hack 来覆盖 Travis 配置中的必要文​​件,这种方法确实会导致在日志中附加 DEBUG 信息。但是,我看不到任何有用的东西。

因为这可能是 Travis 的问题,所以我 raised a bug。同时,我们欢迎任何关于可能导致此问题的遗留环境和容器环境差异的观察。

遇到同样问题的人:

显然,在将主机名 localhost 解析为 IP 127.0.0.1 时,测试中的客户端和 Web 服务器之间似乎存在任何错误。这个错误可能在 PhantomJS 或 PHP 中,因为直接调用 curl 可以正常工作。

最简单的 fix/workaround 是修改测试以调用 http://127.0.0.1:port 并修改服务器配置以侦听 127.0.0.1。由于不需要将主机名解析为环回 IP,因此客户端从 PHP-builtin 网络服务器获取网页没有问题。