diff --git a/.github/workflows/published.yml b/.github/workflows/published.yml index ffa8190..c0c0460 100644 --- a/.github/workflows/published.yml +++ b/.github/workflows/published.yml @@ -34,12 +34,9 @@ jobs: run: vendor/bin/psalm --stats --shepherd - name: Generate Coverage - run: vendor/bin/phpunit --configuration phpunit.xml.dist \ - --coverage-xml=build/coverage-xml \ - --coverage-clover=build/clover.xml \ - --log-junit=build/phpunit.junit.xml + run: vendor/bin/testo --coverage --log-junit=runtime/coverage/phpunit.junit.xml - name: Infection Mutation Testing env: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} - run: vendor/bin/infection --coverage=build --threads=max --logger-github --no-progress --skip-initial-tests + run: vendor/bin/infection --coverage=runtime/coverage --threads=max --logger-github --no-progress --skip-initial-tests diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 703dbe5..c4d7c8c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -36,6 +36,6 @@ jobs: composer-options: "--optimize-autoloader" - name: PHPUnit - run: vendor/bin/phpunit --configuration phpunit.xml.dist --coverage-clover ./coverage.xml + run: vendor/bin/testo env: XDEBUG_MODE: coverage diff --git a/.gitignore b/.gitignore index c356681..aecd873 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # phpstorm project files .idea .zed +.claude # Mac DS_Store Files .DS_Store @@ -18,4 +19,5 @@ phpunit.phar # local *.local.php +*.env .auth.json diff --git a/Makefile b/Makefile index ff42b7b..9adf694 100644 --- a/Makefile +++ b/Makefile @@ -41,10 +41,10 @@ phpstan: ## phpstan ghcr.io/kuaukutsu/php:${PHP_VERSION}-cli \ ./vendor/bin/phpstan analyse -c phpstan.neon -phpunit: ## phpunit +testo: ## testo $(DOCKER_RUN) \ ghcr.io/kuaukutsu/php:${PHP_VERSION}-cli \ - ./vendor/bin/phpunit + ./vendor/bin/testo phpcs: ## php code snifferphp: detect violations of a defined coding standard $(DOCKER_RUN) \ @@ -78,11 +78,13 @@ infection: --target tests \ -t app_cli .docker/php/cli - docker run --init -it --rm \ - --add-host=host.docker.internal:host-gateway \ -u $(USER) \ -v "$$(pwd):/app" \ -w /app \ - app_cli ./vendor/bin/infection + app_cli ./vendor/bin/infection \ + --coverage=/app/runtime/coverage \ + --threads=max \ + --skip-initial-tests docker image rm -f app_cli tests: @@ -93,17 +95,12 @@ tests: --target tests \ -t app_cli .docker/php/cli - docker run --init -it --rm \ - --add-host=host.docker.internal:host-gateway \ -u $(USER) \ -v "$$(pwd):/app" \ -w /app \ - app_cli ./vendor/bin/phpunit \ - --configuration phpunit.xml.dist \ - --coverage-xml=/app/runtime/coverage/coverage-xml \ - --coverage-clover=/app/runtime/coverage/clover.xml \ - --log-junit=/app/runtime/coverage/phpunit.junit.xml + app_cli ./vendor/bin/testo \ + --coverage --log-junit=/app/runtime/coverage/junit.xml - docker run --init -it --rm \ - --add-host=host.docker.internal:host-gateway \ -u $(USER) \ -v "$$(pwd):/app" \ -w /app \ @@ -119,3 +116,10 @@ app: $(DOCKER_RUN) -w /app/example \ ghcr.io/kuaukutsu/php:${PHP_VERSION}-cli \ sh -l + +## AI +-include .claude/Makefile + +# Спец-правило, чтобы Makefile не ругался на неизвестные команды (аргументы) +%: + @: diff --git a/composer.json b/composer.json index 883b3c0..22595f5 100644 --- a/composer.json +++ b/composer.json @@ -20,14 +20,15 @@ }, "require-dev": { "buggregator/trap": "^1.15", - "infection/infection": "^0.32.4", + "infection/infection": "^0.32.7", "php-di/php-di": "^7.1", "phpstan/phpstan": "^2.0", - "phpunit/phpunit": "^12.5", "rector/rector": "^2.0", "roave/security-advisories": "dev-latest", "slevomat/coding-standard": "^8.7", "squizlabs/php_codesniffer": "^3.7", + "testo/bridge-infection": "^0.1.3", + "testo/testo": "^0.10.10", "vimeo/psalm": "^6.13" }, "autoload": { diff --git a/infection.json5.dist b/infection.json5.dist index 05d6aa0..07e646c 100644 --- a/infection.json5.dist +++ b/infection.json5.dist @@ -1,14 +1,12 @@ { + "$schema": "vendor/infection/infection/resources/schema.json", "source": { - "directories": [ - "src" - ] + "directories": ["src"] }, + "testFramework": "testo", "threads": "max", + "tmpDir": "runtime", "minCoveredMsi": 99, - "phpUnit": { - "configDir": "." - }, "mutators": { "@default": true }, diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 5347843..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - tests - - - - - ./ - - - ./tests - ./vendor - - - diff --git a/testo.dist.xml b/testo.dist.xml new file mode 100644 index 0000000..15805ee --- /dev/null +++ b/testo.dist.xml @@ -0,0 +1,12 @@ + + + diff --git a/testo.php b/testo.php new file mode 100644 index 0000000..98cc41d --- /dev/null +++ b/testo.php @@ -0,0 +1,24 @@ +getName()); - self::assertEquals('main', $driver->getSourceName()); + Assert::same($driver->getName(), 'pgsql'); + Assert::same($driver->getSourceName(), 'main'); $driver = new Driver( dsn: 'MYSQL:host=mysql;dbname=copyDb', ); - self::assertEquals('mysql', $driver->getName()); - self::assertEquals('copydb', $driver->getSourceName()); + Assert::same($driver->getName(), 'mysql'); + Assert::same($driver->getSourceName(), 'copydb'); $driver = new Driver( dsn: 'sqlite::memory:', ); - self::assertEquals('sqlite', $driver->getName()); - self::assertEquals('memory', $driver->getSourceName()); + Assert::same($driver->getName(), 'sqlite'); + Assert::same($driver->getSourceName(), 'memory'); $driver = new Driver( dsn: 'sqlite:tests/data/sqlite/db.sqlite3', ); - self::assertEquals('sqlite', $driver->getName()); - self::assertEquals('db', $driver->getSourceName()); + Assert::same($driver->getName(), 'sqlite'); + Assert::same($driver->getSourceName(), 'db'); } - public function testConfigurationException(): void + public function configurationException(): void { - $this->expectException(ConfigurationException::class); + Expect::exception(ConfigurationException::class); new Driver( dsn: 'unknown:', ); } - public function testDSNConfigurationException(): void + public function dsnConfigurationException(): void { - $this->expectException(ConfigurationException::class); - $this->expectExceptionMessage('PDODriver: dsn is incorrect.'); + Expect::exception(ConfigurationException::class) + ->withMessage('PDODriver: dsn is incorrect.'); new Driver( dsn: 'mysql::memory:', ); } - public function testDSNEmptyConfigurationException(): void + public function dsnEmptyConfigurationException(): void { - $this->expectException(ConfigurationException::class); - $this->expectExceptionMessage('PDODriver: dsn is incorrect.'); + Expect::exception(ConfigurationException::class) + ->withMessage('PDODriver: dsn is incorrect.'); new Driver( dsn: 'sqlite:', diff --git a/tests/workflow/MigrationTest.php b/tests/workflow/MigrationTest.php index e164f96..1b1b5f5 100644 --- a/tests/workflow/MigrationTest.php +++ b/tests/workflow/MigrationTest.php @@ -4,28 +4,29 @@ namespace dbschemix\pdo\tests\workflow; -use Override; use Throwable; -use PHPUnit\Framework\Attributes\Depends; -use PHPUnit\Framework\TestCase; -use dbschemix\pdo\Driver; -use dbschemix\pdo\tests\MigratorFactory; +use Testo\Assert; +use Testo\Lifecycle\BeforeTest; +use Testo\Test; use dbschemix\core\command\CommandInterface; use dbschemix\core\Config; use dbschemix\core\InputOptions; use dbschemix\core\MigratorInterface; +use dbschemix\pdo\tests\MigratorFactory; +use dbschemix\pdo\Driver; /** * Верхнеуровневая работа приложения. */ -final class MigrationTest extends TestCase +#[Test] +final class MigrationTest { private MigratorInterface $migrator; private CommandInterface $command; - #[Override] - protected function setUp(): void + #[BeforeTest] + public function prepare(): void { $driver = new Driver( dsn: 'sqlite::memory:', @@ -38,124 +39,119 @@ protected function setUp(): void /** * @throws Throwable */ - public function testInit(): void + public function init(): void { $this->migrator->init(); $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); } /** * @throws Throwable */ - #[Depends('testInit')] - public function testUp(): void + public function up(): void { $this->migrator->init(); $this->migrator->up(); $data = $this->command->fetchApplied(); $countMigration = count($data); - self::assertGreaterThanOrEqual(3, $countMigration); + Assert::int($countMigration)->greaterThanOrEqual(3); // sort order $names = array_keys($data); - self::assertEquals('202501021025_account_email.sql', $names[0]); - self::assertEquals('202501021024_account_create.sql', $names[1]); - self::assertEquals('202501011024_entity_create.sql', $names[2]); + Assert::same($names[0], '202501021025_account_email.sql'); + Assert::same($names[1], '202501021024_account_create.sql'); + Assert::same($names[2], '202501011024_entity_create.sql'); $this->migrator->up(); $data = $this->command->fetchApplied(); - self::assertCount($countMigration, $data); + Assert::count($data, $countMigration); } /** * @throws Throwable */ - #[Depends('testInit')] - public function testDown(): void + public function down(): void { $this->migrator->init(); $this->migrator->up(); $data = $this->command->fetchApplied(); - self::assertGreaterThanOrEqual(3, $data); + Assert::int(count($data))->greaterThanOrEqual(3); $this->migrator->down(); $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); } /** * @throws Throwable */ - #[Depends('testInit')] - public function testRedo(): void + public function redo(): void { $this->migrator->init(); $this->migrator->up(); $data = $this->command->fetchApplied(); - self::assertGreaterThanOrEqual(3, $data); + Assert::int(count($data))->greaterThanOrEqual(3); $version = (int)current($data); - self::assertGreaterThan(0, $version); + Assert::int($version)->greaterThan(0); usleep(10_000); $this->migrator->redo(); $data = $this->command->fetchApplied(); - self::assertGreaterThanOrEqual(3, $data); + Assert::int(count($data))->greaterThanOrEqual(3); $versionNew = (int)current($data); - self::assertGreaterThan(0, $versionNew); + Assert::int($versionNew)->greaterThan(0); // новая версия больше старой - self::assertGreaterThan($version, $versionNew); + Assert::int($versionNew)->greaterThan($version); } /** * @throws Throwable */ - #[Depends('testInit')] - public function testVerify(): void + public function verify(): void { $this->migrator->init(); $this->migrator->up(new InputOptions(limit: 1)); $data = $this->command->fetchApplied(); - self::assertCount(1, $data); + Assert::count($data, 1); $version = (int)current($data); - self::assertGreaterThan(0, $version); + Assert::int($version)->greaterThan(0); usleep(10_000); $this->migrator->verify(); $data = $this->command->fetchApplied(); - self::assertCount(1, $data); + Assert::count($data, 1); $versionNew = (int)current($data); - self::assertEquals($version, $versionNew); + Assert::equals($versionNew, $version); } /** * @throws Throwable */ - #[Depends('testInit')] - public function testFixture(): void + public function fixture(): void { $this->migrator->init(); $this->migrator->up(); $data = $this->command->fetchApplied(); $countMigration = count($data); - self::assertGreaterThan(0, $countMigration); + Assert::int($countMigration)->greaterThan(0); // applied fixture no saved $this->migrator->fixture(); $data = $this->command->fetchApplied(); - self::assertCount($countMigration, $data); + Assert::count($data, $countMigration); } } diff --git a/tests/workflow/StatementMysqlTest.php b/tests/workflow/StatementMysqlTest.php index 76add99..105fb3e 100644 --- a/tests/workflow/StatementMysqlTest.php +++ b/tests/workflow/StatementMysqlTest.php @@ -4,21 +4,23 @@ namespace dbschemix\pdo\tests\workflow; -use Override; use Throwable; use PDO; -use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\TestCase; +use Testo\Assert; +use Testo\Data\DataProvider; +use Testo\Lifecycle\BeforeTest; +use Testo\Test; use dbschemix\core\connection\TransactionInterface; use dbschemix\pdo\internal\Connection; use dbschemix\pdo\Type; -final class StatementMysqlTest extends TestCase +#[Test] +final class StatementMysqlTest { private TransactionInterface $transaction; - #[Override] - protected function setUp(): void + #[BeforeTest] + public function init(): void { $pdo = new PDO(dsn: 'sqlite::memory:'); $pdo->exec( @@ -31,40 +33,69 @@ protected function setUp(): void /** * @throws Throwable */ - public function testExecActiveTransaction(): void + public function execActiveTransaction(): void { // default: false - self::assertFalse($this->transaction->isActive()); + Assert::false($this->transaction->isActive()); $this->transaction->exec( "INSERT INTO migration (name, version, atime) VALUES ('v1', 1, '2026-01-01 00:00:00')" ); // statement INSERT: true - self::assertTrue($this->transaction->isActive()); + Assert::true($this->transaction->isActive()); $state = $this->transaction->commit(); - self::assertTrue($state); - self::assertFalse($this->transaction->isActive()); + Assert::true($state); + Assert::false($this->transaction->isActive()); // not active $state = $this->transaction->commit(); - self::assertTrue($state); + Assert::true($state); $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertCount(1, $data); + Assert::count($data, 1); } /** - * @return iterable + * Non-parameterized DDL case. + * + * Testo's coverage bridge does not attribute per-line coverage to + * #[DataProvider] methods, so {@see execNotActiveTransaction} is invisible + * to Infection and the DDL detection in tryBeginTransaction() would stay + * uncovered. This plain test pins the "DDL does not open a transaction" + * contract so the preg_match guard is mutation-covered. + * + * @throws Throwable + */ + public function execSchemaQueryNotActiveTransaction(): void + { + // default: false + Assert::false($this->transaction->isActive()); + + $this->transaction->exec( + 'CREATE TABLE IF NOT EXISTS test (name TEXT PRIMARY KEY, version INTEGER DEFAULT 0, atime TEXT)' + ); + + // statement CREATE TABLE: still not active, DDL must not open a transaction + Assert::false($this->transaction->isActive()); + + $state = $this->transaction->commit(); + Assert::true($state); + } + + /** + * @return iterable */ public static function additionSchemaQuery(): iterable { - yield ['CREATE TABLE IF NOT EXISTS test (name TEXT PRIMARY KEY, version INTEGER DEFAULT 0, atime TEXT)']; - yield ['ALTER TABLE migration ADD COLUMN test TEXT DEFAULT NULL']; - yield ['CREATE UNIQUE INDEX IF NOT EXISTS `UI_migration_name` ON migration (name)']; - yield ['DROP INDEX IF EXISTS `UI_migration_name`']; - yield ['DROP TABLE IF EXISTS test']; + yield 'create table' => [ + 'CREATE TABLE IF NOT EXISTS test (name TEXT PRIMARY KEY, version INTEGER DEFAULT 0, atime TEXT)', + ]; + yield 'alter table' => ['ALTER TABLE migration ADD COLUMN test TEXT DEFAULT NULL']; + yield 'create index' => ['CREATE UNIQUE INDEX IF NOT EXISTS `UI_migration_name` ON migration (name)']; + yield 'drop index' => ['DROP INDEX IF EXISTS `UI_migration_name`']; + yield 'drop table' => ['DROP TABLE IF EXISTS test']; } /** @@ -72,17 +103,17 @@ public static function additionSchemaQuery(): iterable * @throws Throwable */ #[DataProvider('additionSchemaQuery')] - public function testExecNotActiveTransaction(string $query): void + public function execNotActiveTransaction(string $query): void { // default: false - self::assertFalse($this->transaction->isActive()); + Assert::false($this->transaction->isActive()); $this->transaction->exec($query); // statement CREATE TABLE: false - self::assertFalse($this->transaction->isActive()); + Assert::false($this->transaction->isActive()); $state = $this->transaction->commit(); - self::assertTrue($state); + Assert::true($state); } } diff --git a/tests/workflow/StatementTest.php b/tests/workflow/StatementTest.php index 8d88ce8..99a3131 100644 --- a/tests/workflow/StatementTest.php +++ b/tests/workflow/StatementTest.php @@ -4,21 +4,24 @@ namespace dbschemix\pdo\tests\workflow; -use Override; use Throwable; use PDO; -use PHPUnit\Framework\TestCase; +use Testo\Assert; +use Testo\Lifecycle\AfterTest; +use Testo\Lifecycle\BeforeTest; +use Testo\Test; use dbschemix\core\connection\TransactionInterface; use dbschemix\pdo\internal\Transaction; -final class StatementTest extends TestCase +#[Test] +final class StatementTest { private PDO $pdo; private TransactionInterface $transaction; - #[Override] - protected function setUp(): void + #[BeforeTest] + public function init(): void { $this->pdo = new PDO(dsn: 'sqlite::memory:'); $this->pdo->exec( @@ -28,8 +31,8 @@ protected function setUp(): void $this->transaction = Transaction::begin($this->pdo); } - #[Override] - protected function tearDown(): void + #[AfterTest] + public function clean(): void { $this->transaction->rollback(); } @@ -37,67 +40,67 @@ protected function tearDown(): void /** * @throws Throwable */ - public function testExecWithoutParams(): void + public function execWithoutParams(): void { $this->transaction->exec( "INSERT INTO migration (name, version, atime) VALUES ('v1', 1, '2026-01-01 00:00:00')" ); $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertCount(1, $data); - self::assertArrayHasKey('v1', $data); + Assert::count($data, 1); + Assert::array($data)->hasKeys('v1'); } /** * @throws Throwable */ - public function testExecCommitTransaction(): void + public function execCommitTransaction(): void { - self::assertTrue($this->transaction->isActive()); + Assert::true($this->transaction->isActive()); $this->transaction->exec( "INSERT INTO migration (name, version, atime) VALUES ('v1', 1, '2026-01-01 00:00:00')" ); $state = $this->transaction->commit(); - self::assertTrue($state); - self::assertFalse($this->transaction->isActive()); + Assert::true($state); + Assert::false($this->transaction->isActive()); // not active $state = $this->transaction->commit(); - self::assertTrue($state); + Assert::true($state); $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertCount(1, $data); + Assert::count($data, 1); } /** * @throws Throwable */ - public function testExecRollbackTransaction(): void + public function execRollbackTransaction(): void { - self::assertTrue($this->transaction->isActive()); + Assert::true($this->transaction->isActive()); $this->transaction->exec( "INSERT INTO migration (name, version, atime) VALUES ('v1', 1, '2026-01-01 00:00:00')" ); $state = $this->transaction->rollback(); - self::assertTrue($state); - self::assertFalse($this->transaction->isActive()); + Assert::true($state); + Assert::false($this->transaction->isActive()); // not active $state = $this->transaction->rollback(); - self::assertTrue($state); + Assert::true($state); $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertEmpty($data); + Assert::blank($data); } /** * @throws Throwable */ - public function testExecWithNamedParams(): void + public function execWithNamedParams(): void { $this->transaction->exec( 'INSERT INTO migration (name, version, atime) VALUES (:name, :version, :atime)', @@ -105,9 +108,9 @@ public function testExecWithNamedParams(): void ); $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertCount(1, $data); - self::assertArrayHasKey('202501010000_create_users', $data); - self::assertEquals(42, $data['202501010000_create_users']); + Assert::count($data, 1); + Assert::array($data)->hasKeys('202501010000_create_users'); + Assert::equals($data['202501010000_create_users'], 42); } /** @@ -115,7 +118,7 @@ public function testExecWithNamedParams(): void * * @throws Throwable */ - public function testExecParamsAreNotInterpolated(): void + public function execParamsAreNotInterpolated(): void { $maliciousName = "'); DROP TABLE migration; --"; @@ -125,14 +128,14 @@ public function testExecParamsAreNotInterpolated(): void ); $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertCount(1, $data); - self::assertArrayHasKey($maliciousName, $data); + Assert::count($data, 1); + Assert::array($data)->hasKeys($maliciousName); } /** * @throws Throwable */ - public function testExecMultipleRowsWithParams(): void + public function execMultipleRowsWithParams(): void { $rows = [ ['name' => '202501010000_first', 'version' => 1, 'atime' => '2026-01-01 00:00:00'], @@ -148,16 +151,16 @@ public function testExecMultipleRowsWithParams(): void } $data = $this->transaction->fetchRecord('SELECT name, version FROM migration'); - self::assertCount(3, $data); - self::assertEquals(1, $data['202501010000_first']); - self::assertEquals(2, $data['202501010001_second']); - self::assertEquals(3, $data['202501010002_third']); + Assert::count($data, 3); + Assert::equals($data['202501010000_first'], 1); + Assert::equals($data['202501010001_second'], 2); + Assert::equals($data['202501010002_third'], 3); } /** * @throws Throwable */ - public function testFetchRecordWithParams(): void + public function fetchRecordWithParams(): void { $this->pdo->exec("INSERT INTO migration (name, version, atime) VALUES ('v1', 10, '2026-01-01 00:00:00')"); $this->pdo->exec("INSERT INTO migration (name, version, atime) VALUES ('v2', 20, '2026-01-02 00:00:00')"); @@ -168,16 +171,15 @@ public function testFetchRecordWithParams(): void ['version' => 10], ); - self::assertCount(2, $data); - self::assertArrayHasKey('v1', $data); - self::assertArrayHasKey('v3', $data); - self::assertArrayNotHasKey('v2', $data); + Assert::count($data, 2); + Assert::array($data)->hasKeys('v1', 'v3'); + Assert::array($data)->doesNotHaveKeys('v2'); } /** * @throws Throwable */ - public function testFetchRecordWithParamsNoMatch(): void + public function fetchRecordWithParamsNoMatch(): void { $this->pdo->exec("INSERT INTO migration (name, version, atime) VALUES ('v1', 1, '2026-01-01 00:00:00')"); @@ -186,6 +188,6 @@ public function testFetchRecordWithParamsNoMatch(): void ['version' => 999], ); - self::assertEmpty($data); + Assert::blank($data); } } diff --git a/tests/workflow/UpExactlyTest.php b/tests/workflow/UpExactlyTest.php index c1a6d4a..a0e3c50 100644 --- a/tests/workflow/UpExactlyTest.php +++ b/tests/workflow/UpExactlyTest.php @@ -4,25 +4,28 @@ namespace dbschemix\pdo\tests\workflow; -use Override; use Throwable; -use PHPUnit\Framework\TestCase; -use dbschemix\pdo\Driver; -use dbschemix\pdo\tests\MigratorFactory; +use Testo\Assert; +use Testo\Expect; +use Testo\Lifecycle\BeforeTest; +use Testo\Test; use dbschemix\core\command\CommandInterface; use dbschemix\core\exception\ActionException; use dbschemix\core\Config; use dbschemix\core\InputOptions; use dbschemix\core\MigratorInterface; +use dbschemix\pdo\Driver; +use dbschemix\pdo\tests\MigratorFactory; -final class UpExactlyTest extends TestCase +#[Test] +final class UpExactlyTest { private MigratorInterface $migrator; private CommandInterface $command; - #[Override] - protected function setUp(): void + #[BeforeTest] + public function prepare(): void { $driver = new Driver( dsn: 'sqlite::memory:', @@ -35,19 +38,19 @@ protected function setUp(): void /** * @throws Throwable */ - public function testUpExactlyAll(): void + public function upExactlyAll(): void { $this->migrator->init(); $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); $this->migrator->up(new InputOptions(limit: 1)); $data = $this->command->fetchApplied(); - self::assertCount(1, $data); + Assert::count($data, 1); $this->migrator->down(); $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); try { $this->migrator->up(); @@ -56,11 +59,11 @@ public function testUpExactlyAll(): void // только первая миграция успешно $data = $this->command->fetchApplied(); - self::assertCount(1, $data); + Assert::count($data, 1); $this->migrator->down(); $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); try { $this->migrator->up(new InputOptions(exactlyAll: true)); @@ -69,17 +72,15 @@ public function testUpExactlyAll(): void // всё или ничего $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); } - public function testUpExactlyAllException(): void + public function upExactlyAllException(): void { $this->migrator->init(); - $this->expectException(ActionException::class); - $this->expectExceptionMessage( - 'SQLSTATE[HY000]: General error: 1 no such table:' - ); + Expect::exception(ActionException::class) + ->withMessageContaining('SQLSTATE[HY000]: General error: 1 no such table:'); $this->migrator->up(new InputOptions(exactlyAll: true)); } @@ -87,15 +88,15 @@ public function testUpExactlyAllException(): void /** * @throws Throwable */ - public function testVerify(): void + public function verify(): void { $this->migrator->init(); $data = $this->command->fetchApplied(); - self::assertEmpty($data); + Assert::blank($data); $this->migrator->up(new InputOptions(limit: 1)); $data = $this->command->fetchApplied(); - self::assertCount(1, $data); + Assert::count($data, 1); // точность версионирования usleep(10_000); @@ -107,17 +108,15 @@ public function testVerify(): void // только первая миграция успешно $data = $this->command->fetchApplied(); - self::assertCount(1, $data); + Assert::count($data, 1); } - public function testVerifyException(): void + public function verifyException(): void { $this->migrator->init(); - $this->expectException(ActionException::class); - $this->expectExceptionMessage( - 'SQLSTATE[HY000]: General error: 1 no such table:' - ); + Expect::exception(ActionException::class) + ->withMessageContaining('SQLSTATE[HY000]: General error: 1 no such table:'); $this->migrator->verify(); }