Browse Source

Merge pull request #13349 from cakephp/4.x-fixtures

4.x fixtures
Mark Story 6 years ago
parent
commit
fe405e3a35

+ 1 - 34
psalm-baseline.xml

@@ -2060,29 +2060,6 @@
     <NoInterfaceProperties occurrences="1">
       <code>$test-&gt;fixtureManager</code>
     </NoInterfaceProperties>
-    <PropertyNotSetInConstructor occurrences="1">
-      <code>$_first</code>
-    </PropertyNotSetInConstructor>
-  </file>
-  <file src="src/TestSuite/Fixture/FixtureManager.php">
-    <MissingClosureParamType occurrences="7">
-      <code>$fixtures</code>
-      <code>$db</code>
-      <code>$fixtures</code>
-      <code>$db</code>
-      <code>$db</code>
-      <code>$fixtures</code>
-      <code>$fixtures</code>
-    </MissingClosureParamType>
-    <PossiblyFalseArgument occurrences="1">
-      <code>strrchr($fixture, '\\')</code>
-    </PossiblyFalseArgument>
-    <RedundantCondition occurrences="1">
-      <code>$exists &amp;&amp; !$isFixtureSetup &amp;&amp; $hasSchema</code>
-    </RedundantCondition>
-    <UndefinedPropertyAssignment occurrences="1">
-      <code>$test-&gt;fixtures</code>
-    </UndefinedPropertyAssignment>
   </file>
   <file src="src/TestSuite/Fixture/TestFixture.php">
     <InvalidPropertyAssignmentValue occurrences="1">
@@ -2091,19 +2068,9 @@
     <MismatchingDocblockReturnType occurrences="1">
       <code>TableSchemaInterface</code>
     </MismatchingDocblockReturnType>
-    <PossiblyNullArgument occurrences="1">
-      <code>$this-&gt;table</code>
-    </PossiblyNullArgument>
-    <PossiblyNullArrayAccess occurrences="1">
-      <code>$this-&gt;_schema-&gt;getColumn($field)['type']</code>
-    </PossiblyNullArrayAccess>
-    <PropertyNotSetInConstructor occurrences="2">
-      <code>$table</code>
+    <PropertyNotSetInConstructor occurrences="1">
       <code>$_schema</code>
     </PropertyNotSetInConstructor>
-    <UninitializedProperty occurrences="1">
-      <code>$this-&gt;table</code>
-    </UninitializedProperty>
   </file>
   <file src="src/TestSuite/IntegrationTestTrait.php">
     <InvalidCatch occurrences="1"/>

+ 45 - 0
src/Database/ConstraintsInterface.php

@@ -0,0 +1,45 @@
+<?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.0.0
+ * @license       https://opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Database;
+
+use Cake\Datasource\ConnectionInterface;
+
+/**
+ * Defines the interface for managing constraints.
+ */
+interface ConstraintsInterface
+{
+    /**
+     * Build and execute SQL queries necessary to create the constraints for the
+     * fixture
+     *
+     * @param \Cake\Datasource\ConnectionInterface $db An instance of the database
+     *  into which the constraints will be created.
+     * @return bool on success or if there are no constraints to create, or false on failure
+     */
+    public function createConstraints(ConnectionInterface $db): bool;
+
+    /**
+     * Build and execute SQL queries necessary to drop the constraints for the
+     * fixture
+     *
+     * @param \Cake\Datasource\ConnectionInterface $db An instance of the database
+     *  into which the constraints will be dropped.
+     * @return bool on success or if there are no constraints to drop, or false on failure
+     */
+    public function dropConstraints(ConnectionInterface $db): bool;
+}

+ 0 - 20
src/Datasource/FixtureInterface.php

