# Testing Guide for MineSeeker MineSeeker-specific testing setup and workflows. For general PHPUnit/Symfony testing, see [Symfony Testing Docs](https://symfony.com/doc/current/testing.html). ## Example of the current tests ```shell $ bin/phpunit (master->origin/master|✚1…2⚑1) PHPUnit 13.1.7 by Sebastian Bergmann and contributors. Runtime: PHP 8.5.5 Configuration: /var/www/splendid/Mine/phpunit.dist.xml ................................................................. 65 / 71 ( 91%) ...... 71 / 71 (100%) Time: 00:07.319, Memory: 86.50 MB OK (71 tests, 227 assertions) Faker seed used: 918823 ``` ## Quick Start ```bash # One-time setup make test-db-setup # Run tests make test ``` --- ## Test Database Configuration MineSeeker uses a **separate test database** (`mineseeker_test`) with automatic transaction rollback for isolated tests. ### Stack - **PHPUnit 13** - Testing framework - **[Zenstruck Foundry](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html)** - Factory library for test fixtures - **[DAMA Doctrine Test Bundle](https://github.com/dmaicher/doctrine-test-bundle)** - Transaction isolation (rollback after each test) ### Configuration **`phpunit.dist.xml`**: ```xml ``` **`config/bundles.php`**: ```php Zenstruck\Foundry\ZenstruckFoundryBundle::class => ['dev' => true, 'test' => true], DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true], ``` --- ## Setup ### One-time Setup ```bash make test-db-setup ``` Creates `mineseeker_test` database and runs migrations. ### Reset Test Database ```bash make test-db-reset ``` Drops and recreates test database (useful after schema changes). --- ## Running Tests ```bash # All tests make test # Specific file vendor/bin/phpunit tests/Controller/ProfileControllerTest.php # Specific method vendor/bin/phpunit --filter testCreateUser # With test names vendor/bin/phpunit --testdox ``` --- ## MineSeeker Factories See **[FACTORIES.md](./FACTORIES.md)** for complete factory API. ### Available Factories | Factory | Entity | Location | |---------|--------|----------| | `UserFactory` | Registered users | `tests/Factory/UserFactory.php` | | `GamerFactory` | Anonymous players | `tests/Factory/GamerFactory.php` | | `PlayedGameFactory` | Game records | `tests/Factory/PlayedGameFactory.php` | | `StepFactory` | Game moves | `tests/Factory/StepFactory.php` | | `GridFactory` | 16×16 game grids | `tests/Factory/GridFactory.php` | | `GridRowFactory` | Grid rows | `tests/Factory/GridRowFactory.php` | | `WebAuthnCredentialFactory` | Passkey credentials | `tests/Factory/WebAuthnCredentialFactory.php` | | `ContactMessageFactory` | Contact messages | `tests/Factory/ContactMessageFactory.php` | ### Example ```php use App\Tests\Factory\PlayedGameFactory; use App\Tests\WebTestCase; class GameTest extends WebTestCase { public function testGameCreation(): void { $game = PlayedGameFactory::new() ->withRegisteredPlayers() ->redWins() ->create(); self::assertEquals(26, $game->redPoints); } } ``` --- ## Test Structure All tests extend `App\Tests\WebTestCase`: ```php request('GET', '/profile'); self::assertResponseRedirects('/login'); } } ``` **Important**: Always extend `App\Tests\WebTestCase`, not `Symfony\Bundle\FrameworkBundle\Test\WebTestCase`. --- ## Directory Structure ``` tests/ ├── Controller/ # HTTP endpoint tests ├── Dto/ # Data Transfer Object tests ├── Entity/ # Entity logic tests ├── Service/ # Service layer tests ├── Integration/ # Integration tests ├── Factory/ # Foundry factories ├── WebTestCase.php # Base test class └── bootstrap.php # PHPUnit bootstrap ``` --- ## MineSeeker-Specific Patterns ### Testing Game Flow ```php public function testRedPlayerWinsGame(): void { $game = PlayedGameFactory::new() ->withRegisteredPlayers() ->create(); // Create steps to simulate gameplay for ($i = 0; $i < 26; $i++) { StepFactory::new() ->forPlayer('red') ->mine() ->create(['playedGame' => $game]); } self::assertEquals(26, $game->redPoints); } ``` ### Testing Battle Sharing ```php public function testBattleSharePageReturnsValidGame(): void { $game = PlayedGameFactory::new() ->withRegisteredPlayers() ->redWins() ->create(); $client = static::createClient(); $client->request('GET', '/battle/' . $game->uuid); self::assertResponseIsSuccessful(); self::assertSelectorTextContains('h1', 'Battle Report'); } ``` ### Testing Authentication ```php public function testProfileRequiresAuthentication(): void { $client = static::createClient(); $client->request('GET', '/profile'); self::assertResponseRedirects('/login'); } public function testAuthenticatedUserCanAccessProfile(): void { $user = UserFactory::createOne(); $client = static::createClient(); $client->loginUser($user->_real()); $client->request('GET', '/profile'); self::assertResponseIsSuccessful(); } ``` --- ## Troubleshooting ### Tests interfering with each other? Ensure you extend `App\Tests\WebTestCase`, not the base Symfony class. ### Schema out of sync? ```bash make test-db-reset ``` ### Memory limit errors? ```bash php -d memory_limit=1024M vendor/bin/phpunit ``` Or increase in `phpunit.dist.xml`: ```xml ``` ### Test database doesn't exist? ```bash make test-db-setup ``` --- ## External Resources - **[Symfony Testing](https://symfony.com/doc/current/testing.html)** - Symfony testing guide - **[Zenstruck Foundry](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html)** - Factory documentation - **[DAMA Doctrine Test Bundle](https://github.com/dmaicher/doctrine-test-bundle)** - Transaction isolation - **[PHPUnit](https://docs.phpunit.de/)** - PHPUnit documentation --- ## Modern PHPUnit Attributes MineSeeker tests use modern PHP 8 attributes instead of method name prefixes: ```php use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\TestDox; #[TestDox('Security Controller')] class SecurityControllerTest extends WebTestCase { #[Test] #[TestDox('Login page loads successfully with form fields')] public function loginPageLoadsSuccessfully(): void { // Test implementation } } ``` **Benefits:** - ✅ More readable method names (no `test` prefix required) - ✅ Self-documenting with `TestDox` descriptions - ✅ Better IDE support and refactoring - ✅ Cleaner `--testdox` output **Run with documentation:** ```bash vendor/bin/phpunit --testdox ``` Output: ``` Security Controller ✔ Login page loads successfully with form fields ✔ Login page has links to register and forgot password ✔ Register page loads successfully with form ```