diff --git a/docs/1-essentials/07-testing.md b/docs/1-essentials/07-testing.md index 0e3411ac4..f2095d477 100644 --- a/docs/1-essentials/07-testing.md +++ b/docs/1-essentials/07-testing.md @@ -22,7 +22,7 @@ composer phpunit ## Test-specific discovery locations -Tempest will only discover non-dev namespaces defined in composer.json automatically. That means that `{:hl-keyword:require-dev:}` namespaces aren't discovered automatically. Whenever you need Tempest to discover test-specific locations, you may specify them within the `discoverTestLocations()` method of the provided `IntegrationTest` class. +Tempest will only discover non-dev namespaces defined in composer.json automatically. That means that `{:hl-keyword:require-dev:}` namespaces aren't discovered automatically. Whenever you need Tempest to discover test-specific locations, you may specify them within the `discoverTestLocations()` method of the provided `IntegrationTest` class. On top of that, Tempest _will_ look for files in the `tests/Fixtures` directory and discover them by default. You can override this behavior by providing your own implementation of `discoverTestLocations()`, where you can return an array of `DiscoveryLocation` objects (or nothing). @@ -46,7 +46,7 @@ final class HomeControllerTest extends IntegrationTest If you want to test code that interacts with the database, your test class can call the `setupDatabase()` method. This method will create and migrate a clean database for you on the fly. ```php -class TodoControllerTest extends IntegrationTest +final class TodoControllerTest extends IntegrationTest { protected function setUp(): void { @@ -60,8 +60,6 @@ class TodoControllerTest extends IntegrationTest Most likely, you'll want to use a test-specific database connection. You can create a `database.config.php` file anywhere within test-specific discovery locations, and Tempest will use that connection instead of the project's default. For example, you can create a file `tests/Fixtures/database.config.php` like so: ```php tests/Fixtures/database.config.php -migrations, static fn (MigratesUp $a, MigratesUp $b) => strnatcmp($a->name, $b->name)); + usort($this->migrations, static fn (MigratesUp|MigratesDown $a, MigratesUp|MigratesDown $b) => strnatcmp($a->name, $b->name)); } public function getIterator(): Traversable diff --git a/src/Tempest/Framework/Testing/IntegrationTest.php b/src/Tempest/Framework/Testing/IntegrationTest.php index 953b30c87..60ff8699a 100644 --- a/src/Tempest/Framework/Testing/IntegrationTest.php +++ b/src/Tempest/Framework/Testing/IntegrationTest.php @@ -166,7 +166,6 @@ protected function setupBaseRequest(): self protected function setupDatabase(): self { $migrationManager = $this->container->get(MigrationManager::class); - $migrationManager->dropAll(); $this->migrateDatabase(); @@ -174,13 +173,17 @@ protected function setupDatabase(): self return $this; } + /** + * Creates the migration table. You may override this method to provide more migrations to run for every tests in this file. + */ protected function migrateDatabase(): void { - $this->migrate( - CreateMigrationsTable::class, - ); + $this->migrate(CreateMigrationsTable::class); } + /** + * Migrates the specified migration classes. + */ protected function migrate(string|object ...$migrationClasses): void { $migrationManager = $this->container->get(MigrationManager::class); diff --git a/tests/Integration/Framework/Commands/MigrateRehashCommandTest.php b/tests/Integration/Framework/Commands/MigrateRehashCommandTest.php index 7053dafa8..9113b3000 100644 --- a/tests/Integration/Framework/Commands/MigrateRehashCommandTest.php +++ b/tests/Integration/Framework/Commands/MigrateRehashCommandTest.php @@ -4,7 +4,6 @@ namespace Tests\Tempest\Integration\Framework\Commands; -use PHPUnit\Framework\Assert; use Tempest\Console\ExitCode; use Tempest\Database\Migrations\Migration; use Tempest\Framework\Commands\MigrateFreshCommand; diff --git a/tests/Integration/Framework/Commands/MigrateValidateCommandTest.php b/tests/Integration/Framework/Commands/MigrateValidateCommandTest.php index 597cf85fe..ad071be67 100644 --- a/tests/Integration/Framework/Commands/MigrateValidateCommandTest.php +++ b/tests/Integration/Framework/Commands/MigrateValidateCommandTest.php @@ -4,8 +4,13 @@ namespace Tests\Tempest\Integration\Framework\Commands; +use PHPUnit\Framework\Attributes\PreCondition; use Tempest\Console\ExitCode; +use Tempest\Database\MigratesDown; use Tempest\Database\Migrations\Migration; +use Tempest\Database\Migrations\RunnableMigrations; +use Tempest\Database\QueryStatement; +use Tempest\Database\QueryStatements\RawStatement; use Tempest\Framework\Commands\MigrateFreshCommand; use Tempest\Framework\Commands\MigrateValidateCommand; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; @@ -15,6 +20,20 @@ */ final class MigrateValidateCommandTest extends FrameworkIntegrationTestCase { + #[PreCondition] + protected function configure(): void + { + $this->container->singleton( + className: RunnableMigrations::class, + definition: new RunnableMigrations( + migrations: [ + ...iterator_to_array($this->container->get(RunnableMigrations::class)->getIterator()), + new DownMigrationForRehash(), + ], + ), + ); + } + public function test_migration_validate_command_verifies_valid_migrations(): void { $this->console @@ -53,3 +72,13 @@ public function test_migration_validate_command_fails_when_migration_file_is_mis ->assertExitCode(ExitCode::ERROR); } } + +final class DownMigrationForRehash implements MigratesDown +{ + private(set) string $name = '2025-10-12_down_migration_for_rehash_test'; + + public function down(): QueryStatement + { + return new RawStatement('SELECT 1'); + } +}