@@ -50,26 +50,6 @@ interface FixtureInterface
     public function insert(ConnectionInterface $db);
 
     /**
-     * Build and execute SQL queries necessary to create the constraints for the
-     * fixture
-     *
-     * @param \Cake\Datasource\ConnectionInterface $db An instance of the database
-     *  into which the constraints will be created.
-     * @return bool on success or if there are no constraints to create, or false on failure
-     */
-    public function createConstraints(ConnectionInterface $db): bool;
-
-    /**
-     * Build and execute SQL queries necessary to drop the constraints for the
-     * fixture
-     *
-     * @param \Cake\Datasource\ConnectionInterface $db An instance of the database
-     *  into which the constraints will be dropped.
-     * @return bool on success or if there are no constraints to drop, or false on failure
-     */
-    public function dropConstraints(ConnectionInterface $db): bool;
-
-    /**
      * Truncates the current fixture.
      *
      * @param \Cake\Datasource\ConnectionInterface $db A reference to a db instance

+ 1 - 1
src/TestSuite/Fixture/FixtureInjector.php

@@ -40,7 +40,7 @@ class FixtureInjector implements TestListener
     /**
      * Holds a reference to the container test suite
      *
-     * @var \PHPUnit\Framework\TestSuite
+     * @var \PHPUnit\Framework\TestSuite|null
      */
     protected $_first;
 

+ 27 - 11
src/TestSuite/Fixture/FixtureManager.php

@@ -18,6 +18,7 @@ namespace Cake\TestSuite\Fixture;
 
 use Cake\Core\Configure;
 use Cake\Core\Exception\Exception;
+use Cake\Database\ConstraintsInterface;
 use Cake\Database\Schema\TableSchema;
 use Cake\Database\Schema\TableSchemaAwareInterface;
 use Cake\Datasource\ConnectionInterface;
@@ -210,6 +211,7 @@ class FixtureManager
                 $className = implode('\\', array_filter($nameSegments));
             } else {
                 $className = $fixture;
+                /** @psalm-suppress PossiblyFalseArgument */
                 $name = preg_replace('/Fixture\z/', '', substr(strrchr($fixture, '\\'), 1));
             }
 
@@ -254,7 +256,7 @@ class FixtureManager
 
         $hasSchema = $fixture instanceof TableSchemaAwareInterface && $fixture->getTableSchema() instanceof TableSchema;
 
