PHP Profi

Запуск встроенного PHP веб-сервера из PHPUnit Перевод

php PHPUnit built-in web-server

Иногда в 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.

2017-11-24 alek13 оригинал
General Food

Комментарии

авторизуйтесь, чтобы оставить комментарий