dunglas/panthere

此包已被弃用,不再维护。作者建议使用symfony/panther包。

PHP和Symfony的浏览器测试和网页抓取库。

维护者

详细信息

github.com/dunglas/panthere

主页

源码

资助包维护!
www.panthera.org/donate

dev-master / 1.0.x-dev 2019-08-22 14:24 UTC

README

PHP和Symfony的浏览器测试和网页抓取库。

Build Status Build status SensioLabsInsight

Panther是一个方便的独立库,用于抓取网站和运行使用真实浏览器的端到端测试。

Panther功能强大。它利用W3C的WebDriver协议来驱动Google Chrome和Firefox等原生浏览器。

Panther易于使用,因为它实现了Symfony流行的BrowserKitDomCrawler API,并包含您测试应用程序所需的所有功能。如果您曾经为Symfony应用程序创建过功能测试,它会听起来很熟悉,因为API完全相同!请注意,Panther可以作为独立库在任何PHP项目中使用。

Panther会自动找到您的本地Chrome安装并启动它(归功于ChromeDriver),因此您不需要在计算机上安装任何东西,既不需要Selenium服务器也不需要任何其他神秘的驱动程序。

在测试模式下,Panther会使用PHP内置的web服务器自动启动您的应用程序。您可以将重点放在编写测试或网页抓取场景上,而Panther会处理其他所有事情。

功能

与您习惯的测试和网页抓取库不同,Panther

  • 执行网页中包含的JavaScript代码
  • 支持Chrome(或Firefox)实现的任何功能
  • 允许截图
  • 可以等待异步加载的元素出现
  • 允许您在加载页面的上下文中运行自己的JS代码或XPath查询
  • 支持自定义Selenium服务器安装
  • 支持远程浏览器测试服务,包括SauceLabsBrowserStack

文档

安装

使用Composer在项目中安装Panther。如果您只想将Panther用于测试而不想在生产环境中用于网页抓取,请使用--dev标志。

composer req symfony/panther

composer req --dev symfony/panther

警告:在*nix系统上,必须安装unzip命令,否则您将遇到类似于RuntimeException: sh: 1: exec: /app/vendor/symfony/panther/src/ProcessManager/../../chromedriver-bin/chromedriver_linux64: Permission denied(或chromedriver_linux64: not found)的错误。根本原因是PHP的ZipArchive不保留UNIX可执行权限。

基本用法

<?php

require __DIR__.'/vendor/autoload.php'; // Composer's autoloader

$client = \Symfony\Component\Panther\Client::createChromeClient();
$crawler = $client->request('GET', 'https://api-platform.com'); // Yes, this website is 100% written in JavaScript

$crawler->clickLink('Support');

// Wait for an element to be rendered
$client->waitFor('.support');

echo $crawler->filter('.support')->text();
$client->takeScreenshot('screen.png'); // Yeah, screenshot!

测试用法

PantherTestCase类允许您轻松编写端到端测试。它自动使用内置的PHP网络服务器启动您的应用程序,并允许您使用Panther爬取它。为了提供您习惯的所有测试工具,它扩展了PHPUnitTestCase

如果您正在测试一个Symfony应用程序,PantherTestCase将自动扩展WebTestCase。这意味着您可以轻松创建功能测试,这些测试可以直接执行您的应用程序的内核并访问所有现有服务。在这种情况下,您可以使用Panther与Symfony提供的所有爬取测试断言。

<?php

namespace App\Tests;

use Symfony\Component\Panther\PantherTestCase;

class E2eTest extends PantherTestCase
{
    public function testMyApp(): void
    {
        $client = static::createPantherClient(); // Your app is automatically started using the built-in web server
        $client->request('GET', '/mypage');

        // Use any PHPUnit assertion, including the ones provided by Symfony
        $this->assertPageTitleContains('My Title');
        $this->assertSelectorTextContains('#main', 'My body');
    }
}

要运行此测试

phpunit tests/E2eTest.php

多态猫科动物

Panther还为您提供了即时访问其他基于BrowserKit的ClientCrawler实现。与Panther的本地客户端不同,这些替代客户端不支持JavaScript、CSS和截图捕获,但它们非常super-fast

有两个替代客户端可用

  • 第一个直接操作由WebTestCase提供的Symfony内核。这是最快的客户端,但它仅适用于Symfony应用程序。
  • 第二个利用了Goutte网络爬虫库。它在Symfony和Panther测试客户端之间是中间件。Goutte发送真实的HTTP请求。它很快,能够浏览任何网页,而不仅仅是测试应用程序的网页。然而,由于Goutte完全用PHP编写,它不支持JavaScript和其他高级功能。这个适用于非Symfony应用程序!

有趣的是,这3个客户端实现了完全相同的API,因此您只需调用适当的工厂方法即可从其中一个切换到另一个,为每个测试案例提供良好的权衡(我需要JavaScript吗?我需要通过外部SSO服务器进行身份验证吗?我想访问当前请求的内核吗?等等)。

