Комплексное тестирование PHP сайта: от модулей до нагрузки
Тестирование сайта на PHP является неотъемлемой частью процесса администрирования и разработки. Оно позволяет выявить ошибки в коде, проверить корректность работы функций, оценить производительность и убедиться в безопасности приложения. Далее рассматриваются несколько подходов к тестированию, от модульных тестов до нагрузочных испытаний. Каждый вариант сопровождается вопросом, на который он отвечает, и практическими примерами.
Основные методы проверки PHP проекта
Как организовать модульное тестирование кода PHP с помощью PHPUnit?
PHPUnit является стандартным инструментом для модульного тестирования в PHP. Он позволяет тестировать отдельные классы и методы изолированно. Для начала работы требуется установка через Composer:
composer require --dev phpunit/phpunitAdmin page edit php (админ страница редактирования php)
После установки создаётся тестовый класс, наследующий PHPUnit\Framework\TestCase. Пример простого теста для калькулятора:
<?php
class Calculator {
public function add($a, $b) {
return $a + $b;
}
}
class CalculatorTest extends \PHPUnit\Framework\TestCase {
public function testAdd() {
$calc = new Calculator();
$this->assertEquals(4, $calc->add(2, 2));
}
}Site test php (тестирование сайта php)
Запуск теста осуществляется командой vendor/bin/phpunit tests (если файл находится в папке tests). Для удобства можно создать файл конфигурации phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>Php admin login (админ-логин php)
Типичные ошибки и способы их решения:
- Class not found – отсутствует автозагрузка. Требуется настроить Composer autoload для тестируемых классов или использовать локальный autoload.php.
- No tests executed – неправильно указан путь к тестам. Проверить настройки в phpunit.xml или аргумент командной строки.
- Fatal error: Cannot redeclare class – часто возникает при использовании include вместо require_once. Рекомендуется полагаться на autoload.
Как тестировать функциональность сайта с имитацией действий пользователя с помощью Codeception?
Codeception предоставляет сценарии для acceptance, функционального и модульного тестирования. Для приёмочных тестов (acceptance) используется WebDriver или PhpBrowser. Установка:
composer require --dev codeception/codeception
Инициализация: vendor/bin/codecept bootstrap. Создание acceptance теста:
vendor/bin/codecept generate:test acceptance Login
Пример теста для проверки входа в админку:
<?php
class LoginCest {
public function testLogin(AcceptanceTester $I) {
$I->amOnPage('/admin');
$I->fillField('username', 'admin');
$I->fillField('password', 'secret');
$I->click('Login');
$I->see('Dashboard');
}
}
Для запуска требуется указать драйвер (например, PhpBrowser для имитации браузера без JavaScript). Настройка в файле acceptance.suite.yml:
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost
Возможные проблемы:
- WebDriver не запущен – если используется Selenium, требуется предварительно запустить сервер (java -jar selenium-server.jar).
- Тесты не видят сессию – для PhpBrowser необходимо, чтобы сайт использовал файлы куки в той же файловой системе.
- Медленное выполнение – acceptance тесты с WebDriver могут работать медленно; рекомендуется для простых сценариев использовать PhpBrowser.
Как оценить производительность сайта под нагрузкой с помощью Apache Bench?
Apache Bench (ab) – утилита командной строки для нагрузочного тестирования HTTP-сервера. Она входит в состав Apache. Пример использования:
ab -n 100 -c 10 http://example.com/
Параметры: -n общее количество запросов, -c количество одновременных запросов. Результат включает время выполнения, пропускную способность, процент ошибок.
Для тестирования защищённого соединения (HTTPS) добавляется -Z (если поддерживается). Анализ вывода:
Server Software: Apache/2.4.41
Document Path: /
Concurrency Level: 10
Time taken for tests: 2.345 seconds
Complete requests: 100
Failed requests: 0
Requests per second: 42.64 [#/sec] (mean)
Значение Requests per second – ключевой показатель производительности.
Частые проблемы:
- Команда ab не найдена – установить пакет apache2-utils (в Debian/Ubuntu: apt install apache2-utils).
- Ошибка SSL – при тестировании HTTPS может потребоваться отключение проверки сертификата (флаг -k или -Z).
- Недостаточная нагрузка – для реальных испытаний стоит увеличить количество запросов до нескольких тысяч.
Как проверить работу REST API с помощью curl и PHP-скриптов?
Автоматизация проверки API с помощью PHP-скриптов с библиотекой cURL – простой способ интеграционного тестирования. Пример скрипта для проверки эндпоинта:
<?php
$url = 'http://api.example.com/users';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_TIMEOUT => 5
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
if (isset($data['users']) && count($data['users']) > 0) {
echo "API работает корректно.";
} else {
echo "Формат ответа неверен.";
}
} else {
echo "Ошибка HTTP: $httpCode";
}
Такой скрипт можно запускать из cron или как часть CI/CD. Для тестирования POST-запроса добавляется опция CURLOPT_POST и CURLOPT_POSTFIELDS.
Возможные сложности:
- cURL не установлен – установить расширение PHP cURL или выполнить apt install php-curl.
- Ошибка сертификата – для HTTPS может потребоваться отключить проверку (CURLOPT_SSL_VERIFYPEER = false) или указать CA bundle.
- JSON в теле ответа не декодируется – проверить корректность JSON (например, через json_last_error()).
Как тестировать сайты с динамическим контентом на JavaScript используя Symfony Panther?
Panther – библиотека на основе ChromeDriver, позволяющая тестировать SPA и сайты с интенсивным использованием JavaScript. Установка:
composer require --dev symfony/panther
Пример теста для проверки появления элемента после клика:
<?php
use Symfony\Component\Panther\PantherTestCase;
class DynamicContentTest extends PantherTestCase {
public function testAjaxLoad() {
$client = static::createPantherClient();
$crawler = $client->request('GET', 'http://localhost/');
$crawler->filter('#load-button')->click();
$client->waitFor('.result-block');
$this->assertStringContainsString('Данные загружены', $client->getPageSource());
}
}
Требуется установленный ChromeDriver, который можно автоматически загрузить через Panther. Запуск теста:
vendor/bin/phpunit tests/DynamicContentTest.php
Типичные ошибки:
- ChromeDriver не найден – Panther может сам скачать его, но для этого необходима утилита chromedriver в системе или явное указание пути через переменную окружения PANTHER_CHROME_DRIVER_BINARY.
- Headless режим не работает – на сервере может отсутствовать графическая библиотека. Рекомендуется использовать опции panther_options с флагами --headless.
- Тесты выполняются дольше обычного – из-за ожидания анимации; можно уменьшить время ожидания в методе waitFor.
Расширенные примеры тестирования
Ниже приведены более сложные и редко встречающиеся варианты использования инструментов тестирования. Для каждого примера указан код и ожидаемый результат.
Пример 1: Модульное тестирование с Mock объектами в PHPUnit
Когда тестируемый класс зависит от внешнего сервиса (например, базы данных или API), применяются mock-объекты. Создание mock для класса Mailer:
<?php
use PHPUnit\Framework\TestCase;
class UserService {
private $mailer;
public function __construct($mailer) {
$this->mailer = $mailer;
}
public function register($email) {
// ...
$this->mailer->send($email, 'Welcome');
return true;
}
}
class UserServiceTest extends TestCase {
public function testRegisterSendsEmail() {
$mockMailer = $this->createMock(Mailer::class);
$mockMailer->expects($this->once())
->method('send')
->with('user@example.com', 'Welcome')
->willReturn(true);
$service = new UserService($mockMailer);
$result = $service->register('user@example.com');
$this->assertTrue($result);
}
}
Результат выполнения теста:
PHPUnit 9.5.20 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 0.02 seconds, Memory: 6.00 MB
Пример 2: Acceptance тест в Codeception с PhpBrowser для проверки формы регистрации
Тест заполняет поля формы и проверяет появление сообщения об успехе. Конфигурация использует PhpBrowser без JavaScript.
<?php
class RegistrationCest {
public function testSuccessfulRegistration(AcceptanceTester $I) {
$I->amOnPage('/register');
$I->fillField('name', 'Иван');
$I->fillField('email', 'ivan@example.com');
$I->fillField('password', 'secure123');
$I->click('Зарегистрироваться');
$I->see('Регистрация завершена');
$I->seeInCurrentUrl('/success');
}
}
Команда запуска:
vendor/bin/codecept run acceptance RegistrationCest
Ожидаемый вывод:
Codeception PHP Testing Framework v4.2.0 Powered by PHPUnit 9.5.20 Acceptance Tests (1) ----------------- ✔ RegistrationCest: test successful registration (0.15s) ----------------------------------------- Time: 0.18 seconds, Memory: 12.00 MB
Пример 3: Нагрузочный тест с Apache Bench и передача заголовков
Для имитации авторизации можно передать заголовки через параметр -H.
ab -n 500 -c 20 -H "Authorization: Bearer token123" -H "Accept: application/json" http://api.example.com/endpoint
Результат теста (сокращённый):
Server Software: nginx/1.18.0 Server Hostname: api.example.com Document Path: /endpoint Concurrency Level: 20 Time taken for tests: 3.892 seconds Complete requests: 500 Failed requests: 0 Non-2xx responses: 0 Requests per second: 128.47 [#/sec] (mean) ...
Высокое значение Requests per second говорит о хорошей производительности.
Пример 4: Скрипт для проверки API с обработкой ошибок (cURL)
Скрипт тестирует несколько эндпоинтов и выводит отчёт.
<?php
$endpoints = [
'GET /users' => 'http://api.example.com/users',
'POST /login' => ['url' => 'http://api.example.com/login', 'post' => json_encode(['username' => 'test', 'password' => 'test'])]
];
foreach ($endpoints as $name => $config) {
$ch = curl_init();
if (is_array($config)) {
curl_setopt($ch, CURLOPT_URL, $config['url']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $config['post']);
} else {
curl_setopt($ch, CURLOPT_URL, $config);
}
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_TIMEOUT => 5
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
echo "$name: HTTP $httpCode ";
if ($httpCode >= 200 && $httpCode < 300) {
echo "OK";
} else {
echo "FAIL ($error)";
}
echo "\n";
}
Вывод скрипта:
GET /users: HTTP 200 OK POST /login: HTTP 201 OK
Пример 5: Тестирование SPA с асинхронной загрузкой данных через Symfony Panther
Тест проверяет, что после клика по кнопке появляется список комментариев, загруженных через AJAX.
<?php
use Symfony\Component\Panther\PantherTestCase;
class SPACommentTest extends PantherTestCase {
public function testCommentsLoad() {
$client = static::createPantherClient(['browser' => static::CHROME]);
$client->request('GET', 'http://localhost/app');
// Ждём появления кнопки и кликаем
$button = $client->getCrawler()->filter('#load-comments');
$button->click();
// Ожидаем появления контейнера с комментариями (может занять до 5 сек)
$client->waitFor('.comment-item', 5);
// Проверяем, что есть хотя бы один комментарий
$comments = $client->getCrawler()->filter('.comment-item');
$this->assertGreaterThan(0, $comments->count());
// Закрываем браузер
$client->quit();
}
}
После запуска:
PHPUnit 9.5.20 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 2.731 seconds, Memory: 14.00 MB
Тест успешен, значит AJAX-запрос отработал корректно.