From 8d9699893839a15990451665fd49070954f5b844 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Sat, 25 Apr 2020 13:42:44 +0200 Subject: [PATCH] 1.x dev (#3) * wip * added json based configuration, rabbitmq wip * fix travis --- .gitignore | 3 +- .integration-testing.json | 69 +++ .phpunit.result.cache | 1 - .travis.yml | 10 +- Makefile | 19 + README.md | 86 ++- phpunit-integration.xml.dist | 28 +- resources/jsonschema/integration-testing.json | 533 ++++++++++++++++++ src/Driver/FileSystem.php | 29 +- .../Runner/Extension/Configuration.php | 126 +++++ .../Runner/Extension/FixtureLoader.php | 13 + src/PHPUnit/Runner/Extension/Handler.php | 92 +++ ...tensionConfig.php => PDOFixtureConfig.php} | 7 +- ...baseExtension.php => PDOFixtureLoader.php} | 29 +- src/WithAfterTestFixtureName.php | 1 + src/WithBeforeTestFixtureName.php | 1 + .../FileSystem/HandlerConfigurationTest.php | 32 ++ .../MariaDB/PDOIntegrationTest.php | 4 +- ...DOWithoutBeforeOrAfterTestFixturesTest.php | 4 +- .../Runner/Extension/ConfigurationTest.php | 20 + .../Extension/PDODatabaseExtensionTest.php | 35 +- 21 files changed, 1015 insertions(+), 127 deletions(-) create mode 100644 .integration-testing.json delete mode 100644 .phpunit.result.cache create mode 100644 Makefile create mode 100644 resources/jsonschema/integration-testing.json create mode 100644 src/PHPUnit/Runner/Extension/Configuration.php create mode 100644 src/PHPUnit/Runner/Extension/FixtureLoader.php create mode 100644 src/PHPUnit/Runner/Extension/Handler.php rename src/PHPUnit/Runner/Extension/{PDODatabaseExtensionConfig.php => PDOFixtureConfig.php} (95%) rename src/PHPUnit/Runner/Extension/{PDODatabaseExtension.php => PDOFixtureLoader.php} (72%) create mode 100644 tests/integration/FileSystem/HandlerConfigurationTest.php create mode 100644 tests/unit/PHPUnit/Runner/Extension/ConfigurationTest.php diff --git a/.gitignore b/.gitignore index cb7285e..ca6d925 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ /build/ composer.lock .php_cs.cache -phpunit.xml \ No newline at end of file +phpunit.xml +.phpunit.result.cache \ No newline at end of file diff --git a/.integration-testing.json b/.integration-testing.json new file mode 100644 index 0000000..86a6539 --- /dev/null +++ b/.integration-testing.json @@ -0,0 +1,69 @@ +{ + "pdo": { + "dsn": "mysql:host=localhost:3306;dbname=test;charset=utf8", + "user": "test", + "password": "test", + "fixtures": { + "beforeFirstTest": { + "path": "tests/fixtures/before-first-test", + "extension": "sql" + }, + "beforeTest": { + "path": "tests/fixtures/before-test", + "extension": "sql" + }, + "afterTest": { + "path": "tests/fixtures/after-test" + }, + "afterLastTest": { + "path": "tests/fixtures/after-last-test" + } + } + }, + "amqp": { + "host": "localhost", + "port": 5672, + "user": "test", + "password": "test", + "vhost": "test", + "fixtures": { + "beforeFirstTest": { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "exchange": "test-exchange", + "queue": "test-queue", + "routing_key": "before-first-test", + "path": "tests/fixtures/before-first-test", + "extension": "json" + } + ] + }, + "beforeTest": { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "exchange": "test-exchange", + "queue": "test-queue", + "routing_key": "before-test", + "path": "tests/fixtures/before-test" + } + ] + }, + "afterTest": { + "purgeQueues": [ + "test-queue" + ] + }, + "afterLastTest": { + "purgeQueues": [ + "test-queue" + ] + } + } + } +} \ No newline at end of file diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index b99eaf6..0000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -C:37:"PHPUnit\Runner\DefaultTestResultCache":1962:{a:2:{s:7:"defects";a:7:{s:98:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testBeforeFirstTestBehaviour";i:5;s:93:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testBeforeTestBehaviour";i:5;s:92:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testAfterTestBehaviour";i:5;s:96:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testAfterLastTestBehaviour";i:5;s:92:"IntegrationTesting\Tests\Integration\MariaDB\PDOIntegrationTest::testReadFixtureFromDatabase";i:5;s:124:"IntegrationTesting\Tests\Integration\MariaDB\PDOWithoutBeforeOrAfterTestFixturesTest::testReadingEphemeralTableHasNoContents";i:5;s:137:"IntegrationTesting\Tests\Integration\MariaDB\PDOWithoutBeforeOrAfterTestFixturesTest::testPersistentTableHasRowCountEqualsToTestsExecuted";i:3;}s:5:"times";a:9:{s:98:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testBeforeFirstTestBehaviour";d:0.005;s:93:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testBeforeTestBehaviour";d:0.005;s:92:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testAfterTestBehaviour";d:0.02;s:96:"IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionTest::testAfterLastTestBehaviour";d:0.005;s:92:"IntegrationTesting\Tests\Integration\MariaDB\PDOIntegrationTest::testReadFixtureFromDatabase";d:0.006;s:124:"IntegrationTesting\Tests\Integration\MariaDB\PDOWithoutBeforeOrAfterTestFixturesTest::testReadingEphemeralTableHasNoContents";d:0.002;s:137:"IntegrationTesting\Tests\Integration\MariaDB\PDOWithoutBeforeOrAfterTestFixturesTest::testPersistentTableHasRowCountEqualsToTestsExecuted";d:0.011;s:121:"IntegrationTesting\Tests\Integration\MariaDB\PDOWithoutBeforeOrAfterTestFixturesTest::testPersistentTableHasAtLeastOneRow";d:0.002;s:100:"IntegrationTesting\Tests\Integration\MariaDB\PDOIntegrationTest::testPersistentTableHasAtLeastOneRow";d:0.002;}}} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 3bde9f2..e823224 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,6 @@ cache: directories: - $HOME/.composer/cache -env: - global: - - PHPUNIT_FLAGS='--testdox --verbose' - sudo: false notifications: @@ -21,6 +17,8 @@ matrix: fast_finish: true install: - - composer update + - make install -script: vendor/bin/phpunit $PHPUNIT_FLAGS \ No newline at end of file +script: + - make test-unit + - make test-integration diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..38db666 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +.PHONY : install beautify up down test-unit test-integration debug-test-integration +.DEFAULT : install + +install: + composer install -o +beautify: + vendor/bin/phpcbf --standard=PSR2 src tests +up: + docker-compose up -d --build +down: + docker-compose down --remove-orphans +test-unit: + vendor/bin/phpunit --testdox --verbose --color +test-integration: up + sleep 20 + @-vendor/bin/phpunit --color --testdox --verbose -c phpunit-integration.xml.dist + make down +debug-test-integration: + php -dxdebug.remote_mode=jit vendor/bin/phpunit --no-coverage --color --testdox --group debug -c phpunit-integration.xml.dist \ No newline at end of file diff --git a/README.md b/README.md index 3a46f26..8fbfe7e 100644 --- a/README.md +++ b/README.md @@ -34,78 +34,56 @@ composer require --dev hrodic/php-integration-testing On PHPUnit configuration XML file you must specify the extension with its configuration. -If you need help with PHPUnit extensions, please refer to the [Official Documentation](https://phpunit.readthedocs.io/en/9.1/configuration.html#the-extensions-element) - -As an example, look into phpunit-integration.xml.dist. - - -### PDO Driver - -If you need to test the integration of MySQL or MariaDB, use the PDO driver extension. +You are able to specify the configuration filename that you will be using. Defaults to .integration-testing.json ``` - + - - - - - tests/fixtures/before-first-test - - - tests/fixtures/before-test - - - tests/fixtures/after-test - - - tests/fixtures/after-last-test - - - - - - - mysql:host=localhost:3306;dbname=test;charset=utf8 - test - test - - + .integration-testing.json ``` -The extension class is -``` -IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtension -``` +You also check phpunit-integration.xml.dist example -which requires a configuration and a PDO connection as arguments via XML config - -The configuration class allows you to define in which paths your fixtures will be located +If you need help with PHPUnit extensions, please refer to the [Official Documentation](https://phpunit.readthedocs.io/en/9.1/configuration.html#the-extensions-element) -``` -IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtensionConfig -``` +### PDO Fixtures -The config keys to define each hook type are: +If you need to test the integration of MySQL or MariaDB, use the PDO driver extension. -* BEFORE_FIRST_TEST_PDO_FIXTURES_PATH -* BEFORE_TEST_PDO_FIXTURES_PATH -* AFTER_TEST_PDO_FIXTURES_PATH -* AFTER_LAST_TEST_PDO_FIXTURES_PATH +It requires configuration parameters that can be found in the json config file. -The PDOConnection class is just a wrapper of the PDO PHP class. +The most important parameters are DSN, username and password of your database + some fixture path definitions. +Example: ``` -IntegrationTesting\Driver\PDOConnection +"pdo": { + "dsn": "mysql:host=localhost:3306;dbname=test;charset=utf8", + "user": "test", + "password": "test", + "fixtures": { + "beforeFirstTest": { + "path": "tests/fixtures/before-first-test", + "extension": "sql" + }, + "beforeTest": { + "path": "tests/fixtures/before-test", + "extension": "sql" + }, + "afterTest": { + "path": "tests/fixtures/after-test" + }, + "afterLastTest": { + "path": "tests/fixtures/after-last-test" + } + } +}, ``` -It requires DSN, username and password of your database. - -### RabbitMQ driver +### RabbitMQ fixtures @todo diff --git a/phpunit-integration.xml.dist b/phpunit-integration.xml.dist index 49f98b4..36d7555 100644 --- a/phpunit-integration.xml.dist +++ b/phpunit-integration.xml.dist @@ -20,33 +20,9 @@ - + - - - - - tests/fixtures/before-first-test - - - tests/fixtures/before-test - - - tests/fixtures/after-test - - - tests/fixtures/after-last-test - - - - - - - mysql:host=localhost:3306;dbname=test;charset=utf8 - test - test - - + .integration-testing.json diff --git a/resources/jsonschema/integration-testing.json b/resources/jsonschema/integration-testing.json new file mode 100644 index 0000000..63e0186 --- /dev/null +++ b/resources/jsonschema/integration-testing.json @@ -0,0 +1,533 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "http://example.com/example.json", + "type": "object", + "title": "The Root Schema", + "description": "The root schema comprises the entire JSON document.", + "definitions": { + "pdoFixture": { + "$id": "#/definitions/pdoFixture", + "type": "object", + "title": "The pdoFixture Schema", + "description": "PDO fixture definition.", + "default": {}, + "examples": [ + { + + "extension": "sql", + "path": "tests/fixtures/before-first-test" + } + ], + "additionalProperties": true, + "required": [ + "path" + ], + "properties": { + "path": { + "type": "string", + "title": "The Path Schema", + "description": "Path to locate fixture files", + "default": "", + "examples": [ + "tests/fixtures/before-first-test" + ] + }, + "extension": { + "$id": "#/properties/pdo/properties/fixtures/properties/beforeFirstTest/properties/extension", + "type": "string", + "title": "The Extension Schema", + "description": "Fixture file extension.", + "default": "sql", + "examples": [ + "sql" + ] + } + } + }, + "amqpPurgeQueueFixture": { + "type": "array", + "title": "The Purge Schema", + "description": "AMQP purge queue fixture definition", + "default": [], + "examples": [ + [ + "test-queue" + ] + ], + "additionalItems": true, + "items": { + "type": "string", + "title": "The Items Schema", + "description": "List of queue names to purge.", + "default": "", + "examples": [ + "test-queue" + ] + } + }, + "amqpPublishFixture": { + "$id": "#/definitions/amqpPublishFixture", + "type": "array", + "title": "The Publish Schema", + "description": "AMQP Publish message definition.", + "default": [], + "examples": [ + [ + { + "queue": "test-queue", + "path": "tests/fixtures/before-first-test", + "extension": "json", + "exchange": "test-exchange", + "routing_key": "before-first-test" + } + ] + ], + "additionalItems": true, + "items": { + "type": "object", + "default": {}, + "examples": [ + { + "exchange": "test-exchange", + "routing_key": "before-first-test", + "queue": "test-queue", + "path": "tests/fixtures/before-first-test", + "extension": "json" + } + ], + "additionalProperties": true, + "required": [ + "exchange", + "queue", + "path" + ], + "properties": { + "exchange": { + "type": "string", + "title": "The Exchange Schema", + "description": "AMQP exchange name.", + "default": "", + "examples": [ + "test-exchange" + ] + }, + "queue": { + "type": "string", + "title": "The Queue Schema", + "description": "AMQP queue name.", + "default": "", + "examples": [ + "test-queue" + ] + }, + "routing_key": { + "type": "string", + "title": "The Routing_key Schema", + "description": "The key used for routing from the exchange to the queue.", + "default": "", + "examples": [ + "before-first-test" + ] + }, + "path": { + "type": "string", + "title": "The Path Schema", + "description": "Path to find message body files.", + "default": "", + "examples": [ + "tests/fixtures/before-first-test" + ] + }, + "extension": { + "type": "string", + "title": "The Extension Schema", + "description": "Extension of the message body files.", + "default": "json", + "examples": [ + "json" + ] + } + } + } + } + }, + "default": {}, + "additionalProperties": true, + "required": [], + "properties": { + "pdo": { + "$id": "#/properties/pdo", + "type": "object", + "title": "The Pdo Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "password": "test", + "user": "test", + "dsn": "mysql:host=mariadb;dbname=content;charset=utf8", + "fixtures": { + "beforeTest": { + "extension": "sql", + "path": "tests/fixtures/before-test" + }, + "afterTest": { + "path": "tests/fixtures/after-test", + "extension": "sql" + }, + "afterLastTest": { + "path": "tests/fixtures/after-last-test", + "extension": "sql" + }, + "beforeFirstTest": { + "extension": "sql", + "path": "tests/fixtures/before-first-test" + } + } + } + ], + "additionalProperties": true, + "required": [ + "fixtures" + ], + "properties": { + "dsn": { + "$id": "#/properties/pdo/properties/dsn", + "type": "string", + "title": "The Dsn Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "mysql:host=mariadb;dbname=content;charset=utf8" + ] + }, + "user": { + "$id": "#/properties/pdo/properties/user", + "type": "string", + "title": "The User Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "test" + ] + }, + "password": { + "$id": "#/properties/pdo/properties/password", + "type": "string", + "title": "The Password Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "test" + ] + }, + "fixtures": { + "$id": "#/properties/pdo/properties/fixtures", + "type": "object", + "title": "The Fixtures Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "afterTest": { + "extension": "sql", + "path": "tests/fixtures/after-test" + }, + "afterLastTest": { + "path": "tests/fixtures/after-last-test", + "extension": "sql" + }, + "beforeFirstTest": { + "path": "tests/fixtures/before-first-test" + }, + "beforeTest": { + "path": "tests/fixtures/before-test" + } + } + ], + "additionalProperties": true, + "required": [], + "properties": { + "beforeFirstTest": { + "$ref": "#/definitions/pdoFixture" + }, + "beforeTest": { + "$ref": "#/definitions/pdoFixture" + }, + "afterTest": { + "$ref": "#/definitions/pdoFixture" + }, + "afterLastTest": { + "$ref": "#/definitions/pdoFixture" + } + } + } + } + }, + "amqp": { + "$id": "#/properties/amqp", + "type": "object", + "title": "The amqp Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "vhost": "test", + "fixtures": { + "beforeTest": { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "exchange": "test-exchange", + "routing_key": "before-test", + "queue": "test-queue", + "path": "tests/fixtures/before-test", + "extension": "json" + } + ] + }, + "afterTest": { + "purgeQueues": [ + "test-queue" + ] + }, + "afterLastTest": { + "purgeQueues": [ + "test-queue" + ] + }, + "beforeFirstTest": { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "exchange": "test-exchange", + "routing_key": "before-first-test", + "queue": "test-queue", + "path": "tests/fixtures/before-first-test", + "extension": "json" + } + ] + } + }, + "password": "test", + "host": "rabbitmq", + "port": 5672.0, + "user": "test" + } + ], + "additionalProperties": true, + "required": [ + "fixtures" + ], + "properties": { + "host": { + "$id": "#/properties/amqp/properties/host", + "type": "string", + "title": "The Host Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "rabbitmq" + ] + }, + "port": { + "$id": "#/properties/amqp/properties/port", + "type": "integer", + "title": "The Port Schema", + "description": "An explanation about the purpose of this instance.", + "default": 0, + "examples": [ + 5672.0 + ] + }, + "user": { + "$id": "#/properties/amqp/properties/user", + "type": "string", + "title": "The User Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "test" + ] + }, + "password": { + "$id": "#/properties/amqp/properties/password", + "type": "string", + "title": "The Password Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "test" + ] + }, + "vhost": { + "$id": "#/properties/amqp/properties/vhost", + "type": "string", + "title": "The Vhost Schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "test" + ] + }, + "fixtures": { + "$id": "#/properties/amqp/properties/fixtures", + "type": "object", + "title": "The Fixtures Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "beforeTest": { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "extension": "json", + "exchange": "test-exchange", + "routing_key": "before-test", + "queue": "test-queue", + "path": "tests/fixtures/before-test" + } + ] + }, + "afterTest": { + "purgeQueues": [ + "test-queue" + ] + }, + "afterLastTest": { + "purgeQueues": [ + "test-queue" + ] + }, + "beforeFirstTest": { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "routing_key": "before-first-test", + "queue": "test-queue", + "path": "tests/fixtures/before-first-test", + "extension": "json", + "exchange": "test-exchange" + } + ] + } + } + ], + "additionalProperties": true, + "required": [], + "properties": { + "beforeFirstTest": { + "$id": "#/properties/amqp/properties/fixtures/properties/beforeFirstTest", + "type": "object", + "title": "The Beforefirsttest Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "extension": "json", + "exchange": "test-exchange", + "routing_key": "before-first-test", + "queue": "test-queue", + "path": "tests/fixtures/before-first-test" + } + ] + } + ], + "additionalProperties": true, + "required": [], + "properties": { + "purgeQueues": { "$ref": "#/definitions/amqpPurgeQueueFixture" }, + "publishMessages": { + "$ref": "#/definitions/amqpPublishFixture" + } + } + }, + "beforeTest": { + "$id": "#/properties/amqp/properties/fixtures/properties/beforeTest", + "type": "object", + "title": "The Beforetest Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "purgeQueues": [ + "test-queue" + ], + "publishMessages": [ + { + "routing_key": "before-test", + "queue": "test-queue", + "path": "tests/fixtures/before-test", + "extension": "json", + "exchange": "test-exchange" + } + ] + } + ], + "additionalProperties": true, + "required": [], + "properties": { + "purgeQueues": { "$ref": "#/definitions/amqpPurgeQueueFixture" }, + "publishMessages": { + "$ref": "#/definitions/amqpPublishFixture" + } + } + }, + "afterTest": { + "$id": "#/properties/amqp/properties/fixtures/properties/afterTest", + "type": "object", + "title": "The Aftertest Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "purgeQueues": [ + "test-queue" + ] + } + ], + "additionalProperties": true, + "required": [], + "properties": { + "purgeQueues": { "$ref": "#/definitions/amqpPurgeQueueFixture" } + } + }, + "afterLastTest": { + "$id": "#/properties/amqp/properties/fixtures/properties/afterLastTest", + "type": "object", + "title": "The Afterlasttest Schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "purgeQueues": [ + "test-queue" + ] + } + ], + "additionalProperties": true, + "required": [], + "properties": { + "purgeQueues": { "$ref": "#/definitions/amqpPurgeQueueFixture" } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Driver/FileSystem.php b/src/Driver/FileSystem.php index 2b36bea..8961264 100644 --- a/src/Driver/FileSystem.php +++ b/src/Driver/FileSystem.php @@ -11,17 +11,36 @@ class FileSystem { /** * @param string $path - * @param string $extension - * @return Iterator + * @return string * @throws TestingException */ - public static function getFileListIteratorFromPathByExtension(string $path, string $extension): Iterator + private function getRealPath(string $path): string { $realPath = realpath($path); if (!$realPath) { throw new TestingException("The path [$path] is not valid"); } - $iterator = new FilesystemIterator($realPath); + return $realPath; + } + + public function getFileContents(string $path): string + { + $path = $this->getRealPath($path); + if (!is_readable($path)) { + throw new TestingException("Filepath [$path] is not readable"); + } + return file_get_contents($path); + } + + /** + * @param string $path + * @param string $extension + * @return Iterator + * @throws TestingException + */ + public function getFileListIteratorFromPathByExtension(string $path, string $extension): Iterator + { + $iterator = new FilesystemIterator($this->getRealPath($path)); $fileList = new ArrayIterator(); foreach ($iterator as $path => $fileInfo) { if ($fileInfo->isFile() && $fileInfo->isReadable() && $fileInfo->getExtension() === $extension) { @@ -35,7 +54,7 @@ public static function getFileListIteratorFromPathByExtension(string $path, stri * @param Iterator $iterator * @param callable $callback */ - public static function runCallbackOnEachFileIteratorContents(Iterator $iterator, callable $callback): void + public function runCallbackOnEachFileIteratorContents(Iterator $iterator, callable $callback): void { foreach ($iterator as $filePath) { $callback(file_get_contents($filePath)); diff --git a/src/PHPUnit/Runner/Extension/Configuration.php b/src/PHPUnit/Runner/Extension/Configuration.php new file mode 100644 index 0000000..40dfbd8 --- /dev/null +++ b/src/PHPUnit/Runner/Extension/Configuration.php @@ -0,0 +1,126 @@ + 'mysql:host=localhost:3306;dbname=test;charset=utf8', + 'user' => 'test', + 'password' => 'test', + 'fixtures' => [ + 'beforeFirstTest' => [], + 'beforeTest' => [], + 'afterTest' => [], + 'afterLastTest' => [], + ] + ]; + private static $defaultAMQPParams = [ + 'host' => 'rabbitmq', + 'port' => 5672, + 'user' => 'test', + 'password' => 'test', + 'vhost' => 'test', + 'fixtures' => [ + 'beforeFirstTest' => [ + 'purgeQueues' => [], + 'publishMessages' => [] + ], + 'beforeTest' => [ + 'purgeQueues' => [], + 'publishMessages' => [] + ], + 'afterTest' => [ + 'purgeQueues' => [] + ], + 'afterLastTest' => [ + 'purgeQueues' => [] + ] + ] + ]; + private $PDOParams = []; + private $AMQPParams = []; + + /** + * PDODatabaseExtensionConfig constructor. + * + * @param array $params + * @throws TestingException + */ + public function __construct(array $params) + { + if (empty($params)) { + throw new TestingException('Configuration parameters are empty'); + } + if (isset($params[self::PDO_KEY])) { + if ($invalidConfigParams = array_diff_key($params[self::PDO_KEY], self::$defaultPDOParams)) { + throw new TestingException( + 'The following elements are not valid PDO configuration params: ' . json_encode($invalidConfigParams) + ); + } + $this->PDOParams = array_merge(self::$defaultPDOParams, $params[self::PDO_KEY]); + } + if (isset($params[self::AMQP_KEY])) { + if ($invalidConfigParams = array_diff_key($params[self::AMQP_KEY], self::$defaultAMQPParams)) { + throw new TestingException( + 'The following elements are not valid AMQP configuration params: ' . json_encode($invalidConfigParams) + ); + } + $this->AMQPParams = array_merge(self::$defaultAMQPParams, $params[self::AMQP_KEY]); + } + } + + public function getPDODSN(): string + { + return $this->PDOParams['dsn']; + } + + public function getPDOUser(): string + { + return $this->PDOParams['user']; + } + + public function getPDOPassword(): string + { + return $this->PDOParams['password']; + } + + public function getPDOFixtures(): array + { + return $this->PDOParams['fixtures']; + } + + public function getAMQPHost(): string + { + return $this->AMQPParams['host']; + } + + public function getAMQPPort(): int + { + return (int)$this->AMQPParams['port']; + } + + public function getAMQPUser(): string + { + return $this->AMQPParams['user']; + } + + public function getAMQPPassword(): string + { + return $this->AMQPParams['password']; + } + + public function getAMQPVhost(): string + { + return $this->AMQPParams['vhost']; + } + + public function getAMQPFixtures(): array + { + return $this->AMQPParams['fixtures']; + } +} diff --git a/src/PHPUnit/Runner/Extension/FixtureLoader.php b/src/PHPUnit/Runner/Extension/FixtureLoader.php new file mode 100644 index 0000000..fac8256 --- /dev/null +++ b/src/PHPUnit/Runner/Extension/FixtureLoader.php @@ -0,0 +1,13 @@ +fileSystem = new FileSystem(); + } + $this->fixtureLoaders = new \SplObjectStorage(); + $configuration = $this->getConfigurationFromFileName($configurationFileName); + if ($configuration->getPDODSN()) { + $pdoFixtureConfig = new PDOFixtureConfig([ + PDOFixtureConfig::BEFORE_FIRST_TEST_PDO_FIXTURES_PATH => + $configuration->getPDOFixtures()['beforeFirstTest']['path'], + PDOFixtureConfig::BEFORE_TEST_PDO_FIXTURES_PATH => + $configuration->getPDOFixtures()['beforeTest']['path'], + PDOFixtureConfig::AFTER_TEST_PDO_FIXTURES_PATH => + $configuration->getPDOFixtures()['afterTest']['path'], + PDOFixtureConfig::AFTER_LAST_TEST_PDO_FIXTURES_PATH => + $configuration->getPDOFixtures()['afterLastTest']['path'] + ]); + $pdoConnection = new PDOConnection( + $configuration->getPDODSN(), + $configuration->getPDOUser(), + $configuration->getPDOPassword() + ); + $this->fixtureLoaders->attach(new PDOFixtureLoader($this->fileSystem, $pdoFixtureConfig, $pdoConnection)); + } + } + + public function executeBeforeFirstTest(): void + { + foreach ($this->fixtureLoaders as $fixtureLoader) { + $fixtureLoader->executeBeforeFirstTest(); + } + } + + public function executeBeforeTest(string $test): void + { + foreach ($this->fixtureLoaders as $fixtureLoader) { + $fixtureLoader->executeBeforeTest($test); + } + } + + public function executeAfterTest(string $test, float $time): void + { + foreach ($this->fixtureLoaders as $fixtureLoader) { + $fixtureLoader->executeAfterTest($test, $time); + } + } + + public function executeAfterLastTest(): void + { + foreach ($this->fixtureLoaders as $fixtureLoader) { + $fixtureLoader->executeAfterLastTest(); + } + } + + /** + * @param string $fileName + * @return Configuration + * @throws TestingException + */ + private function getConfigurationFromFileName(string $fileName): Configuration + { + if (empty($fileName)) { + $fileName = '.integration-testing.json'; + } + $data = json_decode($this->fileSystem->getFileContents($fileName), true); + return new Configuration($data); + } +} diff --git a/src/PHPUnit/Runner/Extension/PDODatabaseExtensionConfig.php b/src/PHPUnit/Runner/Extension/PDOFixtureConfig.php similarity index 95% rename from src/PHPUnit/Runner/Extension/PDODatabaseExtensionConfig.php rename to src/PHPUnit/Runner/Extension/PDOFixtureConfig.php index e03e025..e01905b 100644 --- a/src/PHPUnit/Runner/Extension/PDODatabaseExtensionConfig.php +++ b/src/PHPUnit/Runner/Extension/PDOFixtureConfig.php @@ -4,7 +4,7 @@ use IntegrationTesting\Exception\TestingException; -class PDODatabaseExtensionConfig +class PDOFixtureConfig { /** * @todo Currently there is a limitation on the extension array index type. @@ -25,7 +25,8 @@ class PDODatabaseExtensionConfig /** * PDODatabaseExtensionConfig constructor. - * @param array $params + * + * @param array $params * @throws TestingException */ public function __construct(array $params) @@ -42,7 +43,7 @@ public function __construct(array $params) } /** - * @param string $key + * @param string $key * @return string * @throws TestingException */ diff --git a/src/PHPUnit/Runner/Extension/PDODatabaseExtension.php b/src/PHPUnit/Runner/Extension/PDOFixtureLoader.php similarity index 72% rename from src/PHPUnit/Runner/Extension/PDODatabaseExtension.php rename to src/PHPUnit/Runner/Extension/PDOFixtureLoader.php index 0822851..13b72eb 100644 --- a/src/PHPUnit/Runner/Extension/PDODatabaseExtension.php +++ b/src/PHPUnit/Runner/Extension/PDOFixtureLoader.php @@ -5,20 +5,18 @@ use IntegrationTesting\Driver\FileSystem; use IntegrationTesting\Driver\PDOConnection; use IntegrationTesting\Exception\TestingException; -use PHPUnit\Runner\BeforeFirstTestHook; -use PHPUnit\Runner\BeforeTestHook; -use PHPUnit\Runner\AfterTestHook; -use PHPUnit\Runner\AfterLastTestHook; -final class PDODatabaseExtension implements BeforeFirstTestHook, BeforeTestHook, AfterTestHook, AfterLastTestHook +final class PDOFixtureLoader implements FixtureLoader { const EXTENSION_SQL = 'sql'; + private $fileSystem; private $config; private $connection; - public function __construct(PDODatabaseExtensionConfig $config, PDOConnection $connection) + public function __construct(FileSystem $fileSystem, PDOFixtureConfig $config, PDOConnection $connection) { + $this->fileSystem = $fileSystem; $this->config = $config; $this->connection = $connection; } @@ -28,7 +26,7 @@ public function __construct(PDODatabaseExtensionConfig $config, PDOConnection $c */ public function executeBeforeFirstTest(): void { - $path = $this->config->getParam(PDODatabaseExtensionConfig::BEFORE_FIRST_TEST_PDO_FIXTURES_PATH); + $path = $this->config->getParam(PDOFixtureConfig::BEFORE_FIRST_TEST_PDO_FIXTURES_PATH); $this->runFixturesUnderPath($path); } @@ -38,7 +36,7 @@ public function executeBeforeFirstTest(): void */ public function executeBeforeTest(string $test): void { - $stage = PDODatabaseExtensionConfig::BEFORE_TEST_PDO_FIXTURES_PATH; + $stage = PDOFixtureConfig::BEFORE_TEST_PDO_FIXTURES_PATH; $path = $this->config->getParam($stage); $this->runFixturesUnderPath($path); $className = '\\' . substr($test, 0, strpos($test, ':')); @@ -59,7 +57,7 @@ public function executeBeforeTest(string $test): void */ public function executeAfterTest(string $test, float $time): void { - $stage = PDODatabaseExtensionConfig::AFTER_TEST_PDO_FIXTURES_PATH; + $stage = PDOFixtureConfig::AFTER_TEST_PDO_FIXTURES_PATH; $path = $this->config->getParam($stage); $this->runFixturesUnderPath($path); $className = '\\' . substr($test, 0, strpos($test, ':')); @@ -76,7 +74,7 @@ public function executeAfterTest(string $test, float $time): void */ public function executeAfterLastTest(): void { - $path = $this->config->getParam(PDODatabaseExtensionConfig::AFTER_LAST_TEST_PDO_FIXTURES_PATH); + $path = $this->config->getParam(PDOFixtureConfig::AFTER_LAST_TEST_PDO_FIXTURES_PATH); $this->runFixturesUnderPath($path); } @@ -88,13 +86,16 @@ public function runFixturesUnderPath(string $path): void { try { $this->connection->PDO()->beginTransaction(); - $iterator = FileSystem::getFileListIteratorFromPathByExtension( + $iterator = $this->fileSystem->getFileListIteratorFromPathByExtension( $path, self::EXTENSION_SQL ); - FileSystem::runCallbackOnEachFileIteratorContents($iterator, function (string $contents) { - $this->connection->PDO()->exec($contents); - }); + $this->fileSystem->runCallbackOnEachFileIteratorContents( + $iterator, + function (string $contents) { + $this->connection->PDO()->exec($contents); + } + ); $this->connection->PDO()->commit(); } catch (TestingException $exception) { $this->connection->PDO()->rollBack(); diff --git a/src/WithAfterTestFixtureName.php b/src/WithAfterTestFixtureName.php index c8c40df..41274a9 100644 --- a/src/WithAfterTestFixtureName.php +++ b/src/WithAfterTestFixtureName.php @@ -6,6 +6,7 @@ interface WithAfterTestFixtureName { /** * PDODatabaseExtension will try to get the fixture name + * * @return string */ public static function getAfterTestFixtureName(): string; diff --git a/src/WithBeforeTestFixtureName.php b/src/WithBeforeTestFixtureName.php index 8d8e060..12fe2d5 100644 --- a/src/WithBeforeTestFixtureName.php +++ b/src/WithBeforeTestFixtureName.php @@ -6,6 +6,7 @@ interface WithBeforeTestFixtureName { /** * PDODatabaseExtension will try to get the fixture name + * * @return string */ public static function getBeforeTestFixtureName(): string; diff --git a/tests/integration/FileSystem/HandlerConfigurationTest.php b/tests/integration/FileSystem/HandlerConfigurationTest.php new file mode 100644 index 0000000..dd63413 --- /dev/null +++ b/tests/integration/FileSystem/HandlerConfigurationTest.php @@ -0,0 +1,32 @@ +assertInstanceOf(Handler::class, $sut); + } + + public function testConstructorOfHandlerWithCustomConfigurationName(): void + { + $this->expectException(TestingException::class); + new Handler('not-existing-file'); + } +} diff --git a/tests/integration/MariaDB/PDOIntegrationTest.php b/tests/integration/MariaDB/PDOIntegrationTest.php index 21e3b04..7f79175 100644 --- a/tests/integration/MariaDB/PDOIntegrationTest.php +++ b/tests/integration/MariaDB/PDOIntegrationTest.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\TestCase; /** - * @covers \IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtension + * @covers \IntegrationTesting\PHPUnit\Runner\Extension\PDOFixtureLoader * @uses \IntegrationTesting\Driver\PDOConnection */ final class PDOIntegrationTest extends TestCase implements WithBeforeTestFixtureName, WithAfterTestFixtureName @@ -53,4 +53,4 @@ public function testPersistentTableHasAtLeastOneRow(): void // this is the third test to run a beforeTest hook! $this->assertTrue($statement->rowCount() >= 1); } -} \ No newline at end of file +} diff --git a/tests/integration/MariaDB/PDOWithoutBeforeOrAfterTestFixturesTest.php b/tests/integration/MariaDB/PDOWithoutBeforeOrAfterTestFixturesTest.php index 7677ef8..4cca906 100644 --- a/tests/integration/MariaDB/PDOWithoutBeforeOrAfterTestFixturesTest.php +++ b/tests/integration/MariaDB/PDOWithoutBeforeOrAfterTestFixturesTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; /** - * @covers \IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtension + * @covers \IntegrationTesting\PHPUnit\Runner\Extension\PDOFixtureLoader * @uses \IntegrationTesting\Driver\PDOConnection */ final class PDOWithoutBeforeOrAfterTestFixturesTest extends TestCase @@ -35,4 +35,4 @@ public function testPersistentTableHasAtLeastOneRow(): void // this is the third test to run a beforeTest hook! $this->assertTrue($statement->rowCount() >= 1); } -} \ No newline at end of file +} diff --git a/tests/unit/PHPUnit/Runner/Extension/ConfigurationTest.php b/tests/unit/PHPUnit/Runner/Extension/ConfigurationTest.php new file mode 100644 index 0000000..cb47c06 --- /dev/null +++ b/tests/unit/PHPUnit/Runner/Extension/ConfigurationTest.php @@ -0,0 +1,20 @@ +expectException(TestingException::class); + new Configuration([]); + } +} diff --git a/tests/unit/PHPUnit/Runner/Extension/PDODatabaseExtensionTest.php b/tests/unit/PHPUnit/Runner/Extension/PDODatabaseExtensionTest.php index 6d10ad5..c34bc4d 100644 --- a/tests/unit/PHPUnit/Runner/Extension/PDODatabaseExtensionTest.php +++ b/tests/unit/PHPUnit/Runner/Extension/PDODatabaseExtensionTest.php @@ -2,12 +2,13 @@ namespace IntegrationTesting\PHPUnit\Runner\Extension; +use IntegrationTesting\Driver\FileSystem; use IntegrationTesting\Driver\PDOConnection; use PDO; use PHPUnit\Framework\TestCase; /** - * @covers \IntegrationTesting\PHPUnit\Runner\Extension\PDODatabaseExtension + * @covers \IntegrationTesting\PHPUnit\Runner\Extension\PDOFixtureLoader * @uses \IntegrationTesting\Driver\FileSystem */ final class PDODatabaseExtensionTest extends TestCase @@ -15,12 +16,12 @@ final class PDODatabaseExtensionTest extends TestCase public function testBeforeFirstTestBehaviour(): void { $PDO = $this->createMock(PDO::class); - $config = $this->createMock(PDODatabaseExtensionConfig::class); + $config = $this->createMock(PDOFixtureConfig::class); $connection = $this->createMock(PDOConnection::class); $config->expects($this->once()) ->method('getParam') - ->with(PDODatabaseExtensionConfig::BEFORE_FIRST_TEST_PDO_FIXTURES_PATH); + ->with(PDOFixtureConfig::BEFORE_FIRST_TEST_PDO_FIXTURES_PATH); $PDO->expects($this->once()) ->method('beginTransaction'); @@ -33,19 +34,21 @@ public function testBeforeFirstTestBehaviour(): void ->method('PDO') ->willReturn($PDO); - $sut = new PDODatabaseExtension($config, $connection); + $fileSystem = $this->createMock(FileSystem::class); + + $sut = new PDOFixtureLoader($fileSystem, $config, $connection); $sut->executeBeforeFirstTest(); } public function testBeforeTestBehaviour(): void { $PDO = $this->createMock(PDO::class); - $config = $this->createMock(PDODatabaseExtensionConfig::class); + $config = $this->createMock(PDOFixtureConfig::class); $connection = $this->createMock(PDOConnection::class); $config->expects($this->once()) ->method('getParam') - ->with(PDODatabaseExtensionConfig::BEFORE_TEST_PDO_FIXTURES_PATH); + ->with(PDOFixtureConfig::BEFORE_TEST_PDO_FIXTURES_PATH); $PDO->expects($this->once()) ->method('beginTransaction'); @@ -58,19 +61,21 @@ public function testBeforeTestBehaviour(): void ->method('PDO') ->willReturn($PDO); - $sut = new PDODatabaseExtension($config, $connection); + $fileSystem = $this->createMock(FileSystem::class); + + $sut = new PDOFixtureLoader($fileSystem, $config, $connection); $sut->executeBeforeTest(__METHOD__); } public function testAfterTestBehaviour(): void { $PDO = $this->createMock(PDO::class); - $config = $this->createMock(PDODatabaseExtensionConfig::class); + $config = $this->createMock(PDOFixtureConfig::class); $connection = $this->createMock(PDOConnection::class); $config->expects($this->once()) ->method('getParam') - ->with(PDODatabaseExtensionConfig::AFTER_TEST_PDO_FIXTURES_PATH); + ->with(PDOFixtureConfig::AFTER_TEST_PDO_FIXTURES_PATH); $PDO->expects($this->once()) ->method('beginTransaction'); @@ -83,19 +88,21 @@ public function testAfterTestBehaviour(): void ->method('PDO') ->willReturn($PDO); - $sut = new PDODatabaseExtension($config, $connection); + $fileSystem = $this->createMock(FileSystem::class); + + $sut = new PDOFixtureLoader($fileSystem, $config, $connection); $sut->executeAfterTest(__METHOD__, floatval(1)); } public function testAfterLastTestBehaviour(): void { $PDO = $this->createMock(PDO::class); - $config = $this->createMock(PDODatabaseExtensionConfig::class); + $config = $this->createMock(PDOFixtureConfig::class); $connection = $this->createMock(PDOConnection::class); $config->expects($this->once()) ->method('getParam') - ->with(PDODatabaseExtensionConfig::AFTER_LAST_TEST_PDO_FIXTURES_PATH); + ->with(PDOFixtureConfig::AFTER_LAST_TEST_PDO_FIXTURES_PATH); $PDO->expects($this->once()) ->method('beginTransaction'); @@ -108,7 +115,9 @@ public function testAfterLastTestBehaviour(): void ->method('PDO') ->willReturn($PDO); - $sut = new PDODatabaseExtension($config, $connection); + $fileSystem = $this->createMock(FileSystem::class); + + $sut = new PDOFixtureLoader($fileSystem, $config, $connection); $sut->executeAfterLastTest(); } }