Квест → Как хакнуть форму
Прошли: 77
Иногда в PHP нам нужно написать интеграционные тесты, и иногда для этих интеграционных тестов нужен веб-сервер. Встроенный веб-сервер доступен начиная с PHP 5.4 и для этих целей можно использовать его.
Базовый вариант запуска сервера, изложенный в документации PHP, выглядит так:
php -S <addr>:<port> -t <docroot>
Это можно выполнить с помощью команды exec, но проще использовать компонент Symfony Process для управления сервером из теста. Главное, что нужно сделать, — запустить процесс асинхронно, убедиться, что порт свободен и подождать нескольких микросекунд, чтобы сервер запустился.
Следующим требованием является способ вызова веб-сервера. Это можно сделать с помощью curl, но лучше использовать Guzzle, это будет немного аккуратнее. При использовании Guzzle, нужно подавить http-ошибки помощью [‘http_errors’ => false]
. Если код выполняется за прокси это можно обойти, установив параметр прокси в пустую строку.
И всё вместе можно собрать в следующее Silex-приложение:
// web/index.php require_once __DIR__.'/vendor/autoload.php'; $app = new Silex\Application(); $app->get('/testpage/', function () { return "LOL"; }); $app->run();
и далее такой интеграционный тест:
use PHPUnit\Framework\TestCase; use Symfony\Component\Process\Process; use GuzzleHttp\Client; class IntegrationTest extends TestCase { /** @var Process */ private static $process; public static function setUpBeforeClass() { self::$process = new Process("php -S localhost:8080 -t ."); self::$process->start(); usleep(100000); //wait for server to get going } public static function tearDownAfterClass() { self::$process->stop(); } public function test404() { $client = new Client(['http_errors' => false]); $response = $client->request("GET", "http://localhost:8080"); $this->assertEquals(404, $response->getStatusCode()); } public function test200() { $client = new Client(['http_errors' => false]); $response = $client->request("GET", "http://localhost:8080/testpage/"); $this->assertEquals(200, $response->getStatusCode()); } }
Который может быть запущен так:
> bin/phpunit IntegrationTest.php --bootstrap=vendor/autoload.php
Код использует методы setUpBeforeClass
и tearDownAfterClass
для запуска одного веб-сервера на один класс-тест и остановки его когда все тесты в этом классе отработали.
Весь код и зависимости можно найти на GitHub.