-        if (($drop && $exists) || ($exists && !$isFixtureSetup && $hasSchema)) {
+        if (($drop && $exists) || ($exists && $hasSchema)) {
             $fixture->drop($db);
             $fixture->create($db);
         } elseif (!$exists) {
@@ -285,16 +287,20 @@ class FixtureManager
         }
 
         try {
-            $createTables = function (ConnectionInterface $db, $fixtures) use ($test): void {
+            $createTables = function (ConnectionInterface $db, array $fixtures) use ($test): void {
                 $tables = $db->getSchemaCollection()->listTables();
                 $configName = $db->configName();
                 if (!isset($this->_insertionMap[$configName])) {
                     $this->_insertionMap[$configName] = [];
                 }
 
-                /** @var \Cake\TestSuite\Fixture\TestFixture[] $fixtures */
+                /** @var \Cake\Datasource\FixtureInterface[] $fixtures */
                 foreach ($fixtures as $fixture) {
-                    if (in_array($fixture->table, $tables, true)) {
+                    if (!$fixture instanceof ConstraintsInterface) {
+                        continue;
+                    }
+
+                    if (in_array($fixture->sourceName(), $tables, true)) {
                         try {
                             $fixture->dropConstraints($db);
                         } catch (PDOException $e) {
@@ -318,6 +324,10 @@ class FixtureManager
                 }
 
                 foreach ($fixtures as $fixture) {
+                    if (!$fixture instanceof ConstraintsInterface) {
+                        continue;
+                    }
+
                     try {
                         $fixture->createConstraints($db);
                     } catch (PDOException $e) {
@@ -334,7 +344,7 @@ class FixtureManager
             $this->_runOperation($fixtures, $createTables);
 
             // Use a separate transaction because of postgres.
-            $insert = function ($db, $fixtures) use ($test): void {
+            $insert = function (ConnectionInterface $db, array $fixtures) use ($test): void {
                 foreach ($fixtures as $fixture) {
                     try {
                         $fixture->insert($db);
@@ -378,7 +388,7 @@ class FixtureManager
                 $db->disableQueryLogging();
             }
             $db->transactional(function (ConnectionInterface $db) use ($fixtures, $operation): void {
-                $db->disableConstraints(function ($db) use ($fixtures, $operation): void {
+                $db->disableConstraints(function (ConnectionInterface $db) use ($fixtures, $operation): void {
                     $operation($db, $fixtures);
                 });
             });
@@ -418,11 +428,13 @@ class FixtureManager
         if (empty($test->fixtures)) {
             return;
         }
-        $truncate = function ($db, $fixtures): void {
+        $truncate = function (ConnectionInterface $db, array $fixtures): void {
             $configName = $db->configName();
 
             foreach ($fixtures as $name => $fixture) {
-                if ($this->isFixtureSetup($configName, $fixture)) {
+                if ($this->isFixtureSetup($configName, $fixture)
+                    && $fixture instanceof ConstraintsInterface
+                ) {
                     $fixture->dropConstraints($db);
                 }
             }
@@ -463,11 +475,15 @@ class FixtureManager
         }
 
         if (!$dropTables) {
-            $fixture->dropConstraints($db);
+            if ($fixture instanceof ConstraintsInterface) {
+                $fixture->dropConstraints($db);
+            }
             $fixture->truncate($db);
         }
 
-        $fixture->createConstraints($db);
+        if ($fixture instanceof ConstraintsInterface) {
+            $fixture->createConstraints($db);
+        }
         $fixture->insert($db);
     }
 
@@ -478,7 +494,7 @@ class FixtureManager
      */
     public function shutDown(): void
     {
-        $shutdown = function (ConnectionInterface $db, $fixtures): void {
+        $shutdown = function (ConnectionInterface $db, array $fixtures): void {
             $connection = $db->configName();
             /** @var \Cake\Datasource\FixtureInterface $fixture */
             foreach ($fixtures as $fixture) {

+ 8 - 4
src/TestSuite/Fixture/TestFixture.php

@@ -16,6 +16,7 @@ declare(strict_types=1);
 namespace Cake\TestSuite\Fixture;
 
 use Cake\Core\Exception\Exception as CakeException;
+use Cake\Database\ConstraintsInterface;
 use Cake\Database\Schema\TableSchema;
 use Cake\Database\Schema\TableSchemaAwareInterface;
 use Cake\Database\Schema\TableSchemaInterface;
@@ -31,7 +32,7 @@ use Exception;
  * Cake TestFixture is responsible for building and destroying tables to be used
  * during testing.
  */
-class TestFixture implements FixtureInterface, TableSchemaAwareInterface
+class TestFixture implements ConstraintsInterface, FixtureInterface, TableSchemaAwareInterface
 {
     use LocatorAwareTrait;
 
@@ -46,6 +47,7 @@ class TestFixture implements FixtureInterface, TableSchemaAwareInterface
      * Full Table Name
      *
      * @var string
+     * @psalm-suppress PropertyNotSetInConstructor
      */
     public $table;
 
@@ -105,7 +107,7 @@ class TestFixture implements FixtureInterface, TableSchemaAwareInterface
                 $message = sprintf(
                     'Invalid datasource name "%s" for "%s" fixture. Fixture datasource names must begin with "test".',
                     $connection,
-                    $this->table
+                    static::class
                 );
                 throw new CakeException($message);
             }
@@ -332,7 +334,7 @@ class TestFixture implements FixtureInterface, TableSchemaAwareInterface
             [$fields, $values, $types] = $this->_getRecords();
             $query = $db->newQuery()
                 ->insert($fields, $types)
-                ->into($this->table);
+                ->into($this->sourceName());
 
             foreach ($values as $row) {
                 $query->values($row);
@@ -412,7 +414,9 @@ class TestFixture implements FixtureInterface, TableSchemaAwareInterface
         }
         $fields = array_values(array_unique($fields));
         foreach ($fields as $field) {
-            $types[$field] = $this->_schema->getColumn($field)['type'];
+            /** @var array $column */
+            $column = $this->_schema->getColumn($field);
+            $types[$field] = $column['type'];
         }
         $default = array_fill_keys($fields, null);
         foreach ($this->records as $record) {

+ 7 - 0
src/TestSuite/TestCase.php

@@ -46,6 +46,13 @@ abstract class TestCase extends BaseTestCase
     public $fixtureManager;
 
     /**
+     * Fixtures used by this test case.
+     *
+     * @var string[]
+     */
+    public $fixtures = [];
+
+    /**
      * By default, all fixtures attached to this class will be truncated and reloaded after each test.
      * Set this to false to handle manually
      *