以下是检索这些客户端实例的方法

<?php

namespace App\Tests;

use Symfony\Component\Panther\PantherTestCase;
use Symfony\Component\Panther\Client;

class E2eTest extends PantherTestCase
{
    public function testMyApp()
    {
        $symfonyClient = static::createClient(); // A cute kitty: Symfony's functional test tool
        $goutteClient = static::createGoutteClient(); // An agile lynx: Goutte
        $pantherClient = static::createPantherClient(); // A majestic Panther
        // Both Goutte and Panther benefits from the built-in HTTP server

        $customChromeClient = Client::createChromeClient(null, null, [], 'https://example.com'); // Create a custom Chrome client
        $customSeleniumClient = Client::createSeleniumClient('http://127.0.0.1:4444/wd/hub', null, 'https://example.com'); // Create a custom Selenium client
        // When initializing a custom client, the integrated web server IS NOT started automatically.
        // Use PantherTestCase::startWebServer() or WebServerManager if you want to start it manually.

        // enjoy the same API for the 3 felines
        // $*client->request('GET', '...')

        $kernel = static::createKernel(); // If you are testing a Symfony app, you also have access to the kernel

        // ...
    }
}

使用Mercure或WebSocket创建隔离的浏览器以测试应用程序

Panther提供了一种方便的方法来测试具有实时功能的应用程序,这些应用程序使用MercureWebSocket和类似技术。

PantherTestCase::createAdditionalPantherClient()创建额外的、隔离的浏览器,它们可以相互交互。例如,这可以用于测试具有多个同时连接的用户聊天应用程序。

<?php

use Symfony\Component\Panther\PantherTestCase;

class ChatTest extends PantherTestCase
{
    public function testChat(): void
    {
        $client1 = self::createPantherClient();
        $client1->request('GET', '/chat'); 
 
        // Connect a 2nd user using an isolated browser and say hi!
        $client2 = self::createAdditionalPantherClient();
        $client2->request('GET', '/chat');
        $client2->submitForm('Post message', ['message' => 'Hi folks 👋😻']);

        // Wait for the message to be received by the first client
        $client1->waitFor('.message');

        // Symfony Assertions are always executed in the **primary** browser
        $this->assertSelectorTextContains('.message', 'Hi folks 👋😻');
    }
}

附加文档

由于Panther实现了流行库的API,因此它已经有了广泛的文档。

环境变量

