dunglas / panthere
Requires
- php: >=7.1
- facebook/webdriver: ^1.7.1
- symfony/browser-kit: ^4.3
- symfony/http-client: ^4.3
- symfony/polyfill-php72: ^1.9
- symfony/process: ^3.4 || ^4.0
Requires (Dev)
- fabpot/goutte: ^3.2.3
- guzzlehttp/guzzle: ^6.3
- phpunit/phpunit: ^7.3
- symfony/css-selector: ^3.4 || ^4.0
- symfony/framework-bundle: ^3.4 || ^4.0
This package is auto-updated.
Last update: 2023-12-03 22:17:36 UTC
README
PHP和Symfony的浏览器测试和网页抓取库。
Panther是一个方便的独立库,用于抓取网站和运行使用真实浏览器的端到端测试。
Panther功能强大。它利用W3C的WebDriver协议来驱动Google Chrome和Firefox等原生浏览器。
Panther易于使用,因为它实现了Symfony流行的BrowserKit和DomCrawler API,并包含您测试应用程序所需的所有功能。如果您曾经为Symfony应用程序创建过功能测试,它会听起来很熟悉,因为API完全相同!请注意,Panther可以作为独立库在任何PHP项目中使用。
Panther会自动找到您的本地Chrome安装并启动它(归功于ChromeDriver),因此您不需要在计算机上安装任何东西,既不需要Selenium服务器也不需要任何其他神秘的驱动程序。
在测试模式下,Panther会使用PHP内置的web服务器自动启动您的应用程序。您可以将重点放在编写测试或网页抓取场景上,而Panther会处理其他所有事情。
功能
与您习惯的测试和网页抓取库不同,Panther
- 执行网页中包含的JavaScript代码
- 支持Chrome(或Firefox)实现的任何功能
- 允许截图
- 可以等待异步加载的元素出现
- 允许您在加载页面的上下文中运行自己的JS代码或XPath查询
- 支持自定义Selenium服务器安装
- 支持远程浏览器测试服务,包括SauceLabs和BrowserStack
文档
安装
使用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爬取它。为了提供您习惯的所有测试工具,它扩展了PHPUnit的TestCase
。
如果您正在测试一个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的Client
和Crawler
实现。与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提供了一种方便的方法来测试具有实时功能的应用程序,这些应用程序使用Mercure、WebSocket和类似技术。
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,因此它已经有了广泛的文档。
- 关于
Client
类,请参阅BrowserKit文档 - 对于
Crawler
类,请阅读 DomCrawler 文档 - 关于 WebDriver,请阅读 Facebook PHP WebDriver 文档
环境变量
以下环境变量可以被设置以改变 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测试工具。