RU

Тестирование игры (PHPUnit)

У игры на JumPHP могут быть тесты PHPUnit: подсчёт очков, столкновения, ИИ, загрузка уровня… и прежде всего тесты, которые играют в игру («ракетка идёт сверху вниз»), за игрой которых можно наблюдать. Playground запускает их на опубликованной версии, в песочнице, и показывает результат в Студии, тест за тестом, с видеозаписью каждого игрового теста.

Когда Claude разрабатывает вашу игру, он пишет эти тесты по ходу дела: у каждой механики (перемещение, прыжок, выстрел, бонус, враг, конец уровня) есть свой тест, который её проигрывает и запускается после каждого изменения. Вы видите, как они играют в реальном времени, в панели JumPHP, а затем пересматриваете их записанными в Студии после каждой публикации.

Написать тест

В папке игры — папка tests/ с классами …Test.php (PHPUnit 11):

<?php
// tests/ScoreTest.php
namespace Tests;

use App\Entity\Score;
use PHPUnit\Framework\TestCase;

final class ScoreTest extends TestCase
{
    public function testABrickIsWorthTenPoints(): void
    {
        $score = new Score();
        $score->brick();
        self::assertSame(10, $score->points());
    }
}

Код игры загружается так же, как в самой игре (пространства имён из её composer.json, App\ → src/), с движком JumPHP её версии. Tests\ → tests/. На вашем компьютере bin/jumphp test <игра> тоже запускает их (вместе с остальными проверками).

Тесты, которые играют в игру

Игровой тест проигрывает игру кадр за кадром, а затем проверяет, что произошло: «ракетка идёт сверху вниз», «мяч отскакивает», «прыжок приземляется на платформу». Он наследует JumPHP\Testing\GameTestCase:

<?php
namespace Tests;

use App\Entity\Paddle;
use App\Scene\PlayScene;
use JumPHP\Testing\GameTestCase;

final class PaddleTest extends GameTestCase
{
    public function testThePaddleGoesFromTheTopToTheBottom(): void
    {
        $this->game->start(PlayScene::class, ['mode' => 'local']);  // сцена, сразу
        $paddle = $this->game->peek('left');                       // поле сцены, даже приватное
        $this->game->hold('p1_up', 60);                            // клавиша зажата 60 кадров (1 с)
        self::assertEqualsWithDelta(PlayScene::TOP, $paddle->getBoundingBox()['y'], 1);
        $this->game->hold('p1_down', 90);
        self::assertEqualsWithDelta(PlayScene::BOTTOM - Paddle::HEIGHT, $paddle->getBoundingBox()['y'], 1);
    }
}

Также: press($action), run($images), wait($secondes), scene(), shot($nom) (скриншот). Называйте тесты предложениями (testTheBallBouncesOnThePaddle): они отображаются именно так («The ball bounces on the paddle»).

За ними можно наблюдать везде:

  • на вашем компьютере: bin/jumphp test <игра> запускает их, а панель JumPHP для Claude Code показывает каждый тест в реальном времени (на скорости игры), а затем его последний кадр;
  • на сайте: песочница playground проигрывает их без окна и снимает каждый тест на плёнку (один кадр из каждых 4 кадров игры). Страница тестов в Студии показывает их во время выполнения, а затем воспроизводит по кругу: ▶ / ⏸, ползунок, чтобы идти кадр за кадром, щелчок, чтобы открыть кадр крупно.

Этим тестам нужен JumPHP\Testing (JumPHP 0.2.1 или новее): игра на 0.2.0 тестируется на сайте с самым свежим движком, и вывод об этом сообщает. На вашем компьютере bin/jumphp update обновляет JumPHP.

Запуск

  • Студия → ваш проект → Тесты (PHPUnit) → «▶ Запустить тесты»: страница обновляется сама (записи игровых тестов появляются во время их выполнения), затем показывает каждый тест (✔ / ✘ и сообщение об ошибке), запись каждого игрового теста и полный вывод PHPUnit.
  • Ваш Claude: run_tests, затем get_test_run (MCP-сервер), например после каждого sync_project.

Песочница

Тесты выполняются на сервере playground в изоляции: PHP 8.5 (как движок в браузере), PHPUnit 11, без сети, от пользователя без прав, не более 120 секунд и 256 МБ, без окна и звука (SDL работает «вхолостую»: игровые тесты всё равно рисуют каждый кадр для записи). Приватных файлов игры там нет. Результаты и записи видит только владелец игры (хранятся результаты 5 последних запусков).