Das eigene Spiel testen (PHPUnit)
Ein JumPHP-Spiel kann PHPUnit-Tests haben: die Punkteberechnung, die Kollisionen, die KI, das Laden eines Levels … und vor allem Tests, die das Spiel spielen („der Schläger fährt von oben nach unten“), denen man beim Spielen zusieht. Der Playground lässt sie auf der veröffentlichten Version in einer Sandbox laufen und zeigt dir das Ergebnis im Studio, Test für Test, mit dem Film jedes Spieltests.
Wenn Claude dein Spiel entwickelt, schreibt er diese Tests Schritt für Schritt: Jede Mechanik (eine Bewegung, ein Sprung, ein Schuss, ein Bonus, ein Gegner, das Ende eines Levels) hat ihren Test, der sie spielt und nach jeder Änderung läuft. Du siehst sie live im JumPHP-Panel spielen und danach nach jeder Veröffentlichung gefilmt im Studio wieder.
Einen Test schreiben
Im Spielordner ein Ordner tests/ mit Klassen …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());
}
}
Der Code des Spiels wird wie im Spiel geladen (die Namespaces aus seiner composer.json, App\ → src/), mit
der JumPHP-Engine seiner Version. Tests\ → tests/. Auf deinem Computer startet bin/jumphp test <Spiel> sie
ebenfalls (zusammen mit den übrigen Prüfungen).
Tests, die das Spiel spielen
Ein Spieltest lässt das Spiel Frame für Frame spielen und prüft dann, was passiert ist: „der Schläger fährt von oben
nach unten“, „der Ball prallt ab“, „der Sprung landet wieder auf der Plattform“. Er erweitert 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']); // die Szene, sofort
$paddle = $this->game->peek('left'); // ein Feld der Szene, auch privat
$this->game->hold('p1_up', 60); // die Taste 60 Frames gehalten (1 s)
self::assertEqualsWithDelta(PlayScene::TOP, $paddle->getBoundingBox()['y'], 1);
$this->game->hold('p1_down', 90);
self::assertEqualsWithDelta(PlayScene::BOTTOM - Paddle::HEIGHT, $paddle->getBoundingBox()['y'], 1);
}
}
Außerdem: press($action), run($frames), wait($seconds), scene(), shot($name) (ein Screenshot). Benenne die
Tests wie Sätze (testTheBallBouncesOnThePaddle): So werden sie angezeigt („The ball bounces on the
paddle“).
Man sieht ihnen beim Spielen zu, überall:
- auf deinem Computer:
bin/jumphp test <Spiel>startet sie, und das JumPHP-Panel für Claude Code zeigt jeden Test live (in der Geschwindigkeit des Spiels) und danach sein letztes Bild; - auf der Website: Die Sandbox des Playgrounds spielt sie ohne Fenster und filmt jeden Test (jedes 4. Bild des Spiels). Die Testseite des Studios zeigt sie, während sie laufen, und spielt sie danach in Schleife ab: ▶ / ⏸, ein Schieberegler für Bild für Bild, ein Klick öffnet das Bild groß.
Diese Tests brauchen JumPHP\Testing (JumPHP 0.2.1 oder neuer): Ein Spiel mit 0.2.0 wird auf der Website mit der
neuesten Engine getestet, und die Ausgabe sagt das. Auf deinem Computer aktualisiert bin/jumphp update JumPHP.
Sie starten
- Studio → dein Projekt → Tests (PHPUnit) → „▶ Tests starten“: Die Seite aktualisiert sich von selbst (die Filme der Spieltests erscheinen, während sie laufen) und zeigt dann jeden Test (✔ / ✘ und die Fehlermeldung), den Film jedes Spieltests und die vollständige PHPUnit-Ausgabe.
- Dein Claude:
run_testsund dannget_test_run(MCP-Server), zum Beispiel nach jedemsync_project.
Die Sandbox
Die Tests laufen isoliert auf dem Server des Playgrounds: PHP 8.5 (wie die Engine im Browser), PHPUnit 11, ohne Netzwerk, unter einem Benutzer ohne Rechte, höchstens 120 Sekunden und 256 MB, ohne Fenster und Sound (SDL läuft „leer“: Die Spieltests zeichnen trotzdem jedes Bild, für den Film). Die privaten Dateien des Spiels sind dort nicht vorhanden. Nur der Besitzer des Spiels sieht die Ergebnisse und die Filme (die der letzten 5 Durchläufe werden aufbewahrt).