浏览代码

Add a formal interface for fixture state managers

Add a more formal interface for data-only fixture state managers. This
will be useful for userland implementations or plugins like
ElasticSearch which will need their own fixture state management.
Mark Story 5 年之前
父节点
当前提交
651d050ed1

+ 47 - 0
src/TestSuite/Fixture/StateResetStrategyInterface.php

@@ -0,0 +1,47 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ * @link          https://cakephp.org CakePHP(tm) Project
+ * @since         4.3.0
+ * @license       https://opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\TestSuite\Fixture;
+
+/**
+ * Interface for fixture state management.
+ *
+ * This interface exposes hooks that run before and
+ * after tests. This allows test database state to be 'prepared'
+ * and 'cleaned up'.
+ */
+interface StateResetStrategyInterface
+{
+    /**
+     * Before test hook
+     *
+     * Fired before each test is started.
+     *
+     * @param string $test The test that is going to run.
+     * @return void
+     */
+    public function beforeTest(string $test): void;
+
+    /**
+     * After test hook
+     *
+     * Fired after each test is complete.
+     *
+     * @param string $test The test that was completed.
+     * @return void
+     */
+    public function afterTest(string $test): void;
+}

+ 5 - 5
src/TestSuite/Fixture/TransactionStrategy.php

@@ -27,10 +27,8 @@ use RuntimeException;
  * This strategy aims to gives good performance at the cost
  * of not being able to query data in fixtures from another
  * process.
- *
- * @TODO create a strategy interface
  */
-class TransactionStrategy
+class TransactionStrategy implements StateResetStrategyInterface
 {
     /**
      * Constructor.
@@ -90,9 +88,10 @@ class TransactionStrategy
     /**
      * Before each test start a transaction.
      *
+     * @param string $test The test that was completed.
      * @return void
      */
-    public function beforeTest(): void
+    public function beforeTest(string $test): void
     {
         $connections = ConnectionManager::configured();
         foreach ($connections as $connection) {
@@ -114,9 +113,10 @@ class TransactionStrategy
      * operations we should end up at a transaction depth of 0
      * and we will rollback the root transaction started in beforeTest()
      *
+     * @param string $test The test that was completed.
      * @return void
      */
-    public function afterTest(): void
+    public function afterTest(string $test): void
     {
         $connections = ConnectionManager::configured();
         foreach ($connections as $connection) {

+ 5 - 3
src/TestSuite/Fixture/TruncationStrategy.php

@@ -32,7 +32,7 @@ use Cake\Datasource\ConnectionManager;
  * This mode also offers 'backwards compatible' behavior
  * with the schema + data fixture system.
  */
-class TruncationStrategy
+class TruncationStrategy implements StateResetStrategyInterface
 {
     /**
      * Constructor.
@@ -82,9 +82,10 @@ class TruncationStrategy
     /**
      * Before each test start a transaction.
      *
+     * @param string $test The test that was completed.
      * @return void
      */
-    public function beforeTest(): void
+    public function beforeTest(string $test): void
     {
         $connections = ConnectionManager::configured();
         foreach ($connections as $connection) {
@@ -117,9 +118,10 @@ class TruncationStrategy
      *
      * Implemented to satisfy the interface.
      *
+     * @param string $test The test that was completed.
      * @return void
      */
-    public function afterTest(): void
+    public function afterTest(string $test): void
     {
         // Do nothing
     }

+ 15 - 3
src/TestSuite/FixtureSchemaExtension.php

@@ -18,9 +18,12 @@ namespace Cake\TestSuite;
 
 use Cake\TestSuite\Fixture\FixtureDataManager;
 use Cake\TestSuite\Fixture\FixtureLoader;
+use Cake\TestSuite\Fixture\StateResetStrategyInterface;
 use Cake\TestSuite\Fixture\TransactionStrategy;
+use InvalidArgumentException;
 use PHPUnit\Runner\AfterTestHook;
 use PHPUnit\Runner\BeforeTestHook;
+use ReflectionClass;
 
 /**
  * PHPUnit extension to integrate CakePHP's data-only fixtures.
@@ -30,7 +33,7 @@ class FixtureSchemaExtension implements
     BeforeTestHook
 {
     /**
-     * @var object
+     * @var \Cake\TestSuite\Fixture\StateResetStrategyInterface
      */
     protected $state;
 
@@ -38,10 +41,19 @@ class FixtureSchemaExtension implements
      * Constructor.
      *
      * @param string $stateStrategy The state management strategy to use.
+     * @psalm-param class-string<\Cake\TestSuite\Fixture\StateResetStrategyInterface> $stateStrategy
      */
     public function __construct(string $stateStrategy = TransactionStrategy::class)
     {
         $enableLogging = in_array('--debug', $_SERVER['argv'] ?? [], true);
+        $class = new ReflectionClass($stateStrategy);
+        if (!$class->implementsInterface(StateResetStrategyInterface::class)) {
+            throw new InvalidArgumentException(sprintf(
+                'Invalid stateStrategy provided. State strategies must implement `%s`. Got `%s`.',
+                StateResetStrategyInterface::class,
+                $stateStrategy
+            ));
+        }
         $this->state = new $stateStrategy($enableLogging);
 
         FixtureLoader::setInstance(new FixtureDataManager());
@@ -55,7 +67,7 @@ class FixtureSchemaExtension implements
      */
     public function executeBeforeTest(string $test): void
     {
-        $this->state->beforeTest();
+        $this->state->beforeTest($test);
     }
 
     /**
@@ -67,6 +79,6 @@ class FixtureSchemaExtension implements
      */
     public function executeAfterTest(string $test, float $time): void
     {
-        $this->state->afterTest();
+        $this->state->afterTest($test);
     }
 }

+ 2 - 2
tests/TestCase/TestSuite/Fixture/TransactionStrategyTest.php

@@ -34,14 +34,14 @@ class TransactionStrategyTest extends TestCase
         $users = TableRegistry::get('Users');
 
         $strategy = new TransactionStrategy();
-        $strategy->beforeTest();
+        $strategy->beforeTest(__METHOD__);
         $user = $users->newEntity(['username' => 'testing', 'password' => 'secrets']);
 
         $users->save($user, ['atomic' => true]);
         $this->assertNotEmpty($users->get($user->id), 'User should exist.');
 
         // Rollback and the user should be gone.
-        $strategy->afterTest();
+        $strategy->afterTest(__METHOD__);
         $this->assertNull($users->findById($user->id)->first(), 'No user expected.');
     }
 }

+ 1 - 1
tests/TestCase/TestSuite/Fixture/TruncationStrategyTest.php

@@ -43,7 +43,7 @@ class TruncationStrategyTest extends TestCase
         $this->assertGreaterThan(0, $rowCount);
 
         $strategy = new TruncationStrategy();
-        $strategy->beforeTest();
+        $strategy->beforeTest(__METHOD__);
 
         $rowCount = $articles->find()->count();
         $this->assertEquals(0, $rowCount);