new: pkg: add test cases to back-end w/ real database connection in it #10
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Mine-Seeker Game Documentation
|
||||
|
||||
This directory contains comprehensive documentation about the Mine-Seeker game mechanics and implementation.
|
||||
This directory contains comprehensive documentation about the Mine-Seeker game mechanics, testing, and implementation.
|
||||
|
||||
## Game Mechanics
|
||||
|
||||
@@ -18,6 +18,46 @@ Complete reference for the bonus points system including:
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### [Testing Guide](./testing/TESTING.md)
|
||||
Complete testing setup and best practices including:
|
||||
- Test environment configuration
|
||||
- Database isolation with DAMA Doctrine Test Bundle
|
||||
- Test database setup (`mineseeker_test`)
|
||||
- Writing effective tests
|
||||
- Running tests (all, specific, with coverage)
|
||||
- Best practices (AAA pattern, factories, type hints)
|
||||
- CI/CD integration examples
|
||||
- Troubleshooting guide
|
||||
|
||||
**Recommended for**: All developers, understanding test infrastructure, writing new tests, debugging test failures.
|
||||
|
||||
### [Factory Documentation](./testing/FACTORIES.md)
|
||||
Detailed API reference for Zenstruck Foundry factories:
|
||||
- All available factories (User, Gamer, PlayedGame, Step, Grid, etc.)
|
||||
- Factory usage examples
|
||||
- Creating related entities
|
||||
- Repository access
|
||||
- Database isolation explanation
|
||||
- Best practices and patterns
|
||||
|
||||
**Recommended for**: Writing tests with test data, understanding factory patterns, creating complex test scenarios.
|
||||
|
||||
---
|
||||
|
||||
## Technical Documentation
|
||||
|
||||
### [Fonts](./FONTS.md)
|
||||
TrueType fonts used for server-side image generation:
|
||||
- Font file locations
|
||||
- Usage in battle card generation
|
||||
- Web vs. server-side font formats
|
||||
|
||||
**Recommended for**: Working on OG image generation, understanding font rendering.
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Bonus Points at a Glance
|
||||
@@ -30,18 +70,63 @@ Complete reference for the bonus points system including:
|
||||
| Chain Combo | Tracked | Consecutive mine clicks (no safe clicks) |
|
||||
| Biggest Reveal | Tracked | Largest number of safe cells revealed |
|
||||
|
||||
### Key Rules
|
||||
- Safe cell bonus only awarded for ≥2 cells minimum
|
||||
- Chain counter resets on any safe cell click
|
||||
- Endgame threshold: 51 - (redPoints + bluePoints) ≤ 10
|
||||
- Bonus stats are per-player and persist in database
|
||||
### Available Test Factories
|
||||
| Factory | Entity | Purpose |
|
||||
|---------|--------|---------|
|
||||
| `UserFactory` | `User` | Registered users |
|
||||
| `GamerFactory` | `Gamer` | Anonymous/guest players |
|
||||
| `PlayedGameFactory` | `PlayedGame` | Game records |
|
||||
| `StepFactory` | `Step` | Game moves |
|
||||
| `GridFactory` | `Grid` | Game grids (16×16) |
|
||||
| `GridRowFactory` | `GridRow` | Grid rows |
|
||||
| `WebAuthnCredentialFactory` | `WebAuthnCredential` | Passkey credentials |
|
||||
| `ContactMessageFactory` | `ContactMessage` | Contact messages |
|
||||
|
||||
### Running Tests
|
||||
```bash
|
||||
# Recommended: Use Makefile
|
||||
make test-db-setup
|
||||
|
||||
# Or manually:
|
||||
# All tests
|
||||
vendor/bin/phpunit
|
||||
|
||||
# Specific file
|
||||
vendor/bin/phpunit tests/Controller/ProfileControllerTest.php
|
||||
|
||||
# Specific method
|
||||
vendor/bin/phpunit --filter testProfilePageRequiresAuthentication
|
||||
|
||||
# With coverage (requires Xdebug/PCOV)
|
||||
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-html coverage/
|
||||
|
||||
# With increased memory
|
||||
php -d memory_limit=512M vendor/bin/phpunit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files Using This Information
|
||||
|
||||
### Game Mechanics
|
||||
- Backend: `/src/Util/TopicManager.php`
|
||||
- Frontend: `/assets/js/mine-seeker/contexts/GameProvider.jsx`
|
||||
- UI: `/assets/js/mine-seeker/components/BonusStatsDialog.jsx`
|
||||
- Constants: `/assets/js/mine-seeker/utils/constants.jsx`
|
||||
|
||||
### Testing
|
||||
- Test Base Class: `/tests/WebTestCase.php`
|
||||
- Factories: `/tests/Factory/`
|
||||
- Example Tests: `/tests/Integration/FactoryExampleTest.php`
|
||||
- PHPUnit Config: `/phpunit.dist.xml`
|
||||
- Bundle Config: `/config/bundles.php`
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- **[Main README](../README.md)** - Project overview, installation, deployment
|
||||
- **[AI Agent Guidelines](../AGENTS.md)** - Comprehensive guide for AI coding agents
|
||||
- **[Zenstruck Foundry](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html)** - Official Foundry documentation
|
||||
- **[PHPUnit](https://phpunit.de/)** - PHPUnit documentation
|
||||
- **[Symfony Testing](https://symfony.com/doc/current/testing.html)** - Symfony testing guide
|
||||
|
||||
265
docs/testing/FACTORIES.md
Normal file
265
docs/testing/FACTORIES.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# Foundry Factories for MineSeeker
|
||||
|
||||
Factory classes for creating test data. For general Foundry usage, see [Zenstruck Foundry Docs](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html).
|
||||
|
||||
---
|
||||
|
||||
## Available Factories
|
||||
|
||||
All factories are in `tests/Factory/`:
|
||||
|
||||
| Factory | Entity | Use For |
|
||||
|---------|--------|---------|
|
||||
| `UserFactory` | `User` | Registered users with auth |
|
||||
| `GamerFactory` | `Gamer` | Anonymous/guest players |
|
||||
| `PlayedGameFactory` | `PlayedGame` | Game records |
|
||||
| `StepFactory` | `Step` | Individual game moves |
|
||||
| `GridFactory` | `Grid` | 16×16 game grids |
|
||||
| `GridRowFactory` | `GridRow` | Grid row data |
|
||||
| `WebAuthnCredentialFactory` | `WebAuthnCredential` | Passkey credentials |
|
||||
| `ContactMessageFactory` | `ContactMessage` | Contact form messages |
|
||||
|
||||
---
|
||||
|
||||
## Quick Examples
|
||||
|
||||
### UserFactory
|
||||
|
||||
```php
|
||||
// Basic user
|
||||
$user = UserFactory::createOne();
|
||||
|
||||
// Unverified user
|
||||
$user = UserFactory::createOne(['isVerified' => false]);
|
||||
|
||||
// Admin user
|
||||
$user = UserFactory::createOne(['roles' => ['ROLE_ADMIN']]);
|
||||
|
||||
// Multiple users
|
||||
UserFactory::createMany(5);
|
||||
```
|
||||
|
||||
### GamerFactory
|
||||
|
||||
```php
|
||||
// Anonymous gamer
|
||||
$gamer = GamerFactory::new()->anonymous()->create();
|
||||
```
|
||||
|
||||
### PlayedGameFactory
|
||||
|
||||
```php
|
||||
// Game with registered players
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->create();
|
||||
|
||||
// Game with anonymous players
|
||||
$game = PlayedGameFactory::new()
|
||||
->withAnonymousPlayers()
|
||||
->create();
|
||||
|
||||
// Red wins
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->redWins()
|
||||
->create();
|
||||
|
||||
// Blue wins
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->blueWins()
|
||||
->create();
|
||||
|
||||
// Resigned game
|
||||
$game = PlayedGameFactory::new()
|
||||
->resigned('red')
|
||||
->create();
|
||||
```
|
||||
|
||||
### StepFactory
|
||||
|
||||
```php
|
||||
// Mine hit
|
||||
$step = StepFactory::new()
|
||||
->forPlayer('red')
|
||||
->mine()
|
||||
->create(['playedGame' => $game]);
|
||||
|
||||
// Safe cell
|
||||
$step = StepFactory::new()
|
||||
->forPlayer('blue')
|
||||
->safe()
|
||||
->create(['playedGame' => $game]);
|
||||
|
||||
// With revealed cells
|
||||
$step = StepFactory::new()
|
||||
->withRevealedCells([
|
||||
['row' => 5, 'col' => 5],
|
||||
['row' => 5, 'col' => 6],
|
||||
])
|
||||
->create(['playedGame' => $game]);
|
||||
```
|
||||
|
||||
### GridFactory
|
||||
|
||||
```php
|
||||
// Full 16×16 grid
|
||||
$grid = GridFactory::createOne(['playedGame' => $game]);
|
||||
|
||||
// Automatically creates 16 rows
|
||||
self::assertCount(16, $grid->gridRow);
|
||||
```
|
||||
|
||||
### WebAuthnCredentialFactory
|
||||
|
||||
```php
|
||||
// Basic credential
|
||||
$credential = WebAuthnCredentialFactory::createOne(['user' => $user]);
|
||||
|
||||
// Named credential, recently used
|
||||
$credential = WebAuthnCredentialFactory::new()
|
||||
->withName('YubiKey 5C')
|
||||
->recentlyUsed()
|
||||
->create(['user' => $user]);
|
||||
```
|
||||
|
||||
### ContactMessageFactory
|
||||
|
||||
```php
|
||||
// Basic message
|
||||
$message = ContactMessageFactory::createOne();
|
||||
|
||||
// Without consent
|
||||
$message = ContactMessageFactory::new()
|
||||
->withoutConsent()
|
||||
->create();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Factory API Reference
|
||||
|
||||
### Common Methods (All Factories)
|
||||
|
||||
```php
|
||||
// Create single entity
|
||||
Factory::createOne([
|
||||
'property' => 'value',
|
||||
]);
|
||||
|
||||
// Create multiple
|
||||
Factory::createMany(5);
|
||||
|
||||
// Create with factory methods
|
||||
Factory::new()
|
||||
->customMethod()
|
||||
->create(['property' => 'value']);
|
||||
|
||||
// Access repository
|
||||
Factory::repository()->findAll();
|
||||
Factory::repository()->count([]);
|
||||
Factory::repository()->findBy(['field' => 'value']);
|
||||
```
|
||||
|
||||
### PlayedGameFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `withRegisteredPlayers()` | Creates game with 2 registered users |
|
||||
| `withAnonymousPlayers()` | Creates game with 2 anonymous gamers |
|
||||
| `withMixedPlayers()` | One registered, one anonymous |
|
||||
| `redWins()` | Red has 26 points |
|
||||
| `blueWins()` | Blue has 26 points |
|
||||
| `resigned(string $player)` | Set resignation ('red' or 'blue') |
|
||||
|
||||
### StepFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `forPlayer(string $player)` | Set player ('red' or 'blue') |
|
||||
| `mine()` | Step hits a mine |
|
||||
| `safe()` | Step reveals safe cell |
|
||||
| `withRevealedCells(array $cells)` | Set revealed cells array |
|
||||
|
||||
### GamerFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `anonymous()` | Set username as "Guest_12345" |
|
||||
|
||||
### WebAuthnCredentialFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `withName(string $name)` | Set credential name |
|
||||
| `recentlyUsed()` | Set lastUsedAt to now |
|
||||
|
||||
### ContactMessageFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `withoutConsent()` | Set consent to false |
|
||||
| `anonymous()` | Remove IP address |
|
||||
|
||||
---
|
||||
|
||||
## MineSeeker-Specific Patterns
|
||||
|
||||
### Complete Game Setup
|
||||
|
||||
```php
|
||||
// Create full game with steps and grid
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->create();
|
||||
|
||||
// Add steps
|
||||
StepFactory::createMany(10, [
|
||||
'playedGame' => $game,
|
||||
'player' => 'red',
|
||||
]);
|
||||
|
||||
// Add grid
|
||||
$grid = GridFactory::createOne(['playedGame' => $game]);
|
||||
```
|
||||
|
||||
### Testing Battle History
|
||||
|
||||
```php
|
||||
// Create multiple finished games for a user
|
||||
$user = UserFactory::createOne();
|
||||
|
||||
PlayedGameFactory::new()
|
||||
->redWins()
|
||||
->create(['red' => $user]);
|
||||
|
||||
PlayedGameFactory::new()
|
||||
->blueWins()
|
||||
->create(['blue' => $user]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Isolation
|
||||
|
||||
Tests automatically run in isolated transactions:
|
||||
|
||||
```php
|
||||
public function testDatabaseIsolation(): void
|
||||
{
|
||||
UserFactory::createMany(5);
|
||||
self::assertCount(5, UserFactory::repository()->findAll());
|
||||
|
||||
// Automatically rolled back after test
|
||||
}
|
||||
```
|
||||
|
||||
No manual cleanup needed. Each test starts with a clean database.
|
||||
|
||||
---
|
||||
|
||||
## External Resources
|
||||
|
||||
- **[Zenstruck Foundry Documentation](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html)** - Complete Foundry guide
|
||||
- **[DAMA Doctrine Test Bundle](https://github.com/dmaicher/doctrine-test-bundle)** - Transaction isolation details
|
||||
317
docs/testing/TESTING.md
Normal file
317
docs/testing/TESTING.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# 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).
|
||||
|
||||
## 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
|
||||
<env name="DATABASE_URL" value="postgresql://...mineseeker_test..." />
|
||||
<env name="DAMA_DISABLE_STATIC_CONNECTION" value="0" />
|
||||
```
|
||||
|
||||
**`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
|
||||
<?php declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of the SplendidBear Websites' projects.
|
||||
*
|
||||
* Copyright (c) 2026 @ www.splendidbear.org
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Tests\Factory\UserFactory;
|
||||
use App\Tests\WebTestCase;
|
||||
|
||||
class MyControllerTest extends WebTestCase
|
||||
{
|
||||
public function testExample(): void
|
||||
{
|
||||
$user = UserFactory::createOne();
|
||||
$client = static::createClient();
|
||||
|
||||
$client->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
|
||||
<ini name="memory_limit" value="1024M"/>
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
Reference in New Issue
Block a user