以下环境变量可以被设置以改变 Panther 的某些行为

  • PANTHER_NO_HEADLESS:用于禁用浏览器的无头模式(将显示测试窗口,有助于调试)
  • PANTHER_NO_SANDBOX:用于禁用 Chrome 的沙箱(不安全,但允许在容器中使用 Panther)
  • PANTHER_WEB_SERVER_DIR:用于更改项目的文档根目录(默认为 public/
  • PANTHER_CHROME_DRIVER_BINARY:用于使用另一个 chromedriver 二进制文件,而不是依赖 Panther 已提供的二进制文件
  • PANTHER_CHROME_ARGUMENTS:用于自定义 chromedriver 参数。您需要设置 PANTHER_NO_HEADLESS 以完全自定义。
  • PANTHER_WEB_SERVER_PORT:用于更改 web 服务器的端口(默认为 9080
  • PANTHER_WEB_SERVER_ROUTER:用于使用在每个 HTTP 请求开始时运行的 web 服务器路由脚本
  • PANTHER_EXTERNAL_BASE_URI:用于使用外部 web 服务器(PHP 内置的 web 服务器将不会被启动)
  • PANTHER_CHROME_BINARY:用于使用另一个 google-chrome 二进制文件

访问隐藏文本

根据规范,WebDriver 实现默认只返回 显示 的文本。当您在 head 标签(如 title)上筛选时,方法 text() 返回空字符串。使用方法 html() 获取标签的完整内容,包括标签本身。

交互模式

Panther 可以在测试套件失败后暂停。这是通过网页浏览器调查问题的真正休息时间。要启用此模式,您需要使用没有无头模式的 --debug PHPUnit 选项

$ export PANTHER_NO_HEADLESS=1
$ phpunit --debug

Test 'App\AdminTest::testLogin' started
Error: something is wrong.

Press enter to continue...

使用持久性 web 服务器提高性能

当您使用 Panther 客户端时,后台运行的 web 服务器将在第一次调用 createPantherClient()createGoutteClient()startWebServer() 时启动,并在 tearDownAfterClass() 中停止。

如果您想提高性能,您可以在 phpunit.xml.dist 配置文件中通过 Panther 的服务器扩展挂钩到 PHPUnit

<!-- phpunit.xml.dist -->
    <extensions>
        <extension class="Symfony\Component\Panther\ServerExtension" />
    </extensions>

此扩展将像以前一样按需启动 web 服务器,但在最后一个测试之后停止它。

应注意,Panther 的扩展仅与 PHPUnit >= 7.3 一起使用。尽管如此,如果您正在使用更早的 PHPUnit 版本,您也可以使用 Panther 的服务器监听器挂钩到 PHPUnit

<!-- phpunit.xml.dist -->
    <listeners>
        <listener class="Symfony\Component\Panther\ServerListener" />
    </listeners>

此监听器将像以前一样按需启动 web 服务器,但在每个测试套件之后停止它。

使用外部 web 服务器

有时,重新使用现有的 web 服务器配置而不是启动内置的 PHP 服务器会更方便。为此,设置 external_base_uri 选项

<?php

namespace App\Tests;

use Symfony\Component\Panther\PantherTestCase;

class E2eTest extends PantherTestCase
{
    public function testMyApp()
    {
        $pantherClient = static::createPantherClient(['external_base_uri' => 'https://localhost']);
        // the PHP integrated web server will not be started
    }
}

使用代理

要使用代理服务器,设置以下环境变量:PANTHER_CHROME_ARGUMENTS='--proxy-server=socks://127.0.0.1:9050'

接受自签名SSL证书

要强制Chrome接受无效和自签名证书,设置以下环境变量:PANTHER_CHROME_ARGUMENTS='--ignore-certificate-errors' 此选项不安全,仅在开发环境中进行测试时使用,切勿在生产环境中使用(例如,用于网络爬虫)。

Docker集成

以下是一个可以运行Panther的最小Docker镜像

FROM php:latest

RUN apt-get update && apt-get install -y libzip-dev zlib1g-dev chromium && docker-php-ext-install zip
ENV PANTHER_NO_SANDBOX 1

使用docker build . -t myproject构建它。使用docker run -it -v "$PWD":/srv/myproject -w /srv/myproject myproject bin/phpunit运行它

如果您正在使用Alpine Linux,您可能需要使用另一个chromedriver二进制文件。

RUN apk add --no-cache \
        chromium \
        chromium-chromedriver
ENV PANTHER_CHROME_DRIVER_BINARY /usr/lib/chromium/chromedriver

Travis CI集成

如果您添加了Chrome插件,Panther将与Travis无缝配合。以下是一个运行Panther测试的最小.travis.yml文件

language: php
addons:
  chrome: stable

php:
  - 7.1
  - 7.2

script:
  - phpunit

AppVeyor集成

只要安装了Google Chrome,Panther就会与AppVeyor无缝配合。以下是一个运行Panther测试的最小appveyor.yml文件

build: false
platform: x86
clone_folder: c:\projects\myproject

cache:
  - '%LOCALAPPDATA%\Composer\files'

install:
  - ps: Set-Service wuauserv -StartupType Manual
  - cinst -y php composer googlechrome
  - refreshenv
  - cd c:\tools\php73
  - copy php.ini-production php.ini /Y
  - echo date.timezone="UTC" >> php.ini
  - echo extension_dir=ext >> php.ini
  - echo extension=php_openssl.dll >> php.ini
  - echo extension=php_mbstring.dll >> php.ini
  - echo extension=php_curl.dll >> php.ini
  - echo memory_limit=3G >> php.ini
  - cd %APPVEYOR_BUILD_FOLDER%
  - composer install --no-interaction --no-progress

test_script:
  - cd %APPVEYOR_BUILD_FOLDER%
  - php vendor\phpunit\phpunit\phpunit

与其他测试工具一起使用

如果您想与其他测试工具(如LiipFunctionalTestBundle)一起使用Panther,或者如果您只需要使用不同的基类,Panther已经为您准备好了。它提供了Symfony\Component\Panther\PantherTestCaseTrait,您可以使用它来增强现有的测试基础设施,使其具有Panther的强大功能。

<?php

namespace App\Tests\Controller;

use Liip\FunctionalTestBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Panther\PantherTestCaseTrait;

class DefaultControllerTest extends WebTestCase
{
    use PantherTestCaseTrait; // this is the magic. Panther is now available.

    public function testWithFixtures()
    {
        $this->loadFixtures([]); // load your fixtures
        $client = self::createPantherClient(); // create your panther client

        $client->request('GET', '/');
    }
}

限制

以下功能目前不支持

  • 爬取XML文档(仅支持HTML)
  • 更新现有文档(浏览器主要用于消耗数据,而不是创建网页)
  • 使用多维PHP数组语法设置表单值
  • 返回\DOMElement实例的方法(因为此库内部使用WebDriverElement
  • 在选择框中选择无效选项

欢迎通过Pull Requests来填补剩余的空白!

拯救Panther

许多野生猫科动物物种都面临高度威胁。如果您喜欢这个软件,请通过向Panthera组织捐款来帮助拯救(真正的)Panther。

致谢

Kévin Dunglas创建。由Les-Tilleuls.coop赞助。

Panther建立在PHP WebDriver其他几个FOSS库之上。它受到了Nightwatch.js的启发,这是一个基于WebDriver的JavaScript测试工具。