From 6bfd8532bbc2a39a24edd69d5903af3f728c0db0 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Sat, 17 Oct 2026 10:52:37 -0400 Subject: [PATCH 1/2] feat(43963): add PHPUnit preparation subscriber and tests; remove deprecated subscriber --- phpunit.xml.dist | 34 ++++ ...HPUnitBeforeTestMethodCalledSubscriber.php | 35 ---- .../Fixture/Extension/PHPUnitExtension.php | 2 +- .../PHPUnitPreparationStartedSubscriber.php | 45 +++++ ...HPUnitPreparationStartedSubscriberTest.php | 167 ++++++++++++++++++ 5 files changed, 247 insertions(+), 36 deletions(-) create mode 100644 phpunit.xml.dist delete mode 100644 src/TestSuite/Fixture/Extension/PHPUnitBeforeTestMethodCalledSubscriber.php create mode 100644 src/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriber.php create mode 100644 tests/TestCase/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriberTest.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..bd68de9 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,34 @@ + + + + + + + + + + + tests/TestCase/ + + + + + + src/ + + + diff --git a/src/TestSuite/Fixture/Extension/PHPUnitBeforeTestMethodCalledSubscriber.php b/src/TestSuite/Fixture/Extension/PHPUnitBeforeTestMethodCalledSubscriber.php deleted file mode 100644 index 9761215..0000000 --- a/src/TestSuite/Fixture/Extension/PHPUnitBeforeTestMethodCalledSubscriber.php +++ /dev/null @@ -1,35 +0,0 @@ -begin(); - } -} diff --git a/src/TestSuite/Fixture/Extension/PHPUnitExtension.php b/src/TestSuite/Fixture/Extension/PHPUnitExtension.php index 978bd0d..81203ca 100644 --- a/src/TestSuite/Fixture/Extension/PHPUnitExtension.php +++ b/src/TestSuite/Fixture/Extension/PHPUnitExtension.php @@ -37,7 +37,7 @@ public function bootstrap(Configuration $configuration, Facade $facade, Paramete $facade->registerSubscribers( new PHPUnitStartedSubscriber($fixtureManager), - new PHPUnitBeforeTestMethodCalledSubscriber(), + new PHPUnitPreparationStartedSubscriber(), new PHPUnitAfterTestMethodFinishedSubscriber() ); } diff --git a/src/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriber.php b/src/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriber.php new file mode 100644 index 0000000..fc4a38f --- /dev/null +++ b/src/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriber.php @@ -0,0 +1,45 @@ +inTransaction()) { + $connection->rollback(true); + } + $connection->begin(); + } +} diff --git a/tests/TestCase/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriberTest.php b/tests/TestCase/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriberTest.php new file mode 100644 index 0000000..082c9a5 --- /dev/null +++ b/tests/TestCase/TestSuite/Fixture/Extension/PHPUnitPreparationStartedSubscriberTest.php @@ -0,0 +1,167 @@ +connection = new class extends Connection { + /** + * @var array + */ + public array $calls = []; + + /** + * @var bool + */ + public bool $inTransaction = false; + + /** + * Skip the parent constructor, the test never touches the driver. + */ + public function __construct() + { + } + + /** + * @return bool + */ + public function inTransaction(): bool + { + return $this->inTransaction; + } + + /** + * @return void + */ + public function begin(): void + { + $this->calls[] = 'begin'; + $this->inTransaction = true; + } + + /** + * @param bool|null $toBeginning Whether the transaction should be rolled back to the beginning. + * @return bool + */ + public function rollback(?bool $toBeginning = null): bool + { + $this->calls[] = 'rollback'; + $this->inTransaction = false; + + return true; + } + }; + + ConnectionManager::drop('test'); + ConnectionManager::setConfig('test', $this->connection); + } + + /** + * The subscriber opens the per-test transaction on the PreparationStarted event. + * + * @return void + */ + public function testOpensTransactionOnPreparationStarted(): void + { + $subscriber = new PHPUnitPreparationStartedSubscriber(); + $this->assertInstanceOf(PreparationStartedSubscriber::class, $subscriber); + + $subscriber->notify($this->preparationStartedEvent()); + + $this->assertSame(['begin'], $this->connection->calls); + } + + /** + * A transaction left open by a previous test is rolled back before beginning. + * + * @return void + */ + public function testRollsBackAbandonedTransactionBeforeBeginning(): void + { + $this->connection->inTransaction = true; + + (new PHPUnitPreparationStartedSubscriber())->notify($this->preparationStartedEvent()); + + $this->assertSame(['rollback', 'begin'], $this->connection->calls); + } + + /** + * Builds a PreparationStarted event; the subscriber ignores the payload. + * + * @return \PHPUnit\Event\Test\PreparationStarted + */ + protected function preparationStartedEvent(): PreparationStarted + { + $snapshot = new Snapshot( + HRTime::fromSecondsAndNanoseconds(0, 0), + MemoryUsage::fromBytes(0), + MemoryUsage::fromBytes(0), + new GarbageCollectorStatus(0, 0, 0, 0, null, null, null, null, null, null, null, null), + ); + $telemetry = new Info( + $snapshot, + Duration::fromSecondsAndNanoseconds(0, 0), + MemoryUsage::fromBytes(0), + Duration::fromSecondsAndNanoseconds(0, 0), + MemoryUsage::fromBytes(0), + ); + $test = new class ('PreparationStarted') extends EventTest { + /** + * @return string + */ + public function id(): string + { + return 'CakeDC\DbTest\Test\TestCase\PreparationStarted::test'; + } + + /** + * @return string + */ + public function name(): string + { + return 'test'; + } + }; + + return new PreparationStarted($telemetry, $test); + } +} From bb62fc7d3cebc8aa54e273e45f4077e6c1535493 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Sat, 17 Oct 2026 11:01:50 -0400 Subject: [PATCH 2/2] feat: add CI workflow for testing and static analysis --- .github/workflows/ci.yml | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a6e38be --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,78 @@ +name: CI + +on: + push: + + pull_request: + branches: + - '*' + +permissions: + contents: read + +jobs: + testsuite: + name: PHP ${{ matrix.php-version }} + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + # composer.json declares php >=8.1 and cakephp/cakephp ^5.0. + # CakePHP 5.0-5.2 allow PHP 8.1; 5.3+ requires PHP 8.2, so on 8.1 + # composer resolves 5.2.x and on 8.2+ the latest 5.x. Test the whole + # declared range: 8.1 (min) -> 8.5 (newest). + php-version: ['8.1', '8.2', '8.3', '8.4', '8.5'] + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl, apcu, sqlite3, pdo_sqlite + ini-values: apc.enable_cli=1 + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + + - name: Cache composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ matrix.php-version }}-${{ hashFiles('composer.json') }} + restore-keys: ${{ runner.os }}-composer-${{ matrix.php-version }}- + + - name: Install dependencies + # composer.lock is gitignored, so resolve dependencies on each run. + run: composer update --prefer-dist --no-interaction --no-progress + + - name: Run PHPUnit + run: vendor/bin/phpunit + + cs-stan: + name: Coding Standard & Static Analysis + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: mbstring, intl, apcu + coverage: none + + - name: Install dependencies + run: composer update --prefer-dist --no-interaction --no-progress + + - name: Run PHP CodeSniffer + run: composer cs-check + + # NOTE: phpstan/psalm are pinned to 1.10.14 / 5.10.0 in .phive/phars.xml; + # those versions do not run on PHP 8.2+ (fatal in better-reflection) and + # report pre-existing findings. Modernize the pins in a separate change + # before wiring them back into CI as a blocking step.