From 78b03e8ec7a84f44177fdf372fc9a6e1d74278ef Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Mon, 13 May 2019 15:45:02 -0500 Subject: [PATCH 01/14] =?UTF-8?q?Add=20Static=20Analysis=20Limit=20PHPUnit?= =?UTF-8?q?=20versions=20to=206=20&=207=20Update=20cost=20style=20checks?= =?UTF-8?q?=20Add=20other=20code=20quality=20checks=20Remove=20Waffle.io?= =?UTF-8?q?=20badges=20(=F0=9F=98=A2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issues #48, #49, #50 --- .gitignore | 1 + .php_cs | 82 ++++++++--------------- .travis.yml | 9 ++- README.md | 2 - composer.json | 58 +++++++++++------ hooks/commit-msg.rb | 2 + hooks/pre-commit.sh | 20 ++++-- phpstan.neon.dist | 21 ++++++ src/Verify.php | 90 +------------------------- src/VerifyBase.php | 15 ++--- src/VerifyDirectory.php | 6 -- src/VerifyFile.php | 12 ---- src/function.php | 24 +++---- test/FunctionsTest.php | 14 ++-- test/UnitTestBase.php | 14 +--- test/VerifyDirectoryTest.php | 16 ++--- test/VerifyFileTest.php | 25 ++++--- test/VerifyTest.php | 122 ++++++----------------------------- 18 files changed, 176 insertions(+), 357 deletions(-) create mode 100644 phpstan.neon.dist diff --git a/.gitignore b/.gitignore index 5adde54..54c07a5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ vendor composer.phar composer.lock .php_cs.cache +phpstan.neon diff --git a/.php_cs b/.php_cs index ce21371..10da338 100644 --- a/.php_cs +++ b/.php_cs @@ -2,68 +2,40 @@ $finder = PhpCsFixer\Finder::create() ->in('src') - ->in('test'); + ->in('test') + ->notName('function.php'); // no_superfluous_php_doc_tags does not play well with function.php + // basically treat rule & file as mutually exclusive; either have one or the other return PhpCsFixer\Config::create() ->setRules([ - '@Symfony' => true, - '@Symfony:risky' => true, - '@PHP70Migration' => true, - '@PHP70Migration:risky' => true, - '@PHPUnit60Migration:risky' => true, - 'align_multiline_comment' => ['comment_type' => 'all_multiline'], - 'array_indentation' => true, - 'array_syntax' => ['syntax' => 'short'], - 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], - 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], - 'combine_consecutive_issets' => true, - 'combine_consecutive_unsets' => true, - 'comment_to_phpdoc' => true, - 'compact_nullable_typehint' => true, + '@PHP70Migration' => true, + '@PHP70Migration:risky' => true, + '@PHPUnit60Migration:risky' => true, + '@PhpCsFixer' => true, + '@PhpCsFixer:risky' => true, + 'align_multiline_comment' => ['comment_type' => 'all_multiline'], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], + 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], + 'class_definition' => [ + 'single_item_single_line' => true, + 'multi_line_extends_each_single_line' => true, + ], 'concat_space' => ['spacing' => 'one'], 'date_time_immutable' => true, 'escape_implicit_backslashes' => ['single_quoted' => true], - 'explicit_indirect_variable' => true, - 'explicit_string_variable' => true, - 'fully_qualified_strict_types' => true, - 'heredoc_to_nowdoc' => true, 'linebreak_after_opening_tag' => true, 'list_syntax' => true, - 'method_chaining_indentation' => true, - 'multiline_comment_opening_closing' => true, - 'multiline_whitespace_before_semicolons' => true, - 'native_function_invocation' => true, - 'no_alternative_syntax' => true, - 'no_extra_blank_lines' => [ - 'tokens' => [ - 'case', - 'continue', - 'curly_brace_block', - 'default', - 'extra', - 'parenthesis_brace_block', - 'return', - 'square_brace_block', - 'switch', - 'throw', - 'use', - ], - ], - 'no_null_property_initialization' => true, - 'no_php4_constructor' => true, - 'no_superfluous_elseif' => true, - 'no_unreachable_default_argument_value' => true, - 'no_useless_else' => true, - 'no_useless_return' => true, - 'ordered_class_elements' => ['sortAlgorithm' => 'alpha'], - 'ordered_imports' => ['importsOrder' => ['const', 'class', 'function']], - 'php_unit_strict' => true, - 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], - 'phpdoc_order' => true, - 'phpdoc_types_order' => ['sort_algorithm' => 'none', 'null_adjustment' => 'always_last'], - 'psr0' => true, - 'simplified_null_return' => true, - 'single_line_comment_style' => ['comment_types' => ['asterisk', 'hash']], - 'yoda_style' => false, + 'mb_str_functions' => true, + 'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'], + 'no_php4_constructor' => true, + 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], + 'ordered_class_elements' => ['sortAlgorithm' => 'alpha'], + 'phpdoc_types_order' => ['sort_algorithm' => 'none', 'null_adjustment' => 'always_last'], + 'php_unit_test_case_static_method_calls' => ['call_type' => 'this'], + 'php_unit_test_class_requires_covers' => false, + 'psr0' => ['dir' => 'src'], + 'simplified_null_return' => true, + 'yoda_style' => false, ]) ->setFinder($finder); diff --git a/.travis.yml b/.travis.yml index da6afe4..bbf90ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ php: - 7 - 7.1 - 7.2 + - 7.3 env: - PHPUNIT_VERSION=6.0 @@ -13,6 +14,9 @@ matrix: exclude: - php: 7 env: PHPUNIT_VERSION=7.0 + exclude: + - php: 7.3 + env: PHPUNIT_VERSION=6.0 sudo: false @@ -21,8 +25,9 @@ install: - travis_retry composer install --dev --no-interaction --prefer-dist script: - - composer cs-check - - composer test-coverage + - composer cs:check + - composer test:static + - composer test:coverage after_success: - bash <(curl -s https://codecov.io/bash) diff --git a/README.md b/README.md index 5c30d72..59fc0e5 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ BDD Assertions for PHPUnit and Codeception This is very tiny wrapper for PHPUnit assertions, that are aimed to make tests a bit more readable. With BDD assertions influenced by Chai, Jasmine, and RSpec your assertions would be a bit closer to natural language. -[![Ready Stories](https://badge.waffle.io/bbatsche/Verify.png?label=ready&title=Ready)](https://waffle.io/bbatsche/Verify) -[![Stories In Progress](https://badge.waffle.io/bbatsche/Verify.png?label=in+progress&title=In+Progress)](https://waffle.io/bbatsche/Verify) [![Latest Stable Version](https://img.shields.io/packagist/v/bebat/verify.svg?style=plastic)](https://packagist.org/packages/bebat/verify) [![Total Downloads](https://img.shields.io/packagist/dt/bebat/verify.svg?style=plastic)](https://packagist.org/packages/bebat/verify) [![License](https://img.shields.io/packagist/l/bebat/verify.svg?style=plastic)](https://packagist.org/packages/bebat/verify) diff --git a/composer.json b/composer.json index fee9c47..98a1fd9 100644 --- a/composer.json +++ b/composer.json @@ -2,11 +2,18 @@ "name": "bebat/verify", "description": "BDD assertion library for PHPUnit", "keywords": [ - "bdd", "assertions", "unit testing", "unit test", "phpunit", "codeception", "unit", "test", "testing" + "bdd", + "assertions", + "unit testing", + "unit test", + "phpunit", + "codeception", + "unit", + "test", + "testing" ], "homepage": "https://github.com/bbatsche/Verify", "license": "MIT", - "minimum-stability": "stable", "authors": [ { "name": "Michael Bodnarchuk", @@ -17,40 +24,53 @@ "homepage": "http://github.com/bbatsche" } ], - "support": { - "issues": "https://waffle.io/bbatsche/verify", - "docs": "http://bbatsche.github.io/Verify/" - }, "require": { - "php": ">=7.0", - "phpunit/phpunit": ">=6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.12", - "mockery/mockery": "^1.0" + "php": "^7.0", + "phpunit/phpunit": "^6.0 || ^7.0" }, "replace": { "codeception/verify": "*" }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.15", + "localheinz/composer-normalize": "^1.1", + "mockery/mockery": "^1.0", + "maglnet/composer-require-checker": "^2.0", + "phpstan/phpstan": "^0.11.6", + "phpstan/phpstan-mockery": "^0.11.0", + "phpstan/phpstan-phpunit": "^0.11.0" + }, "suggest": { "codeception/specify": "Highly readable test code blocks for PHPUnit and Codeception" }, "autoload": { - "files": ["src/function.php"], "psr-4": { "BeBat\\Verify\\": "src" - } + }, + "files": [ + "src/function.php" + ] }, "autoload-dev": { "psr-4": { "BeBat\\Verify\\Test\\": "test" } }, + "minimum-stability": "stable", "scripts": { - "cs-check": "php-cs-fixer fix -v --allow-risky=yes --ansi --dry-run --diff", - "cs-check-file": "php-cs-fixer fix -v --allow-risky=yes --ansi --dry-run --diff --path-mode=intersection", - "cs-fix": "php-cs-fixer fix -v --allow-risky=yes --ansi", - "test": "phpunit --colors=always", - "test-coverage": "phpunit --coverage-clover=coverage.xml" + "cs:check": "php-cs-fixer fix -v --allow-risky=yes --ansi --dry-run --diff", + "cs:fix": "php-cs-fixer fix -v --allow-risky=yes --ansi", + "test:all": [ + "@composer cs:check", + "@composer test:static", + "@composer test:unit" + ], + "test:coverage": "phpunit --coverage-clover=coverage.xml", + "test:static": "phpstan analyze --ansi --level 7 src test", + "test:unit": "phpunit --colors=always" + }, + "support": { + "issues": "https://github.com/bbatsche/Verify/issues", + "docs": "https://github.com/bbatsche/Verify/blob/master/README.md" } } diff --git a/hooks/commit-msg.rb b/hooks/commit-msg.rb index af5b73b..e11c6f6 100755 --- a/hooks/commit-msg.rb +++ b/hooks/commit-msg.rb @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +Encoding.default_external = Encoding::UTF_8 +Encoding.default_internal = Encoding::UTF_8 message_file = ARGV[0] message = File.read(message_file) diff --git a/hooks/pre-commit.sh b/hooks/pre-commit.sh index 08d4fc8..d586411 100755 --- a/hooks/pre-commit.sh +++ b/hooks/pre-commit.sh @@ -10,17 +10,27 @@ git diff --cached --name-only | while read FILE; do exit 1 fi - composer cs-check-file "$FILE" 2> /dev/null - if [ $? -ne 0 ]; then - echo -e "\033[1;31m\tAborting Commit! Files do not follow coding standards.\033[0m" >&2 - exit 1 + if ! [[ "$FILE" =~ src/function.php$ ]]; then + composer cs:check "$FILE" 2> /dev/null + if [ $? -ne 0 ]; then + echo -e "\033[1;31m\tAborting Commit! Files do not follow coding standards.\033[0m" >&2 + exit 1 + fi fi fi fi done || exit $? if [ $? -eq 0 ]; then - composer test 2> /dev/null + composer test:static 2> /dev/null + if [ $? -ne 0 ]; then + echo -e "\033[1;31m\tAborting Commit! Static analyzer failed.\033[0m" >&2 + exit 1 + fi +fi + +if [ $? -eq 0 ]; then + composer test:unit 2> /dev/null if [ $? -ne 0 ]; then echo -e "\033[1;31m\tAborting Commit! There are broken unit tests.\033[0m" >&2 exit 1 diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..2949e03 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,21 @@ +parameters: + ignoreErrors: + - + message: '/PHPDoc tag @param references unknown parameter: \$actual/' + path: %currentWorkingDirectory%/src/function.php + - + message: '/PHPDoc tag @param references unknown parameter: \$description/' + path: %currentWorkingDirectory%/src/function.php + - + message: '/Trying to invoke string but it might not be a callable/' + path: %currentWorkingDirectory%/test/FunctionsTest.php + - + message: '/Property [a-zA-Z\\:$]+ \([a-zA-Z\\&|]+\) does not accept alias:[a-zA-Z\\&|]+/' + path: %currentWorkingDirectory%/test/UnitTestBase.php + - + message: '/Call to an undefined method BeBat\\Verify\\Verify::[a-z_]+_conjunction\(\)/' + path: %currentWorkingDirectory%/test/VerifyTest.php +includes: + - vendor/phpstan/phpstan-mockery/extension.neon + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/src/Verify.php b/src/Verify.php index d59f11f..fab43e4 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -71,8 +71,6 @@ class Verify extends VerifyBase * Sets the attribute name to check. * * @param string $attr Name of attribute - * - * @return self */ public function __get(string $attr): self { @@ -83,8 +81,6 @@ public function __get(string $attr): self * Assert SUT does or does not have a given class attribute. * * @param string $attribute Name of attribute expected to be in SUT - * - * @return self */ public function attribute(string $attribute): self { @@ -113,8 +109,6 @@ public function attribute(string $attribute): self * Sets the attribute name to check. * * @param string $attr Name of attribute - * - * @return self */ public function attributeNamed(string $attr): self { @@ -127,8 +121,6 @@ public function attributeNamed(string $attr): self * Assert SUT does or does not contain a given value. * * @param mixed $needle Value expected to be in SUT - * - * @return self */ public function contain($needle): self { @@ -187,8 +179,6 @@ public function contain($needle): self * Assert SUT does or does not contain only instances of a given class or internal PHP type. * * @param string $type Class name or internal PHP type expected to be in SUT - * - * @return self */ public function containOnly(string $type): self { @@ -249,8 +239,6 @@ public function count(int $count) /** * Assert SUT is or is not empty. - * - * @return self */ public function empty(): self { @@ -279,8 +267,6 @@ public function empty(): self * Assert SUT does or does not end with a given value. * * @param string $suffix Value SUT is expected to end with - * - * @return self */ public function endWith(string $suffix): self { @@ -301,8 +287,6 @@ public function endWith(string $suffix): self * Assert SUT does or does not equal a given value. * * @param mixed $expected Expected value for SUT - * - * @return self */ public function equalTo($expected): self { @@ -365,8 +349,6 @@ public function equalTo($expected): self * Assert SUT does or does not equal the contents of a given file. * * @param string $file Name of file SUT is expected to match - * - * @return self */ public function equalToFile(string $file): self { @@ -389,8 +371,6 @@ public function equalToFile(string $file): self * Assert SUT's JSON value is or is not the same as JSON in a given file. * * @param string $file Name of file with JSON expected to match SUT - * - * @return self */ public function equalToJsonFile(string $file): self { @@ -411,8 +391,6 @@ public function equalToJsonFile(string $file): self * Assert SUT's JSON value does or does not equal a given JSON value. * * @param string $string JSON value SUT is expected to be equal to - * - * @return self */ public function equalToJsonString(string $string): self { @@ -433,8 +411,6 @@ public function equalToJsonString(string $string): self * Assert SUT's XML value is or is not equal to the XML stored in a given file. * * @param string $file Name of XML file SUT is expected to match - * - * @return self */ public function equalToXmlFile(string $file): self { @@ -455,8 +431,6 @@ public function equalToXmlFile(string $file): self * Assert SUT's XML value is or is not the same as a given string of XML. * * @param string $xmlString XML data SUT is expected to equal - * - * @return self */ public function equalToXmlString(string $xmlString): self { @@ -477,8 +451,6 @@ public function equalToXmlString(string $xmlString): self * Assert SUT has the same XML structur as a given DOMElement. * * @param \DOMElement $xml Structure SUT is expected to match - * - * @return self */ public function equalToXmlStructure(\DOMElement $xml): self { @@ -497,8 +469,6 @@ public function equalToXmlStructure(\DOMElement $xml): self /** * Assert SUT is or is not false. - * - * @return self */ public function false(): self { @@ -517,8 +487,6 @@ public function false(): self /** * Assert SUT is or is not finite. - * - * @return self */ public function finite(): self { @@ -539,8 +507,6 @@ public function finite(): self * Assert SUT is or is not greater than or equal to a given value. * * @param int|float $expected Value SUT is expected to be greater than or equal to - * - * @return self */ public function greaterOrEqualTo($expected): self { @@ -569,8 +535,6 @@ public function greaterOrEqualTo($expected): self * Assert SUT is or is not greater than a given value. * * @param int|float $expected Value SUT is expected to be greater than - * - * @return self */ public function greaterThan($expected): self { @@ -597,8 +561,6 @@ public function greaterThan($expected): self /** * Assert SUT is or is not infinite. - * - * @return self */ public function infinite(): self { @@ -619,8 +581,6 @@ public function infinite(): self * Assert SUT is or is not an instance of a given class. * * @param string $class Name of class SUT is expected to be an instance of - * - * @return self */ public function instanceOf(string $class): self { @@ -649,8 +609,6 @@ public function instanceOf(string $class): self * Assert SUT is or is not a given PHP data type. * * @param string $type Data type SUT is expected to be - * - * @return self */ public function internalType(string $type): self { @@ -677,8 +635,6 @@ public function internalType(string $type): self /** * Assert SUT is or is not a string containing valid JSON data. - * - * @return self */ public function json(): self { @@ -699,8 +655,6 @@ public function json(): self * Assert SUT does or does not have a given key. * * @param int|string $key Key expected to be in SUT - * - * @return self */ public function key($key): self { @@ -721,8 +675,6 @@ public function key($key): self * Assert SUT is or is not less than or equal to a given value. * * @param int|float $expected Value SUT is expected to be less than or equal to - * - * @return self */ public function lessOrEqualTo($expected): self { @@ -751,8 +703,6 @@ public function lessOrEqualTo($expected): self * Assert SUT is or is not less than a given value. * * @param int|float $expected Value SUT is expected to be less than - * - * @return self */ public function lessThan($expected): self { @@ -783,8 +733,6 @@ public function lessThan($expected): self * @param string $format Format code(s) SUT is expected to match * * @see https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertStringMatchesFormat - * - * @return self */ public function matchFormat(string $format): self { @@ -807,8 +755,6 @@ public function matchFormat(string $format): self * @param string $formatFile Filename to read format code(s) from * * @see https://phpunit.de/manual/current/en/appendixes.assertions.html#appendixes.assertions.assertStringMatchesFormat - * - * @return self */ public function matchFormatFile(string $formatFile): self { @@ -829,8 +775,6 @@ public function matchFormatFile(string $formatFile): self * Assert SUT does or does not match a given regular expression. * * @param string $expression Regular expression SUT is expected to match - * - * @return self */ public function matchRegExp(string $expression): self { @@ -849,8 +793,6 @@ public function matchRegExp(string $expression): self /** * Assert SUT is NaN. - * - * @return self */ public function nan(): self { @@ -869,8 +811,6 @@ public function nan(): self /** * Assert SUT is or is not null. - * - * @return self */ public function null(): self { @@ -891,8 +831,6 @@ public function null(): self * Assert SUT does or does not have both the same value and type as a given value. * * @param mixed $expected Value SUT is exptected to match - * - * @return self */ public function sameAs($expected): self { @@ -920,9 +858,7 @@ public function sameAs($expected): self /** * Assert SUT does or does not have the same number of elements as given array/Countable/Traversable object. * - * @param array|Countable|Traversable $expected Value SUT is expected to be the same size as - * - * @return self + * @param array|\Countable|\Traversable $expected Value SUT is expected to be the same size as */ public function sameSizeAs($expected): self { @@ -943,8 +879,6 @@ public function sameSizeAs($expected): self * Assert SUT does or does not start with a given value. * * @param string $prefix Value SUT is expected to start with - * - * @return self */ public function startWith(string $prefix): self { @@ -965,8 +899,6 @@ public function startWith(string $prefix): self * Assert SUT does or does not have a given static attribute. * * @param string $attribute Name of attribute expected to be in SUT - * - * @return self */ public function staticAttribute(string $attribute): self { @@ -987,8 +919,6 @@ public function staticAttribute(string $attribute): self * Assert SUT contains a given subset of values. * * @param array $array Subset expected to be in SUT - * - * @return self */ public function subset($array): self { @@ -1027,8 +957,6 @@ public function true(): self /** * Check element attributes when comparing SUT to an XML document. - * - * @return self */ public function withAttributes(): self { @@ -1039,8 +967,6 @@ public function withAttributes(): self /** * Compare objects within SUT based on their identity, not just value. - * - * @return self */ public function withIdentity(): self { @@ -1053,8 +979,6 @@ public function withIdentity(): self * Specify an acceptable range when checking a floating point SUT's equality. * * @param float $delta range within which floating point values will be considered "equal" - * - * @return self */ public function within(float $delta): self { @@ -1065,8 +989,6 @@ public function within(float $delta): self /** * Include element ordering when comparing SUT to an array. - * - * @return self */ public function withOrder(): self { @@ -1077,8 +999,6 @@ public function withOrder(): self /** * Ignore element attributes when comparing SUT to an XML document. - * - * @return self */ public function withoutAttributes(): self { @@ -1089,8 +1009,6 @@ public function withoutAttributes(): self /** * Compare objects within SUT based solely on their value. - * - * @return self */ public function withoutIdentity(): self { @@ -1101,8 +1019,6 @@ public function withoutIdentity(): self /** * Ignore element ordering when comparing SUT to an array. - * - * @return self */ public function withoutOrder(): self { @@ -1113,8 +1029,6 @@ public function withoutOrder(): self /** * Ignore type when comparing elements in SUT. - * - * @return self */ public function withoutType(): self { @@ -1125,8 +1039,6 @@ public function withoutType(): self /** * Compare both type and value for elements in SUT. - * - * @return self */ public function withType(): self { diff --git a/src/VerifyBase.php b/src/VerifyBase.php index 0e277c4..4c4b2c3 100644 --- a/src/VerifyBase.php +++ b/src/VerifyBase.php @@ -74,26 +74,23 @@ public function __construct($actual, $description = '') /** * Set positive or negative modifier and chain method calls along. * - * @param string $method - * @param array $arguments - * - * @return self + * @return static */ public function __call(string $method, array $arguments = []): self { - if (\in_array($method, self::$positiveConjunctions)) { + if (\in_array($method, self::$positiveConjunctions, true)) { $this->modifierCondition = true; return $this; } - if (\in_array($method, self::$negativeConjunctions)) { + if (\in_array($method, self::$negativeConjunctions, true)) { $this->modifierCondition = false; return $this; } - if (\in_array($method, self::$neutralConjunctions)) { + if (\in_array($method, self::$neutralConjunctions, true)) { return $this; } @@ -103,7 +100,7 @@ public function __call(string $method, array $arguments = []): self /** * Turn on case sensitivity when checking SUT. * - * @return self + * @return static */ public function withCase(): self { @@ -115,7 +112,7 @@ public function withCase(): self /** * Turn off case sensitivity when checking SUT. * - * @return self + * @return static */ public function withoutCase(): self { diff --git a/src/VerifyDirectory.php b/src/VerifyDirectory.php index 3ad265f..323c934 100644 --- a/src/VerifyDirectory.php +++ b/src/VerifyDirectory.php @@ -15,8 +15,6 @@ class VerifyDirectory extends VerifyBase { /** * Assert SUT does or does not exist in the filesystem. - * - * @return self */ public function exist(): self { @@ -35,8 +33,6 @@ public function exist(): self /** * Assert SUT is or is not readable. - * - * @return self */ public function readable(): self { @@ -55,8 +51,6 @@ public function readable(): self /** * Assert SUT is or is not writable. - * - * @return self */ public function writable(): self { diff --git a/src/VerifyFile.php b/src/VerifyFile.php index b75b193..acef89f 100644 --- a/src/VerifyFile.php +++ b/src/VerifyFile.php @@ -17,8 +17,6 @@ class VerifyFile extends VerifyBase * Assert contents of SUT are or are not equal to another given file's contents. * * @param string $expected Name of file SUT is expected to be equal to - * - * @return self */ public function equalTo(string $expected): self { @@ -41,8 +39,6 @@ public function equalTo(string $expected): self * Assert SUT's contents as JSON value are or are not equal to the JSON contents of a given file. * * @param string $file JSON file SUT is expected to be the same as - * - * @return self */ public function equalToJsonFile(string $file): self { @@ -63,8 +59,6 @@ public function equalToJsonFile(string $file): self * Assert SUT's contents as XML are or are not the same as the XML in a given file. * * @param string $file XML file SUT is expected to be the same as - * - * @return self */ public function equalToXmlFile(string $file): self { @@ -83,8 +77,6 @@ public function equalToXmlFile(string $file): self /** * Assert SUT does or does not exist in the filesystem. - * - * @return self */ public function exist(): self { @@ -103,8 +95,6 @@ public function exist(): self /** * Assert SUT is or is not readable. - * - * @return self */ public function readable(): self { @@ -123,8 +113,6 @@ public function readable(): self /** * Assert SUT is or is not writable. - * - * @return self */ public function writable(): self { diff --git a/src/function.php b/src/function.php index 37bc49f..3c00549 100644 --- a/src/function.php +++ b/src/function.php @@ -16,13 +16,13 @@ * * @return \BeBat\Verify\Verify */ -function verify() +function verify(...$args) { - switch (\func_num_args()) { + switch (\count($args)) { case 1: - return new Verify(\func_get_arg(0)); + return new Verify($args[0]); case 2: - return new Verify(\func_get_arg(1), \func_get_arg(0)); + return new Verify($args[1], $args[0]); default: throw new \BadFunctionCallException('verify() must be called with exactly 1 or 2 arguments.'); } @@ -40,13 +40,13 @@ function verify() * * @return \BeBat\Verify\VerifyFile */ -function verify_file() +function verify_file(...$args) { - switch (\func_num_args()) { + switch (\count($args)) { case 1: - return new VerifyFile(\func_get_arg(0)); + return new VerifyFile($args[0]); case 2: - return new VerifyFile(\func_get_arg(1), \func_get_arg(0)); + return new VerifyFile($args[1], $args[0]); default: throw new \BadFunctionCallException('verify_file() must be called with exactly 1 or 2 arguments.'); } @@ -64,13 +64,13 @@ function verify_file() * * @return \BeBat\Verify\VerifyDirectory */ -function verify_directory() +function verify_directory(...$args) { - switch (\func_num_args()) { + switch (\count($args)) { case 1: - return new VerifyDirectory(\func_get_arg(0)); + return new VerifyDirectory($args[0]); case 2: - return new VerifyDirectory(\func_get_arg(1), \func_get_arg(0)); + return new VerifyDirectory($args[1], $args[0]); default: throw new \BadFunctionCallException('verify_directory() must be called with exactly 1 or 2 arguments.'); } diff --git a/test/FunctionsTest.php b/test/FunctionsTest.php index f0b824f..858f8d2 100644 --- a/test/FunctionsTest.php +++ b/test/FunctionsTest.php @@ -9,14 +9,14 @@ use BeBat\Verify\VerifyFile; use PHPUnit\Framework\TestCase; -class FunctionsTest extends TestCase +/** + * @internal + */ +final class FunctionsTest extends TestCase { /** * Test verify*() methods' default behavior. * - * @param string $functionName - * @param string $className - * * @dataProvider verifyFunctions */ public function testFunction(string $functionName, string $className) @@ -36,8 +36,6 @@ public function testFunction(string $functionName, string $className) /** * Test exception thrown with zero arguments. * - * @param string $functionName - * * @dataProvider verifyFunctions */ public function testFunctionNoArguments(string $functionName) @@ -49,8 +47,6 @@ public function testFunctionNoArguments(string $functionName) /** * Test exception thrown with too many arguments. * - * @param string $functionName - * * @dataProvider verifyFunctions */ public function testFunctionTooManyArguments(string $functionName) @@ -61,8 +57,6 @@ public function testFunctionTooManyArguments(string $functionName) /** * All verify functions and their corresponding classes. - * - * @return array */ public function verifyFunctions(): array { diff --git a/test/UnitTestBase.php b/test/UnitTestBase.php index e217be9..594e6cb 100644 --- a/test/UnitTestBase.php +++ b/test/UnitTestBase.php @@ -24,7 +24,7 @@ abstract class UnitTestBase extends TestCase /** * Assertion mock. * - * @var Assert|\Mockery\MockInterface + * @var Assert&\Mockery\MockInterface */ protected $mockAssert; @@ -43,8 +43,7 @@ protected function setUp() /** * Test MissingConditionException is thrown for all methods. * - * @param string $verifyMethod - * @param mixed $value + * @param mixed $value * * @dataProvider allMethods */ @@ -58,10 +57,6 @@ public function testMissingConditionException(string $verifyMethod, $value = 'du /** * Test VerifyFile methods that don't take any value. * - * @param bool $modifierCondition - * @param string $verifyMethod - * @param string $assertMethod - * * @dataProvider noParamMethods */ public function testNoParamMethods(bool $modifierCondition, string $verifyMethod, string $assertMethod) @@ -78,10 +73,7 @@ public function testNoParamMethods(bool $modifierCondition, string $verifyMethod /** * Test verify methods that take in a single value for comparison. * - * @param bool $modifierCondition - * @param string $verifyMethod - * @param string $assertMethod - * @param mixed $expectedValue + * @param mixed $expectedValue * * @dataProvider singleParamMethods */ diff --git a/test/VerifyDirectoryTest.php b/test/VerifyDirectoryTest.php index 1a8701b..ae3ceca 100644 --- a/test/VerifyDirectoryTest.php +++ b/test/VerifyDirectoryTest.php @@ -6,11 +6,14 @@ use BeBat\Verify\VerifyDirectory; -class VerifyDirectoryTest extends UnitTestBase +/** + * @internal + */ +final class VerifyDirectoryTest extends UnitTestBase { protected $defaultActualValue = 'directory under test'; - public function setUp() + protected function setUp() { $this->subject = new VerifyDirectory($this->defaultActualValue, 'some message'); @@ -19,8 +22,6 @@ public function setUp() /** * All VerifyDirectory methods. - * - * @return array */ public function allMethods(): array { @@ -33,8 +34,6 @@ public function allMethods(): array /** * All VerifyDirectory methods and their PHPUnit assertions that do not take a value for comparison. - * - * @return array */ public function noParamMethods(): array { @@ -51,10 +50,7 @@ public function noParamMethods(): array /** * VerifyDirectory doesn't have any comparison methods so override parent test with a no-op. * - * @param bool $modifierCondition - * @param string $verifyMethod - * @param string $assertMethod - * @param mixed $expectedValue + * @param mixed $expectedValue * * @doesNotPerformAssertions */ diff --git a/test/VerifyFileTest.php b/test/VerifyFileTest.php index e4f42a7..f746058 100644 --- a/test/VerifyFileTest.php +++ b/test/VerifyFileTest.php @@ -7,11 +7,21 @@ use BeBat\Verify\VerifyFile; use Mockery; -class VerifyFileTest extends UnitTestBase +/** + * @internal + */ +final class VerifyFileTest extends UnitTestBase { protected $defaultActualValue = 'file under test'; - public function setUp() + /** + * VerifyFile class. + * + * @var \BeBat\Verify\VerifyFile + */ + protected $subject; + + protected function setUp() { $this->subject = new VerifyFile($this->defaultActualValue, 'some message'); @@ -20,8 +30,6 @@ public function setUp() /** * All VerifyFile methods. - * - * @return array */ public function allMethods(): array { @@ -37,8 +45,6 @@ public function allMethods(): array /** * PHPUnit assertions used by VerifyFile::equalTo(). - * - * @return array */ public function equalToMethods(): array { @@ -50,8 +56,6 @@ public function equalToMethods(): array /** * All VerifyFile methods and their PHPUnit assertions that do not take a value for comparison. - * - * @return array */ public function noParamMethods(): array { @@ -67,8 +71,6 @@ public function noParamMethods(): array /** * All VerifyFile methods and their PHPUnit assertions that take in a single parameter. - * - * @return array */ public function singleParamMethods(): array { @@ -83,9 +85,6 @@ public function singleParamMethods(): array /** * Test VerifyFile::equalTo(). * - * @param bool $modifierConition - * @param string $assertMethod - * * @dataProvider equalToMethods */ public function testEqualTo(bool $modifierConition, string $assertMethod) diff --git a/test/VerifyTest.php b/test/VerifyTest.php index d33372b..3f9c374 100644 --- a/test/VerifyTest.php +++ b/test/VerifyTest.php @@ -8,11 +8,21 @@ use DOMElement; use Mockery; -class VerifyTest extends UnitTestBase +/** + * @internal + */ +final class VerifyTest extends UnitTestBase { protected $defaultActualValue = 'actual value'; - public function setUp() + /** + * Verify class. + * + * @var \BeBat\Verify\Verify + */ + protected $subject; + + protected function setUp() { $this->subject = new Verify($this->defaultActualValue, 'some message'); @@ -21,8 +31,6 @@ public function setUp() /** * All possible verify methods. - * - * @return array */ public function allMethods(): array { @@ -67,8 +75,6 @@ public function allMethods(): array /** * Sample data for testing attribute() method. - * - * @return array */ public function attributeAssertMethods(): array { @@ -82,8 +88,6 @@ public function attributeAssertMethods(): array /** * Assert methods used by contain() for attributes. - * - * @return array */ public function attributeContainAssertMethods(): array { @@ -95,8 +99,6 @@ public function attributeContainAssertMethods(): array /** * Assert methods used by containOnly() for attributes. - * - * @return array */ public function attributeContainOnlyAssertMethods(): array { @@ -108,8 +110,6 @@ public function attributeContainOnlyAssertMethods(): array /** * Assert methods used by equalTo() for attributes. - * - * @return array */ public function attributeEqualToAssertMethods(): array { @@ -121,8 +121,6 @@ public function attributeEqualToAssertMethods(): array /** * Verify methods and their PHPUnit assertions for object attributes. - * - * @return array */ public function attributeMethods(): array { @@ -148,8 +146,6 @@ public function attributeMethods(): array /** * Assert methods used by contain(). - * - * @return array */ public function containAssertMethods(): array { @@ -161,8 +157,6 @@ public function containAssertMethods(): array /** * Assert methods used by containOnly(). - * - * @return array */ public function containOnlyAssertMethods(): array { @@ -174,8 +168,6 @@ public function containOnlyAssertMethods(): array /** * Assert methods used by equalTo(). - * - * @return array */ public function equalToAssertMethods(): array { @@ -187,8 +179,6 @@ public function equalToAssertMethods(): array /** * Assert methods used by equalToFile(). - * - * @return array */ public function equalToFileAssertMethods(): array { @@ -200,8 +190,6 @@ public function equalToFileAssertMethods(): array /** * Verify methods that cannot be used with a negative condition. - * - * @return array */ public function methodsWithoutNegativeCondition(): array { @@ -215,8 +203,6 @@ public function methodsWithoutNegativeCondition(): array /** * Verify methods and their PHPUnit assertions that don't take any comparison value. - * - * @return array */ public function noParamMethods(): array { @@ -240,8 +226,6 @@ public function noParamMethods(): array /** * Verify methods and their PHPUNit assertions that take a comparison value. - * - * @return array */ public function singleParamMethods(): array { @@ -292,9 +276,6 @@ public function singleParamMethods(): array /** * Test Verify::contain() with & without case sensitivity for attributes. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeContainAssertMethods */ public function testAttribueContainCaseSensitive(bool $modifierCondition, string $assertMethod) @@ -337,9 +318,6 @@ public function testAttribueContainCaseSensitive(bool $modifierCondition, string /** * Test Verify::contain() with & without data type for attributes. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeContainAssertMethods */ public function testAttribueContainDataType(bool $modifierCondition, string $assertMethod) @@ -382,9 +360,6 @@ public function testAttribueContainDataType(bool $modifierCondition, string $ass /** * Test Verify::contain() with & without object identity for attributes. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeContainAssertMethods */ public function testAttribueContainObjectIdentity(bool $modifierCondition, string $assertMethod) @@ -427,9 +402,7 @@ public function testAttribueContainObjectIdentity(bool $modifierCondition, strin /** * Test Verify::attribute(). * - * @param bool $modifierCondition * @param string|object $actualValue - * @param string $assertMethod * * @dataProvider attributeAssertMethods */ @@ -449,10 +422,7 @@ public function testAttribute(bool $modifierCondition, $actualValue, string $ass /** * Test negative assertions for object attributes. * - * @param bool $modifierCondition - * @param string $verifyMethod - * @param string $assertMethod - * @param mixed $expectedValue + * @param mixed $expectedValue * * @dataProvider attributeMethods */ @@ -476,9 +446,6 @@ public function testAttributeAssertions( /** * Test Verify::contain() basic case for attributes. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeContainAssertMethods */ public function testAttributeContain(bool $modifierCondition, string $assertMethod) @@ -496,9 +463,6 @@ public function testAttributeContain(bool $modifierCondition, string $assertMeth /** * Test Verify::containOnly() for object attributes. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeContainOnlyAssertMethods */ public function testAttributeContainOnly(bool $modifierCondition, string $assertMethod) @@ -516,9 +480,6 @@ public function testAttributeContainOnly(bool $modifierCondition, string $assert /** * Test Verify::equalTo() for attributes. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeEqualToAssertMethods */ public function testAttributeEqualTo(bool $modifierCondition, string $assertMethod) @@ -544,9 +505,6 @@ public function testAttributeEqualTo(bool $modifierCondition, string $assertMeth /** * Test Verify::equalTo() for attributes with or without case sensitivity. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeEqualToAssertMethods */ public function testAttributeEqualToCaseSensitive(bool $modifierCondition, string $assertMethod) @@ -591,9 +549,6 @@ public function testAttributeEqualToCaseSensitive(bool $modifierCondition, strin /** * Test Verify::equalTo() for attributes with some float delta. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeEqualToAssertMethods */ public function testAttributeEqualToFloatDelta(bool $modifierCondition, string $assertMethod) @@ -619,9 +574,6 @@ public function testAttributeEqualToFloatDelta(bool $modifierCondition, string $ /** * Test Verify::equalTo() for attributes with or without order. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider attributeEqualToAssertMethods */ public function testAttributeEqualToOrder(bool $modifierCondition, string $assertMethod) @@ -695,9 +647,6 @@ public function testConjunctions() /** * Test Verify::contain() basic case. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider containAssertMethods */ public function testContain(bool $modifierCondition, string $assertMethod) @@ -714,9 +663,6 @@ public function testContain(bool $modifierCondition, string $assertMethod) /** * Test Verify::contain() with & without case sensitivity. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider containAssertMethods */ public function testContainCaseSensitive(bool $modifierCondition, string $assertMethod) @@ -743,9 +689,6 @@ public function testContainCaseSensitive(bool $modifierCondition, string $assert /** * Test Verify::contain() with & without data type. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider containAssertMethods */ public function testContainDataType(bool $modifierCondition, string $assertMethod) @@ -772,9 +715,6 @@ public function testContainDataType(bool $modifierCondition, string $assertMetho /** * Test Verify::contain() with & without object identity. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider containAssertMethods */ public function testContainObjectIdentity(bool $modifierCondition, string $assertMethod) @@ -801,9 +741,6 @@ public function testContainObjectIdentity(bool $modifierCondition, string $asser /** * Test Verify::containOnly(). * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider containOnlyAssertMethods */ public function testContainOnly(bool $modifierCondition, string $assertMethod) @@ -820,9 +757,6 @@ public function testContainOnly(bool $modifierCondition, string $assertMethod) /** * Test Verify::equalTo(). * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider equalToAssertMethods */ public function testEqualTo(bool $modifierCondition, string $assertMethod) @@ -846,9 +780,6 @@ public function testEqualTo(bool $modifierCondition, string $assertMethod) /** * Test Verify::equalTo() with or without case sensitivity. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider equalToAssertMethods */ public function testEqualToCaseSensitive(bool $modifierCondition, string $assertMethod) @@ -889,9 +820,6 @@ public function testEqualToCaseSensitive(bool $modifierCondition, string $assert /** * Test Verify::equalToFile(). * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider equalToFileAssertMethods */ public function testEqualToFile(bool $modifierCondition, string $assertMethod) @@ -913,9 +841,6 @@ public function testEqualToFile(bool $modifierCondition, string $assertMethod) /** * Test Verify::equalToFile() with or without case sensitivity. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider equalToFileAssertMethods */ public function testEqualToFileCaseSensitive(bool $modifierCondition, string $assertMethod) @@ -952,9 +877,6 @@ public function testEqualToFileCaseSensitive(bool $modifierCondition, string $as /** * Test Verify::equalTo() with some float delta. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider equalToAssertMethods */ public function testEqualToFloatDelta(bool $modifierCondition, string $assertMethod) @@ -978,9 +900,6 @@ public function testEqualToFloatDelta(bool $modifierCondition, string $assertMet /** * Test Verify::equalTo() with or without order. * - * @param bool $modifierCondition - * @param string $assertMethod - * * @dataProvider equalToAssertMethods */ public function testEqualToOrder(bool $modifierCondition, string $assertMethod) @@ -1064,35 +983,34 @@ public function testSubset() $this->setModifierCondition(true); $this->mockAssert->shouldReceive('assertArraySubset') - ->with('subset', 'actual value', Mockery::any(), 'some message') + ->with(['subset'], 'actual value', Mockery::any(), 'some message') ->once(); - $this->assertSame($this->subject, $this->subject->subset('subset')); + $this->assertSame($this->subject, $this->subject->subset(['subset'])); $this->subject = new Verify('actual with type', 'message with type'); $this->setModifierCondition(true); $this->mockAssert->shouldReceive('assertArraySubset') - ->with('subset with type', 'actual with type', true, 'message with type') + ->with(['subset with type'], 'actual with type', true, 'message with type') ->once(); - $this->assertSame($this->subject, $this->subject->withType()->subset('subset with type')); + $this->assertSame($this->subject, $this->subject->withType()->subset(['subset with type'])); $this->subject = new Verify('actual w/o type', 'message w/o type'); $this->setModifierCondition(true); $this->mockAssert->shouldReceive('assertArraySubset') - ->with('subset w/o type', 'actual w/o type', false, 'message w/o type') + ->with(['subset w/o type'], 'actual w/o type', false, 'message w/o type') ->once(); - $this->assertSame($this->subject, $this->subject->withoutType()->subset('subset w/o type')); + $this->assertSame($this->subject, $this->subject->withoutType()->subset(['subset w/o type'])); } /** * Test methods that do not support negative conditions throw an exception. * - * @param string $methodName - * @param mixed $value + * @param mixed $value * * @dataProvider methodsWithoutNegativeCondition */ From d66f1f73cfcd58b4ef348d53e19df4cf9a9058e8 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Tue, 14 May 2019 10:18:45 -0500 Subject: [PATCH 02/14] Keep PHP 7 compatibility and work around incompatible dependencies Issue #50 --- .travis.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index bbf90ff..73ebc3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,27 +7,33 @@ php: - 7.3 env: - - PHPUNIT_VERSION=6.0 - - PHPUNIT_VERSION=7.0 + - PHPUNIT_VERSION=6.0 TEST_SUITE=unit + - PHPUNIT_VERSION=7.0 TEST_SUITE=static + - PHPUNIT_VERSION=7.0 TEST_SUITE=unit matrix: exclude: - php: 7 - env: PHPUNIT_VERSION=7.0 - exclude: + env: PHPUNIT_VERSION=7.0 TEST_SUITE=static + - php: 7 + env: PHPUNIT_VERSION=7.0 TEST_SUITE=unit - php: 7.3 - env: PHPUNIT_VERSION=6.0 + env: PHPUNIT_VERSION=6.0 TEST_SUITE=unit sudo: false +before_install: + # Remove some dependencies that aren't needed for static test suite and are incompatible with PHP 7 or PHPUnit 6 + - if [ $TEST_SUITE == "unit" ]; then composer remove --dev localheinz/composer-normalize maglnet/composer-require-checker phpstan/phpstan phpstan/phpstan-mockery phpstan/phpstan-phpunit; fi + install: - composer require phpunit/phpunit:^$PHPUNIT_VERSION --update-no-dev --no-interaction --prefer-dist --no-progress --no-suggest --update-with-all-dependencies - travis_retry composer install --dev --no-interaction --prefer-dist script: - - composer cs:check - - composer test:static - - composer test:coverage + - if [$TEST_SUITE == "static"]; then composer cs:check; fi + - if [$TEST_SUITE == "static"]; then composer test:static; fi + - if [$TEST_SUITE == "unit"]; then composer test:coverage; fi after_success: - bash <(curl -s https://codecov.io/bash) From fb9f7a32352fa63a4272cb1f95af5e168fabbabe Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Tue, 21 Jul 2020 11:17:49 -0500 Subject: [PATCH 03/14] Add gitattributes Update dependencies & versions Expand Travis matrix Hopefully retain (most) backwards compatibility Issues #50, #49, #47 --- .gitattributes | 9 ++ .gitignore | 162 +++++++++++++++++++++++++++++- .php_cs | 44 ++++---- .travis.yml | 42 +++++++- composer.json | 35 ++++--- hooks/pre-commit.sh | 2 +- phpstan.neon.dist | 17 ++-- src/MissingConditionException.php | 7 +- src/Verify.php | 20 ++-- src/VerifyBase.php | 7 +- test/FunctionsTest.php | 13 ++- test/SetupMockeryTrait.php | 61 +++++++++++ test/UnitTestBase.php | 29 +++--- test/VerifyDirectoryTest.php | 12 +-- test/VerifyFileTest.php | 14 +-- test/VerifyTest.php | 76 ++++++++++++-- 16 files changed, 453 insertions(+), 97 deletions(-) create mode 100644 .gitattributes create mode 100644 test/SetupMockeryTrait.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9f32009 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and miscellaneous support files with "export-ignore". +/.* export-ignore +/hooks export-ignore +/phpstan.neon.dist export-ignore +/phpunit.xml export-ignore +/test export-ignore diff --git a/.gitignore b/.gitignore index 54c07a5..696a1e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,160 @@ -vendor -.idea +# Created by https://www.toptal.com/developers/gitignore/api/macos,linux,composer,intellij+all,phpunit +# Edit at https://www.toptal.com/developers/gitignore?templates=macos,linux,composer,intellij+all,phpunit + +### Composer ### composer.phar +/vendor/ + +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file composer.lock -.php_cs.cache -phpstan.neon + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### PHPUnit ### +# Covers PHPUnit +# Reference: https://phpunit.de/ + +# Generated files +.phpunit.result.cache + +# PHPUnit +/app/phpunit.xml +/phpunit.xml + +# Build data +/build/ + +# End of https://www.toptal.com/developers/gitignore/api/macos,linux,composer,intellij+all,phpunit +/.php_cs.cache +/phpstan.neon diff --git a/.php_cs b/.php_cs index 10da338..4b0d21b 100644 --- a/.php_cs +++ b/.php_cs @@ -13,7 +13,7 @@ return PhpCsFixer\Config::create() '@PHPUnit60Migration:risky' => true, '@PhpCsFixer' => true, '@PhpCsFixer:risky' => true, - 'align_multiline_comment' => ['comment_type' => 'all_multiline'], + 'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], 'backtick_to_shell_exec' => true, 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], @@ -21,21 +21,29 @@ return PhpCsFixer\Config::create() 'single_item_single_line' => true, 'multi_line_extends_each_single_line' => true, ], - 'concat_space' => ['spacing' => 'one'], - 'date_time_immutable' => true, - 'escape_implicit_backslashes' => ['single_quoted' => true], - 'linebreak_after_opening_tag' => true, - 'list_syntax' => true, - 'mb_str_functions' => true, - 'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'], - 'no_php4_constructor' => true, - 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], - 'ordered_class_elements' => ['sortAlgorithm' => 'alpha'], - 'phpdoc_types_order' => ['sort_algorithm' => 'none', 'null_adjustment' => 'always_last'], - 'php_unit_test_case_static_method_calls' => ['call_type' => 'this'], - 'php_unit_test_class_requires_covers' => false, - 'psr0' => ['dir' => 'src'], - 'simplified_null_return' => true, - 'yoda_style' => false, + 'concat_space' => ['spacing' => 'one'], + 'date_time_immutable' => true, + 'final_static_access' => true, + 'global_namespace_import' => true, + 'linebreak_after_opening_tag' => true, + 'list_syntax' => true, + 'mb_str_functions' => true, + 'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'], + 'no_php4_constructor' => true, + 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], + 'no_unset_on_property' => false, + 'nullable_type_declaration_for_default_null_value' => true, + 'ordered_class_elements' => ['sortAlgorithm' => 'alpha'], + 'ordered_imports' => ['imports_order' => ['const', 'class', 'function']], + 'phpdoc_line_span' => ['const' => 'single', 'property' => 'single'], + 'phpdoc_no_empty_return' => false, + 'phpdoc_types_order' => ['sort_algorithm' => 'none', 'null_adjustment' => 'always_last'], + 'php_unit_test_case_static_method_calls' => ['call_type' => 'this'], + 'php_unit_test_class_requires_covers' => false, + 'psr0' => ['dir' => 'src'], + 'self_static_accessor' => true, + 'simplified_null_return' => true, + 'yoda_style' => false, ]) - ->setFinder($finder); + ->setFinder($finder) + ->setRiskyAllowed(true); diff --git a/.travis.yml b/.travis.yml index 73ebc3f..9c76923 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,21 +5,61 @@ php: - 7.1 - 7.2 - 7.3 + - 7.4 env: - PHPUNIT_VERSION=6.0 TEST_SUITE=unit - PHPUNIT_VERSION=7.0 TEST_SUITE=static - PHPUNIT_VERSION=7.0 TEST_SUITE=unit + - PHPUNIT_VERSION=8.0 TEST_SUITE=static + - PHPUNIT_VERSION=8.0 TEST_SUITE=unit + - PHPUNIT_VERSION=9.0 TEST_SUITE=static + - PHPUNIT_VERSION=9.0 TEST_SUITE=unit matrix: exclude: + # PHP 7.0 - php: 7 env: PHPUNIT_VERSION=7.0 TEST_SUITE=static - php: 7 env: PHPUNIT_VERSION=7.0 TEST_SUITE=unit + - php: 7 + env: PHPUNIT_VERSION=8.0 TEST_SUITE=static + - php: 7 + env: PHPUNIT_VERSION=8.0 TEST_SUITE=unit + - php: 7 + env: PHPUNIT_VERSION=9.0 TEST_SUITE=static + - php: 7 + env: PHPUNIT_VERSION=9.0 TEST_SUITE=unit + + # PHP 7.1 + - php: 7.1 + env: PHPUNIT_VERSION=8.0 TEST_SUITE=static + - php: 7.1 + env: PHPUNIT_VERSION=8.0 TEST_SUITE=unit + - php: 7.1 + env: PHPUNIT_VERSION=9.0 TEST_SUITE=static + - php: 7.1 + env: PHPUNIT_VERSION=9.0 TEST_SUITE=unit + + # PHP 7.2 + - php: 7.2 + env: PHPUNIT_VERSION=9.0 TEST_SUITE=static + - php: 7.2 + env: PHPUNIT_VERSION=9.0 TEST_SUITE=unit + + # PHP 7.3 - php: 7.3 env: PHPUNIT_VERSION=6.0 TEST_SUITE=unit + # PHP 7.4 + - php: 7.4 + env: PHPUNIT_VERSION=6.0 TEST_SUITE=unit + - php: 7.4 + env: PHPUNIT_VERSION=7.0 TEST_SUITE=static + - php: 7.4 + env: PHPUNIT_VERSION=7.0 TEST_SUITE=unit + sudo: false before_install: @@ -31,7 +71,7 @@ install: - travis_retry composer install --dev --no-interaction --prefer-dist script: - - if [$TEST_SUITE == "static"]; then composer cs:check; fi + - if [$TEST_SUITE == "static"]; then composer style:check; fi - if [$TEST_SUITE == "static"]; then composer test:static; fi - if [$TEST_SUITE == "unit"]; then composer test:coverage; fi diff --git a/composer.json b/composer.json index 98a1fd9..45068a3 100644 --- a/composer.json +++ b/composer.json @@ -26,19 +26,20 @@ ], "require": { "php": "^7.0", - "phpunit/phpunit": "^6.0 || ^7.0" + "phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0" }, "replace": { "codeception/verify": "*" }, "require-dev": { + "ergebnis/composer-normalize": "^2.6", "friendsofphp/php-cs-fixer": "^2.15", - "localheinz/composer-normalize": "^1.1", - "mockery/mockery": "^1.0", "maglnet/composer-require-checker": "^2.0", - "phpstan/phpstan": "^0.11.6", - "phpstan/phpstan-mockery": "^0.11.0", - "phpstan/phpstan-phpunit": "^0.11.0" + "mockery/mockery": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-mockery": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12" }, "suggest": { "codeception/specify": "Highly readable test code blocks for PHPUnit and Codeception" @@ -58,17 +59,25 @@ }, "minimum-stability": "stable", "scripts": { - "cs:check": "php-cs-fixer fix -v --allow-risky=yes --ansi --dry-run --diff", - "cs:fix": "php-cs-fixer fix -v --allow-risky=yes --ansi", - "test:all": [ - "@composer cs:check", - "@composer test:static", - "@composer test:unit" + "style:check": "php-cs-fixer fix -v --ansi --dry-run --diff", + "style:fix": "php-cs-fixer fix -v --ansi", + "test": [ + "@style:check", + "@test:static", + "@test:unit" ], "test:coverage": "phpunit --coverage-clover=coverage.xml", - "test:static": "phpstan analyze --ansi --level 7 src test", + "test:static": "phpstan analyze --ansi", "test:unit": "phpunit --colors=always" }, + "scripts-descriptions": { + "style:check": "Check all files for code style violations.", + "style:fix": "Automatically fix code style in all files.", + "test": "Check code style, static analysis, and unit tests.", + "test:coverage": "Run unit tests and generate coverage report.", + "test:static": "Run phpstan static analysis.", + "test:unit": "Run unit tests." + }, "support": { "issues": "https://github.com/bbatsche/Verify/issues", "docs": "https://github.com/bbatsche/Verify/blob/master/README.md" diff --git a/hooks/pre-commit.sh b/hooks/pre-commit.sh index d586411..4570c24 100755 --- a/hooks/pre-commit.sh +++ b/hooks/pre-commit.sh @@ -11,7 +11,7 @@ git diff --cached --name-only | while read FILE; do fi if ! [[ "$FILE" =~ src/function.php$ ]]; then - composer cs:check "$FILE" 2> /dev/null + composer style:check "$FILE" 2> /dev/null if [ $? -ne 0 ]; then echo -e "\033[1;31m\tAborting Commit! Files do not follow coding standards.\033[0m" >&2 exit 1 diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 2949e03..5a00dcd 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,4 +1,9 @@ parameters: + level: 8 + paths: + - src + - test + checkMissingIterableValueType: false ignoreErrors: - message: '/PHPDoc tag @param references unknown parameter: \$actual/' @@ -6,16 +11,14 @@ parameters: - message: '/PHPDoc tag @param references unknown parameter: \$description/' path: %currentWorkingDirectory%/src/function.php + - + message: '/has parameter \$args with no typehint specified/' + path: %currentWorkingDirectory%/src/function.php - message: '/Trying to invoke string but it might not be a callable/' path: %currentWorkingDirectory%/test/FunctionsTest.php - - - message: '/Property [a-zA-Z\\:$]+ \([a-zA-Z\\&|]+\) does not accept alias:[a-zA-Z\\&|]+/' - path: %currentWorkingDirectory%/test/UnitTestBase.php - message: '/Call to an undefined method BeBat\\Verify\\Verify::[a-z_]+_conjunction\(\)/' path: %currentWorkingDirectory%/test/VerifyTest.php -includes: - - vendor/phpstan/phpstan-mockery/extension.neon - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon + - '/Mockery\\LegacyMockInterface::shouldReceive/' + - '/Mockery\\HigherOrderMessage::with/' diff --git a/src/MissingConditionException.php b/src/MissingConditionException.php index 0cda262..4397f3a 100644 --- a/src/MissingConditionException.php +++ b/src/MissingConditionException.php @@ -4,9 +4,12 @@ namespace BeBat\Verify; -class MissingConditionException extends \BadMethodCallException +use BadMethodCallException; +use Throwable; + +class MissingConditionException extends BadMethodCallException { - public function __construct(int $code = 0, \Throwable $previous = null) + public function __construct(int $code = 0, ?Throwable $previous = null) { parent::__construct('Assertions must be prefaced by some condition method, such as "is()", "will()", "doesNot()", "isNot()", etc.', $code, $previous); } diff --git a/src/Verify.php b/src/Verify.php index fab43e4..e9cbdaf 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -4,7 +4,11 @@ namespace BeBat\Verify; +use BadMethodCallException; use BeBat\Verify\Assert as a; +use Countable; +use DOMElement; +use Traversable; /** * Verify Class. @@ -450,9 +454,9 @@ public function equalToXmlString(string $xmlString): self /** * Assert SUT has the same XML structur as a given DOMElement. * - * @param \DOMElement $xml Structure SUT is expected to match + * @param DOMElement $xml Structure SUT is expected to match */ - public function equalToXmlStructure(\DOMElement $xml): self + public function equalToXmlStructure(DOMElement $xml): self { if (!isset($this->modifierCondition)) { throw new MissingConditionException(); @@ -461,7 +465,7 @@ public function equalToXmlStructure(\DOMElement $xml): self if ($this->modifierCondition) { a::assertEqualXMLStructure($xml, $this->actual, $this->xmlAttributes, $this->description); } else { - throw new \BadMethodCallException(__METHOD__ . ' does not support negative condition.'); + throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } return $this; @@ -580,7 +584,7 @@ public function infinite(): self /** * Assert SUT is or is not an instance of a given class. * - * @param string $class Name of class SUT is expected to be an instance of + * @param class-string $class Name of class SUT is expected to be an instance of */ public function instanceOf(string $class): self { @@ -645,7 +649,7 @@ public function json(): self if ($this->modifierCondition) { a::assertJson($this->actual, $this->description); } else { - throw new \BadMethodCallException(__METHOD__ . ' does not support negative condition.'); + throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } return $this; @@ -803,7 +807,7 @@ public function nan(): self if ($this->modifierCondition) { a::assertNan($this->actual, $this->description); } else { - throw new \BadMethodCallException(__METHOD__ . ' does not support negative condition.'); + throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } return $this; @@ -858,7 +862,7 @@ public function sameAs($expected): self /** * Assert SUT does or does not have the same number of elements as given array/Countable/Traversable object. * - * @param array|\Countable|\Traversable $expected Value SUT is expected to be the same size as + * @param array|Countable|Traversable $expected Value SUT is expected to be the same size as */ public function sameSizeAs($expected): self { @@ -929,7 +933,7 @@ public function subset($array): self if ($this->modifierCondition) { a::assertArraySubset($array, $this->actual, $this->dataType, $this->description); } else { - throw new \BadMethodCallException(__METHOD__ . ' does not support negative condition.'); + throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } return $this; diff --git a/src/VerifyBase.php b/src/VerifyBase.php index 4c4b2c3..a1f475f 100644 --- a/src/VerifyBase.php +++ b/src/VerifyBase.php @@ -4,6 +4,8 @@ namespace BeBat\Verify; +use BadMethodCallException; + /** * VerifyBase Class. * @@ -25,10 +27,13 @@ */ abstract class VerifyBase { + /** @var string[] */ public static $negativeConjunctions = ['doesNot', 'isNot', 'willNot']; + /** @var string[] */ public static $neutralConjunctions = ['and', 'be', 'have']; + /** @var string[] */ public static $positiveConjunctions = ['does', 'has', 'is', 'will']; /** @@ -94,7 +99,7 @@ public function __call(string $method, array $arguments = []): self return $this; } - throw new \BadMethodCallException("Unknown method {$method}."); + throw new BadMethodCallException("Unknown method {$method}."); } /** diff --git a/test/FunctionsTest.php b/test/FunctionsTest.php index 858f8d2..6141b11 100644 --- a/test/FunctionsTest.php +++ b/test/FunctionsTest.php @@ -4,6 +4,7 @@ namespace BeBat\Verify\Test; +use BadFunctionCallException; use BeBat\Verify\Verify; use BeBat\Verify\VerifyDirectory; use BeBat\Verify\VerifyFile; @@ -17,7 +18,11 @@ final class FunctionsTest extends TestCase /** * Test verify*() methods' default behavior. * + * @param class-string $className + * * @dataProvider verifyFunctions + * + * @return void */ public function testFunction(string $functionName, string $className) { @@ -37,10 +42,12 @@ public function testFunction(string $functionName, string $className) * Test exception thrown with zero arguments. * * @dataProvider verifyFunctions + * + * @return void */ public function testFunctionNoArguments(string $functionName) { - $this->expectException(\BadFunctionCallException::class); + $this->expectException(BadFunctionCallException::class); $functionName(); } @@ -48,10 +55,12 @@ public function testFunctionNoArguments(string $functionName) * Test exception thrown with too many arguments. * * @dataProvider verifyFunctions + * + * @return void */ public function testFunctionTooManyArguments(string $functionName) { - $this->expectException(\BadFunctionCallException::class); + $this->expectException(BadFunctionCallException::class); $functionName('param 1', 'param 2', 'param 3'); } diff --git a/test/SetupMockeryTrait.php b/test/SetupMockeryTrait.php new file mode 100644 index 0000000..e352015 --- /dev/null +++ b/test/SetupMockeryTrait.php @@ -0,0 +1,61 @@ += 1) { + trait SetupMockeryTrait + { + /** + * Assertion mock. + * + * @var Assert|\Mockery\LegacyMockInterface + */ + protected $mockAssert; + + protected function setUp(): void + { + $this->initSubject(); + + $this->mockAssert = Mockery::mock('alias:' . Assert::class); + } + + /** + * Initialize the subject to be tested. + * + * @return void + */ + abstract protected function initSubject(); + } +} else { + trait SetupMockeryTrait + { + /** + * Assertion mock. + * + * @var Assert|\Mockery\LegacyMockInterface + */ + protected $mockAssert; + + /** + * @return void + */ + protected function setUp() + { + $this->initSubject(); + + $this->mockAssert = Mockery::mock('alias:' . Assert::class); + } + + /** + * Initialize the subject to be tested. + * + * @return void + */ + abstract protected function initSubject(); + } +} diff --git a/test/UnitTestBase.php b/test/UnitTestBase.php index 594e6cb..45e7266 100644 --- a/test/UnitTestBase.php +++ b/test/UnitTestBase.php @@ -4,15 +4,15 @@ namespace BeBat\Verify\Test; -use BeBat\Verify\Assert; use BeBat\Verify\MissingConditionException; -use Mockery; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use PHPUnit\Framework\TestCase; +use ReflectionObject; abstract class UnitTestBase extends TestCase { use MockeryPHPUnitIntegration; + use SetupMockeryTrait; /** * Default value used for Verify objects. @@ -21,13 +21,6 @@ abstract class UnitTestBase extends TestCase */ protected $defaultActualValue; - /** - * Assertion mock. - * - * @var Assert&\Mockery\MockInterface - */ - protected $mockAssert; - /** * Verify class. * @@ -35,17 +28,14 @@ abstract class UnitTestBase extends TestCase */ protected $subject; - protected function setUp() - { - $this->mockAssert = Mockery::mock('alias:' . Assert::class); - } - /** * Test MissingConditionException is thrown for all methods. * * @param mixed $value * * @dataProvider allMethods + * + * @return void */ public function testMissingConditionException(string $verifyMethod, $value = 'dummy value') { @@ -58,6 +48,8 @@ public function testMissingConditionException(string $verifyMethod, $value = 'du * Test VerifyFile methods that don't take any value. * * @dataProvider noParamMethods + * + * @return void */ public function testNoParamMethods(bool $modifierCondition, string $verifyMethod, string $assertMethod) { @@ -76,6 +68,8 @@ public function testNoParamMethods(bool $modifierCondition, string $verifyMethod * @param mixed $expectedValue * * @dataProvider singleParamMethods + * + * @return void */ public function testSingleParamMethods( bool $modifierCondition, @@ -92,9 +86,14 @@ public function testSingleParamMethods( $this->assertSame($this->subject, $this->subject->{$verifyMethod}($expectedValue)); } + /** + * Inject $value into modifierCondition of subject. + * + * @return void + */ protected function setModifierCondition(bool $value) { - $reflection = new \ReflectionObject($this->subject); + $reflection = new ReflectionObject($this->subject); $modifierProperty = $reflection->getProperty('modifierCondition'); $modifierProperty->setAccessible(true); $modifierProperty->setValue($this->subject, $value); diff --git a/test/VerifyDirectoryTest.php b/test/VerifyDirectoryTest.php index ae3ceca..f0129aa 100644 --- a/test/VerifyDirectoryTest.php +++ b/test/VerifyDirectoryTest.php @@ -13,13 +13,6 @@ final class VerifyDirectoryTest extends UnitTestBase { protected $defaultActualValue = 'directory under test'; - protected function setUp() - { - $this->subject = new VerifyDirectory($this->defaultActualValue, 'some message'); - - parent::setUp(); - } - /** * All VerifyDirectory methods. */ @@ -61,4 +54,9 @@ public function testSingleParamMethods( $expectedValue = 'some value' ) { } + + protected function initSubject() + { + $this->subject = new VerifyDirectory($this->defaultActualValue, 'some message'); + } } diff --git a/test/VerifyFileTest.php b/test/VerifyFileTest.php index f746058..e658a45 100644 --- a/test/VerifyFileTest.php +++ b/test/VerifyFileTest.php @@ -21,13 +21,6 @@ final class VerifyFileTest extends UnitTestBase */ protected $subject; - protected function setUp() - { - $this->subject = new VerifyFile($this->defaultActualValue, 'some message'); - - parent::setUp(); - } - /** * All VerifyFile methods. */ @@ -86,6 +79,8 @@ public function singleParamMethods(): array * Test VerifyFile::equalTo(). * * @dataProvider equalToMethods + * + * @return void */ public function testEqualTo(bool $modifierConition, string $assertMethod) { @@ -115,4 +110,9 @@ public function testEqualTo(bool $modifierConition, string $assertMethod) $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('expected file w/o case')); } + + protected function initSubject() + { + $this->subject = new VerifyFile($this->defaultActualValue, 'some message'); + } } diff --git a/test/VerifyTest.php b/test/VerifyTest.php index 3f9c374..4143190 100644 --- a/test/VerifyTest.php +++ b/test/VerifyTest.php @@ -4,9 +4,11 @@ namespace BeBat\Verify\Test; +use BadMethodCallException; use BeBat\Verify\Verify; use DOMElement; use Mockery; +use stdClass; /** * @internal @@ -22,13 +24,6 @@ final class VerifyTest extends UnitTestBase */ protected $subject; - protected function setUp() - { - $this->subject = new Verify($this->defaultActualValue, 'some message'); - - parent::setUp(); - } - /** * All possible verify methods. */ @@ -80,9 +75,9 @@ public function attributeAssertMethods(): array { return [ [true, 'SomeClass', 'assertClassHasAttribute'], - [true, new \stdClass(), 'assertObjectHasAttribute'], + [true, new stdClass(), 'assertObjectHasAttribute'], [false, 'SomeClass', 'assertClassNotHasAttribute'], - [false, new \stdClass(), 'assertObjectNotHasAttribute'], + [false, new stdClass(), 'assertObjectNotHasAttribute'], ]; } @@ -277,6 +272,8 @@ public function singleParamMethods(): array * Test Verify::contain() with & without case sensitivity for attributes. * * @dataProvider attributeContainAssertMethods + * + * @return void */ public function testAttribueContainCaseSensitive(bool $modifierCondition, string $assertMethod) { @@ -319,6 +316,8 @@ public function testAttribueContainCaseSensitive(bool $modifierCondition, string * Test Verify::contain() with & without data type for attributes. * * @dataProvider attributeContainAssertMethods + * + * @return void */ public function testAttribueContainDataType(bool $modifierCondition, string $assertMethod) { @@ -361,6 +360,8 @@ public function testAttribueContainDataType(bool $modifierCondition, string $ass * Test Verify::contain() with & without object identity for attributes. * * @dataProvider attributeContainAssertMethods + * + * @return void */ public function testAttribueContainObjectIdentity(bool $modifierCondition, string $assertMethod) { @@ -405,6 +406,8 @@ public function testAttribueContainObjectIdentity(bool $modifierCondition, strin * @param string|object $actualValue * * @dataProvider attributeAssertMethods + * + * @return void */ public function testAttribute(bool $modifierCondition, $actualValue, string $assertMethod) { @@ -425,6 +428,8 @@ public function testAttribute(bool $modifierCondition, $actualValue, string $ass * @param mixed $expectedValue * * @dataProvider attributeMethods + * + * @return void */ public function testAttributeAssertions( bool $modifierCondition, @@ -447,6 +452,8 @@ public function testAttributeAssertions( * Test Verify::contain() basic case for attributes. * * @dataProvider attributeContainAssertMethods + * + * @return void */ public function testAttributeContain(bool $modifierCondition, string $assertMethod) { @@ -464,6 +471,8 @@ public function testAttributeContain(bool $modifierCondition, string $assertMeth * Test Verify::containOnly() for object attributes. * * @dataProvider attributeContainOnlyAssertMethods + * + * @return void */ public function testAttributeContainOnly(bool $modifierCondition, string $assertMethod) { @@ -481,6 +490,8 @@ public function testAttributeContainOnly(bool $modifierCondition, string $assert * Test Verify::equalTo() for attributes. * * @dataProvider attributeEqualToAssertMethods + * + * @return void */ public function testAttributeEqualTo(bool $modifierCondition, string $assertMethod) { @@ -506,6 +517,8 @@ public function testAttributeEqualTo(bool $modifierCondition, string $assertMeth * Test Verify::equalTo() for attributes with or without case sensitivity. * * @dataProvider attributeEqualToAssertMethods + * + * @return void */ public function testAttributeEqualToCaseSensitive(bool $modifierCondition, string $assertMethod) { @@ -550,6 +563,8 @@ public function testAttributeEqualToCaseSensitive(bool $modifierCondition, strin * Test Verify::equalTo() for attributes with some float delta. * * @dataProvider attributeEqualToAssertMethods + * + * @return void */ public function testAttributeEqualToFloatDelta(bool $modifierCondition, string $assertMethod) { @@ -575,6 +590,8 @@ public function testAttributeEqualToFloatDelta(bool $modifierCondition, string $ * Test Verify::equalTo() for attributes with or without order. * * @dataProvider attributeEqualToAssertMethods + * + * @return void */ public function testAttributeEqualToOrder(bool $modifierCondition, string $assertMethod) { @@ -617,16 +634,20 @@ public function testAttributeEqualToOrder(bool $modifierCondition, string $asser /** * Test exception for invalid conjunction. + * + * @return void */ public function testConjunctionException() { - $this->expectException(\BadMethodCallException::class); + $this->expectException(BadMethodCallException::class); $this->subject->some_invalid_conjunction(); $this->assertAttributeSame(null, 'modifierCondition', $this->subject); } /** * Test conjunction magic method. + * + * @return void */ public function testConjunctions() { @@ -648,6 +669,8 @@ public function testConjunctions() * Test Verify::contain() basic case. * * @dataProvider containAssertMethods + * + * @return void */ public function testContain(bool $modifierCondition, string $assertMethod) { @@ -664,6 +687,8 @@ public function testContain(bool $modifierCondition, string $assertMethod) * Test Verify::contain() with & without case sensitivity. * * @dataProvider containAssertMethods + * + * @return void */ public function testContainCaseSensitive(bool $modifierCondition, string $assertMethod) { @@ -690,6 +715,8 @@ public function testContainCaseSensitive(bool $modifierCondition, string $assert * Test Verify::contain() with & without data type. * * @dataProvider containAssertMethods + * + * @return void */ public function testContainDataType(bool $modifierCondition, string $assertMethod) { @@ -716,6 +743,8 @@ public function testContainDataType(bool $modifierCondition, string $assertMetho * Test Verify::contain() with & without object identity. * * @dataProvider containAssertMethods + * + * @return void */ public function testContainObjectIdentity(bool $modifierCondition, string $assertMethod) { @@ -742,6 +771,8 @@ public function testContainObjectIdentity(bool $modifierCondition, string $asser * Test Verify::containOnly(). * * @dataProvider containOnlyAssertMethods + * + * @return void */ public function testContainOnly(bool $modifierCondition, string $assertMethod) { @@ -758,6 +789,8 @@ public function testContainOnly(bool $modifierCondition, string $assertMethod) * Test Verify::equalTo(). * * @dataProvider equalToAssertMethods + * + * @return void */ public function testEqualTo(bool $modifierCondition, string $assertMethod) { @@ -781,6 +814,8 @@ public function testEqualTo(bool $modifierCondition, string $assertMethod) * Test Verify::equalTo() with or without case sensitivity. * * @dataProvider equalToAssertMethods + * + * @return void */ public function testEqualToCaseSensitive(bool $modifierCondition, string $assertMethod) { @@ -821,6 +856,8 @@ public function testEqualToCaseSensitive(bool $modifierCondition, string $assert * Test Verify::equalToFile(). * * @dataProvider equalToFileAssertMethods + * + * @return void */ public function testEqualToFile(bool $modifierCondition, string $assertMethod) { @@ -842,6 +879,8 @@ public function testEqualToFile(bool $modifierCondition, string $assertMethod) * Test Verify::equalToFile() with or without case sensitivity. * * @dataProvider equalToFileAssertMethods + * + * @return void */ public function testEqualToFileCaseSensitive(bool $modifierCondition, string $assertMethod) { @@ -878,6 +917,8 @@ public function testEqualToFileCaseSensitive(bool $modifierCondition, string $as * Test Verify::equalTo() with some float delta. * * @dataProvider equalToAssertMethods + * + * @return void */ public function testEqualToFloatDelta(bool $modifierCondition, string $assertMethod) { @@ -901,6 +942,8 @@ public function testEqualToFloatDelta(bool $modifierCondition, string $assertMet * Test Verify::equalTo() with or without order. * * @dataProvider equalToAssertMethods + * + * @return void */ public function testEqualToOrder(bool $modifierCondition, string $assertMethod) { @@ -939,6 +982,8 @@ public function testEqualToOrder(bool $modifierCondition, string $assertMethod) /** * Test Verify::equalToXmlStructure(). + * + * @return void */ public function testEqualToXmlStructure() { @@ -977,6 +1022,8 @@ public function testEqualToXmlStructure() /** * Test Verify::subset(). + * + * @return void */ public function testSubset() { @@ -1013,14 +1060,21 @@ public function testSubset() * @param mixed $value * * @dataProvider methodsWithoutNegativeCondition + * + * @return void */ public function testUnsupportedNegativeCondition(string $methodName, $value = 'dummy value') { $this->setModifierCondition(false); - $this->expectException(\BadMethodCallException::class); + $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage($methodName . ' does not support negative condition.'); $this->subject->{$methodName}($value); } + + protected function initSubject() + { + $this->subject = new Verify($this->defaultActualValue, 'some message'); + } } From 978b991b90f0821ac585dbaaf6ec025bd0f71f4d Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Tue, 21 Jul 2020 11:41:09 -0500 Subject: [PATCH 04/14] Fix removing static analysis requirements in Travis Fix for Mockery blocking older versions of PHPUnit Issue #49, #50 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9c76923..4beb80b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,9 +64,10 @@ sudo: false before_install: # Remove some dependencies that aren't needed for static test suite and are incompatible with PHP 7 or PHPUnit 6 - - if [ $TEST_SUITE == "unit" ]; then composer remove --dev localheinz/composer-normalize maglnet/composer-require-checker phpstan/phpstan phpstan/phpstan-mockery phpstan/phpstan-phpunit; fi + - if [ $TEST_SUITE == "unit" ]; then composer remove --dev ergebnis/composer-normalize maglnet/composer-require-checker phpstan/phpstan phpstan/phpstan-mockery phpstan/phpstan-phpunit phpstan/phpstan-strict-rules; fi install: + - if [ -e composer.lock ]; then rm composer.lock; fi - composer require phpunit/phpunit:^$PHPUNIT_VERSION --update-no-dev --no-interaction --prefer-dist --no-progress --no-suggest --update-with-all-dependencies - travis_retry composer install --dev --no-interaction --prefer-dist From abc0648f28032f48a04db67dc89fb35360217238 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Tue, 21 Jul 2020 17:36:50 -0500 Subject: [PATCH 05/14] Move attribute access to Verify class Fix build (hopefully) Issues #43, #51 --- .travis.yml | 2 +- phpstan.neon.dist | 3 + src/InvalidAttributeException.php | 11 + src/InvalidSubjectException.php | 11 + src/Verify.php | 435 ++++++++++++------------- test/FunctionsTest.php | 27 +- test/Stub/ExampleChild.php | 29 ++ test/Stub/ExampleParent.php | 29 ++ test/VerifyTest.php | 507 +++++++----------------------- 9 files changed, 421 insertions(+), 633 deletions(-) create mode 100644 src/InvalidAttributeException.php create mode 100644 src/InvalidSubjectException.php create mode 100644 test/Stub/ExampleChild.php create mode 100644 test/Stub/ExampleParent.php diff --git a/.travis.yml b/.travis.yml index 4beb80b..e20ad9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,7 +67,7 @@ before_install: - if [ $TEST_SUITE == "unit" ]; then composer remove --dev ergebnis/composer-normalize maglnet/composer-require-checker phpstan/phpstan phpstan/phpstan-mockery phpstan/phpstan-phpunit phpstan/phpstan-strict-rules; fi install: - - if [ -e composer.lock ]; then rm composer.lock; fi + - if [ -e composer.lock ]; then rm -rf composer.lock vendor; fi - composer require phpunit/phpunit:^$PHPUNIT_VERSION --update-no-dev --no-interaction --prefer-dist --no-progress --no-suggest --update-with-all-dependencies - travis_retry composer install --dev --no-interaction --prefer-dist diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 5a00dcd..a49084b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -14,6 +14,9 @@ parameters: - message: '/has parameter \$args with no typehint specified/' path: %currentWorkingDirectory%/src/function.php + - + message: '/Negated boolean expression is always false/' + path: %currentWorkingDirectory%/src/Verify.php - message: '/Trying to invoke string but it might not be a callable/' path: %currentWorkingDirectory%/test/FunctionsTest.php diff --git a/src/InvalidAttributeException.php b/src/InvalidAttributeException.php new file mode 100644 index 0000000..484f217 --- /dev/null +++ b/src/InvalidAttributeException.php @@ -0,0 +1,11 @@ +modifierCondition) { if (\is_string($this->actual)) { - a::assertClassHasAttribute($attribute, $this->actual, $this->description); + a::assertClassHasAttribute($attribute, $this->getActualValue(), $this->description); } else { - a::assertObjectHasAttribute($attribute, $this->actual, $this->description); + a::assertObjectHasAttribute($attribute, $this->getActualValue(), $this->description); } } else { if (\is_string($this->actual)) { - a::assertClassNotHasAttribute($attribute, $this->actual, $this->description); + a::assertClassNotHasAttribute($attribute, $this->getActualValue(), $this->description); } else { - a::assertObjectNotHasAttribute($attribute, $this->actual, $this->description); + a::assertObjectNotHasAttribute($attribute, $this->getActualValue(), $this->description); } } @@ -133,47 +136,23 @@ public function contain($needle): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeContains( - $needle, - $this->attributeName, - $this->actual, - $this->description, - $this->ignoreCase, - $this->objectIdentity, - $this->dataType - ); - } else { - a::assertContains( - $needle, - $this->actual, - $this->description, - $this->ignoreCase, - $this->objectIdentity, - $this->dataType - ); - } + a::assertContains( + $needle, + $this->getActualValue(), + $this->description, + $this->ignoreCase, + $this->objectIdentity, + $this->dataType + ); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotContains( - $needle, - $this->attributeName, - $this->actual, - $this->description, - $this->ignoreCase, - $this->objectIdentity, - $this->dataType - ); - } else { - a::assertNotContains( - $needle, - $this->actual, - $this->description, - $this->ignoreCase, - $this->objectIdentity, - $this->dataType - ); - } + a::assertNotContains( + $needle, + $this->getActualValue(), + $this->description, + $this->ignoreCase, + $this->objectIdentity, + $this->dataType + ); } return $this; @@ -191,21 +170,11 @@ public function containOnly(string $type): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - // $isNativeType can be determined automatically - a::assertAttributeContainsOnly($type, $this->attributeName, $this->actual, null, $this->description); - } else { - // $isNativeType can be determined automatically - a::assertContainsOnly($type, $this->actual, null, $this->description); - } + // $isNativeType can be determined automatically + a::assertContainsOnly($type, $this->getActualValue(), null, $this->description); } else { - if (isset($this->attributeName)) { - // $isNativeType can be determined automatically - a::assertAttributeNotContainsOnly($type, $this->attributeName, $this->actual, null, $this->description); - } else { - // $isNativeType can be determined automatically - a::assertNotContainsOnly($type, $this->actual, null, $this->description); - } + // $isNativeType can be determined automatically + a::assertNotContainsOnly($type, $this->getActualValue(), null, $this->description); } return $this; @@ -225,17 +194,9 @@ public function count(int $count) } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeCount($count, $this->attributeName, $this->actual, $this->description); - } else { - a::assertCount($count, $this->actual, $this->description); - } + a::assertCount($count, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotCount($count, $this->attributeName, $this->actual, $this->description); - } else { - a::assertNotCount($count, $this->actual, $this->description); - } + a::assertNotCount($count, $this->getActualValue(), $this->description); } return $this; @@ -251,17 +212,9 @@ public function empty(): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeEmpty($this->attributeName, $this->actual, $this->description); - } else { - a::assertEmpty($this->actual, $this->description); - } + a::assertEmpty($this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotEmpty($this->attributeName, $this->actual, $this->description); - } else { - a::assertNotEmpty($this->actual, $this->description); - } + a::assertNotEmpty($this->getActualValue(), $this->description); } return $this; @@ -279,9 +232,9 @@ public function endWith(string $suffix): self } if ($this->modifierCondition) { - a::assertStringEndsWith($suffix, $this->actual, $this->description); + a::assertStringEndsWith($suffix, $this->getActualValue(), $this->description); } else { - a::assertStringEndsNotWith($suffix, $this->actual, $this->description); + a::assertStringEndsNotWith($suffix, $this->getActualValue(), $this->description); } return $this; @@ -299,51 +252,25 @@ public function equalTo($expected): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeEquals( - $expected, - $this->attributeName, - $this->actual, - $this->description, - $this->floatDelta, - $this->maxDepth, - $this->ignoreOrder, - $this->ignoreCase - ); - } else { - a::assertEquals( - $expected, - $this->actual, - $this->description, - $this->floatDelta, - $this->maxDepth, - $this->ignoreOrder, - $this->ignoreCase - ); - } + a::assertEquals( + $expected, + $this->getActualValue(), + $this->description, + $this->floatDelta, + $this->maxDepth, + $this->ignoreOrder, + $this->ignoreCase + ); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotEquals( - $expected, - $this->attributeName, - $this->actual, - $this->description, - $this->floatDelta, - $this->maxDepth, - $this->ignoreOrder, - $this->ignoreCase - ); - } else { - a::assertNotEquals( - $expected, - $this->actual, - $this->description, - $this->floatDelta, - $this->maxDepth, - $this->ignoreOrder, - $this->ignoreCase - ); - } + a::assertNotEquals( + $expected, + $this->getActualValue(), + $this->description, + $this->floatDelta, + $this->maxDepth, + $this->ignoreOrder, + $this->ignoreCase + ); } return $this; @@ -362,10 +289,10 @@ public function equalToFile(string $file): self if ($this->modifierCondition) { // $canonicalize hardcoded to false - a::assertStringEqualsFile($file, $this->actual, $this->description, false, $this->ignoreCase); + a::assertStringEqualsFile($file, $this->getActualValue(), $this->description, false, $this->ignoreCase); } else { // $canonicalize hardcoded to false - a::assertStringNotEqualsFile($file, $this->actual, $this->description, false, $this->ignoreCase); + a::assertStringNotEqualsFile($file, $this->getActualValue(), $this->description, false, $this->ignoreCase); } return $this; @@ -383,9 +310,9 @@ public function equalToJsonFile(string $file): self } if ($this->modifierCondition) { - a::assertJsonStringEqualsJsonFile($file, $this->actual, $this->description); + a::assertJsonStringEqualsJsonFile($file, $this->getActualValue(), $this->description); } else { - a::assertJsonStringNotEqualsJsonFile($file, $this->actual, $this->description); + a::assertJsonStringNotEqualsJsonFile($file, $this->getActualValue(), $this->description); } return $this; @@ -403,9 +330,9 @@ public function equalToJsonString(string $string): self } if ($this->modifierCondition) { - a::assertJsonStringEqualsJsonString($string, $this->actual, $this->description); + a::assertJsonStringEqualsJsonString($string, $this->getActualValue(), $this->description); } else { - a::assertJsonStringNotEqualsJsonString($string, $this->actual, $this->description); + a::assertJsonStringNotEqualsJsonString($string, $this->getActualValue(), $this->description); } return $this; @@ -423,9 +350,9 @@ public function equalToXmlFile(string $file): self } if ($this->modifierCondition) { - a::assertXmlStringEqualsXmlFile($file, $this->actual, $this->description); + a::assertXmlStringEqualsXmlFile($file, $this->getActualValue(), $this->description); } else { - a::assertXmlStringNotEqualsXmlFile($file, $this->actual, $this->description); + a::assertXmlStringNotEqualsXmlFile($file, $this->getActualValue(), $this->description); } return $this; @@ -443,9 +370,9 @@ public function equalToXmlString(string $xmlString): self } if ($this->modifierCondition) { - a::assertXmlStringEqualsXmlString($xmlString, $this->actual, $this->description); + a::assertXmlStringEqualsXmlString($xmlString, $this->getActualValue(), $this->description); } else { - a::assertXmlStringNotEqualsXmlString($xmlString, $this->actual, $this->description); + a::assertXmlStringNotEqualsXmlString($xmlString, $this->getActualValue(), $this->description); } return $this; @@ -463,7 +390,7 @@ public function equalToXmlStructure(DOMElement $xml): self } if ($this->modifierCondition) { - a::assertEqualXMLStructure($xml, $this->actual, $this->xmlAttributes, $this->description); + a::assertEqualXMLStructure($xml, $this->getActualValue(), $this->xmlAttributes, $this->description); } else { throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } @@ -481,9 +408,9 @@ public function false(): self } if ($this->modifierCondition) { - a::assertFalse($this->actual, $this->description); + a::assertFalse($this->getActualValue(), $this->description); } else { - a::assertNotFalse($this->actual, $this->description); + a::assertNotFalse($this->getActualValue(), $this->description); } return $this; @@ -499,9 +426,9 @@ public function finite(): self } if ($this->modifierCondition) { - a::assertFinite($this->actual, $this->description); + a::assertFinite($this->getActualValue(), $this->description); } else { - a::assertInfinite($this->actual, $this->description); + a::assertInfinite($this->getActualValue(), $this->description); } return $this; @@ -519,17 +446,9 @@ public function greaterOrEqualTo($expected): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeGreaterThanOrEqual($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertGreaterThanOrEqual($expected, $this->actual, $this->description); - } + a::assertGreaterThanOrEqual($expected, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeLessThan($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertLessThan($expected, $this->actual, $this->description); - } + a::assertLessThan($expected, $this->getActualValue(), $this->description); } return $this; @@ -547,17 +466,9 @@ public function greaterThan($expected): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeGreaterThan($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertGreaterThan($expected, $this->actual, $this->description); - } + a::assertGreaterThan($expected, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeLessThanOrEqual($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertLessThanOrEqual($expected, $this->actual, $this->description); - } + a::assertLessThanOrEqual($expected, $this->getActualValue(), $this->description); } return $this; @@ -573,9 +484,9 @@ public function infinite(): self } if ($this->modifierCondition) { - a::assertInfinite($this->actual, $this->description); + a::assertInfinite($this->getActualValue(), $this->description); } else { - a::assertFinite($this->actual, $this->description); + a::assertFinite($this->getActualValue(), $this->description); } return $this; @@ -593,17 +504,9 @@ public function instanceOf(string $class): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeInstanceOf($class, $this->attributeName, $this->actual, $this->description); - } else { - a::assertInstanceOf($class, $this->actual, $this->description); - } + a::assertInstanceOf($class, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotInstanceOf($class, $this->attributeName, $this->actual, $this->description); - } else { - a::assertNotInstanceOf($class, $this->actual, $this->description); - } + a::assertNotInstanceOf($class, $this->getActualValue(), $this->description); } return $this; @@ -621,17 +524,9 @@ public function internalType(string $type): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeInternalType($type, $this->attributeName, $this->actual, $this->description); - } else { - a::assertInternalType($type, $this->actual, $this->description); - } + a::assertInternalType($type, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotInternalType($type, $this->attributeName, $this->actual, $this->description); - } else { - a::assertNotInternalType($type, $this->actual, $this->description); - } + a::assertNotInternalType($type, $this->getActualValue(), $this->description); } return $this; @@ -647,7 +542,7 @@ public function json(): self } if ($this->modifierCondition) { - a::assertJson($this->actual, $this->description); + a::assertJson($this->getActualValue(), $this->description); } else { throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } @@ -667,9 +562,9 @@ public function key($key): self } if ($this->modifierCondition) { - a::assertArrayHasKey($key, $this->actual, $this->description); + a::assertArrayHasKey($key, $this->getActualValue(), $this->description); } else { - a::assertArrayNotHasKey($key, $this->actual, $this->description); + a::assertArrayNotHasKey($key, $this->getActualValue(), $this->description); } return $this; @@ -687,17 +582,9 @@ public function lessOrEqualTo($expected): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeLessThanOrEqual($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertLessThanOrEqual($expected, $this->actual, $this->description); - } + a::assertLessThanOrEqual($expected, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeGreaterThan($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertGreaterThan($expected, $this->actual, $this->description); - } + a::assertGreaterThan($expected, $this->getActualValue(), $this->description); } return $this; @@ -715,17 +602,9 @@ public function lessThan($expected): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeLessThan($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertLessThan($expected, $this->actual, $this->description); - } + a::assertLessThan($expected, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeGreaterThanOrEqual($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertGreaterThanOrEqual($expected, $this->actual, $this->description); - } + a::assertGreaterThanOrEqual($expected, $this->getActualValue(), $this->description); } return $this; @@ -745,9 +624,9 @@ public function matchFormat(string $format): self } if ($this->modifierCondition) { - a::assertStringMatchesFormat($format, $this->actual, $this->description); + a::assertStringMatchesFormat($format, $this->getActualValue(), $this->description); } else { - a::assertStringNotMatchesFormat($format, $this->actual, $this->description); + a::assertStringNotMatchesFormat($format, $this->getActualValue(), $this->description); } return $this; @@ -767,9 +646,9 @@ public function matchFormatFile(string $formatFile): self } if ($this->modifierCondition) { - a::assertStringMatchesFormatFile($formatFile, $this->actual, $this->description); + a::assertStringMatchesFormatFile($formatFile, $this->getActualValue(), $this->description); } else { - a::assertStringNotMatchesFormatFile($formatFile, $this->actual, $this->description); + a::assertStringNotMatchesFormatFile($formatFile, $this->getActualValue(), $this->description); } return $this; @@ -787,9 +666,9 @@ public function matchRegExp(string $expression): self } if ($this->modifierCondition) { - a::assertRegExp($expression, $this->actual, $this->description); + a::assertRegExp($expression, $this->getActualValue(), $this->description); } else { - a::assertNotRegExp($expression, $this->actual, $this->description); + a::assertNotRegExp($expression, $this->getActualValue(), $this->description); } return $this; @@ -805,7 +684,7 @@ public function nan(): self } if ($this->modifierCondition) { - a::assertNan($this->actual, $this->description); + a::assertNan($this->getActualValue(), $this->description); } else { throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } @@ -823,9 +702,9 @@ public function null(): self } if ($this->modifierCondition) { - a::assertNull($this->actual, $this->description); + a::assertNull($this->getActualValue(), $this->description); } else { - a::assertNotNull($this->actual, $this->description); + a::assertNotNull($this->getActualValue(), $this->description); } return $this; @@ -843,17 +722,9 @@ public function sameAs($expected): self } if ($this->modifierCondition) { - if (isset($this->attributeName)) { - a::assertAttributeSame($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertSame($expected, $this->actual, $this->description); - } + a::assertSame($expected, $this->getActualValue(), $this->description); } else { - if (isset($this->attributeName)) { - a::assertAttributeNotSame($expected, $this->attributeName, $this->actual, $this->description); - } else { - a::assertNotSame($expected, $this->actual, $this->description); - } + a::assertNotSame($expected, $this->getActualValue(), $this->description); } return $this; @@ -871,9 +742,9 @@ public function sameSizeAs($expected): self } if ($this->modifierCondition) { - a::assertSameSize($expected, $this->actual, $this->description); + a::assertSameSize($expected, $this->getActualValue(), $this->description); } else { - a::assertNotSameSize($expected, $this->actual, $this->description); + a::assertNotSameSize($expected, $this->getActualValue(), $this->description); } return $this; @@ -891,9 +762,9 @@ public function startWith(string $prefix): self } if ($this->modifierCondition) { - a::assertStringStartsWith($prefix, $this->actual, $this->description); + a::assertStringStartsWith($prefix, $this->getActualValue(), $this->description); } else { - a::assertStringStartsNotWith($prefix, $this->actual, $this->description); + a::assertStringStartsNotWith($prefix, $this->getActualValue(), $this->description); } return $this; @@ -911,9 +782,9 @@ public function staticAttribute(string $attribute): self } if ($this->modifierCondition) { - a::assertClassHasStaticAttribute($attribute, $this->actual, $this->description); + a::assertClassHasStaticAttribute($attribute, $this->getActualValue(), $this->description); } else { - a::assertClassNotHasStaticAttribute($attribute, $this->actual, $this->description); + a::assertClassNotHasStaticAttribute($attribute, $this->getActualValue(), $this->description); } return $this; @@ -931,7 +802,7 @@ public function subset($array): self } if ($this->modifierCondition) { - a::assertArraySubset($array, $this->actual, $this->dataType, $this->description); + a::assertArraySubset($array, $this->getActualValue(), $this->dataType, $this->description); } else { throw new BadMethodCallException(__METHOD__ . ' does not support negative condition.'); } @@ -951,9 +822,9 @@ public function true(): self } if ($this->modifierCondition) { - a::assertTrue($this->actual, $this->description); + a::assertTrue($this->getActualValue(), $this->description); } else { - a::assertNotTrue($this->actual, $this->description); + a::assertNotTrue($this->getActualValue(), $this->description); } return $this; @@ -1050,4 +921,104 @@ public function withType(): self return $this; } + + /** + * Get the value for an attribute (if specified) otherwise return the subject. + * + * @return mixed + */ + private function getActualValue() + { + if (!$this->attributeName) { + return $this->actual; + } + + return $this->readAttribute(); + } + + /** + * Returns the value of an object's attribute. + * This also works for attributes that are declared protected or private. + * + * @throws InvalidAttributeException if subject doesn't have the named attribute + * + * @return mixed + */ + private function getObjectAttribute() + { + $reflector = new ReflectionObject($this->actual); + + do { + try { + \assert(\is_string($this->attributeName)); + + $attribute = $reflector->getProperty($this->attributeName); + + if (!$attribute || $attribute->isPublic()) { + return $this->actual->{$this->attributeName}; + } + + $attribute->setAccessible(true); + $value = $attribute->getValue($this->actual); + $attribute->setAccessible(false); + + return $value; + } catch (ReflectionException $e) { + } + } while ($reflector = $reflector->getParentClass()); + + throw new InvalidAttributeException("Could not find object property \"{$this->attributeName}\"."); + } + + /** + * Returns the value of a static attribute. + * This also works for attributes that are declared protected or private. + * + * @throws InvalidAttributeException if subject doesn't have the named static attribute + * + * @return mixed + */ + private function getStaticAttribute() + { + $class = new ReflectionClass($this->actual); + + while ($class) { + $attributes = $class->getStaticProperties(); + + \assert(\is_string($this->attributeName)); + + if (\array_key_exists($this->attributeName, $attributes)) { + return $attributes[$this->attributeName]; + } + + $class = $class->getParentClass(); + } + + throw new InvalidAttributeException("Could not find static property \"{$this->attributeName}\"."); + } + + /** + * Returns the value of an attribute of a class or an object. + * This also works for attributes that are declared protected or private. + * + * @throws InvalidSubjectException if subject is not a class name or object + * + * @return mixed + */ + private function readAttribute() + { + if (\is_string($this->actual)) { + if (!class_exists($this->actual)) { + throw new InvalidSubjectException("Could not find class \"{$this->actual}\"."); + } + + return $this->getStaticAttribute(); + } + + if (\is_object($this->actual)) { + return $this->getObjectAttribute(); + } + + throw new InvalidSubjectException('Subject must be either an object or class name.'); + } } diff --git a/test/FunctionsTest.php b/test/FunctionsTest.php index 6141b11..c9b1e16 100644 --- a/test/FunctionsTest.php +++ b/test/FunctionsTest.php @@ -9,6 +9,7 @@ use BeBat\Verify\VerifyDirectory; use BeBat\Verify\VerifyFile; use PHPUnit\Framework\TestCase; +use ReflectionObject; /** * @internal @@ -29,13 +30,33 @@ public function testFunction(string $functionName, string $className) $object = $functionName('no message'); $this->assertInstanceOf($className, $object); - $this->assertAttributeSame('no message', 'actual', $object); + + $reflection = new ReflectionObject($object); + + $actual = $reflection->getProperty('actual'); + $actual->setAccessible(true); + + $this->assertSame('no message', $actual->getValue($object)); + + $actual->setAccessible(false); $object = $functionName('some message', 'message included'); $this->assertInstanceOf($className, $object); - $this->assertAttributeSame('message included', 'actual', $object); - $this->assertAttributeSame('some message', 'description', $object); + + $reflection = new ReflectionObject($object); + + $actual = $reflection->getProperty('actual'); + $description = $reflection->getProperty('description'); + + $actual->setAccessible(true); + $description->setAccessible(true); + + $this->assertSame('message included', $actual->getValue($object)); + $this->assertSame('some message', $description->getValue($object)); + + $actual->setAccessible(false); + $description->setAccessible(false); } /** diff --git a/test/Stub/ExampleChild.php b/test/Stub/ExampleChild.php new file mode 100644 index 0000000..2a393e4 --- /dev/null +++ b/test/Stub/ExampleChild.php @@ -0,0 +1,29 @@ +subject = new Verify('value with case', 'message with case'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_with_case'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'needle with case', - 'attribute_with_case', - 'value with case', - 'message with case', - false, - Mockery::any(), - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->withCase()->contain('needle with case')); - - $this->subject = new Verify('value w/o case', 'message w/o case'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_without_case'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'needle w/o case', - 'attribute_without_case', - 'value w/o case', - 'message w/o case', - true, - Mockery::any(), - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->withoutCase()->contain('needle w/o case')); - } - - /** - * Test Verify::contain() with & without data type for attributes. - * - * @dataProvider attributeContainAssertMethods - * - * @return void - */ - public function testAttribueContainDataType(bool $modifierCondition, string $assertMethod) - { - $this->subject = new Verify('value with type', 'message with type'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_with_type'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'needle with type', - 'attribute_with_type', - 'value with type', - 'message with type', - Mockery::any(), - Mockery::any(), - true - )->once(); - - $this->assertSame($this->subject, $this->subject->withType()->contain('needle with type')); - - $this->subject = new Verify('value w/o type', 'message w/o type'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_without_type'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'needle w/o type', - 'attribute_without_type', - 'value w/o type', - 'message w/o type', - Mockery::any(), - Mockery::any(), - false - )->once(); - - $this->assertSame($this->subject, $this->subject->withoutType()->contain('needle w/o type')); - } - - /** - * Test Verify::contain() with & without object identity for attributes. - * - * @dataProvider attributeContainAssertMethods - * - * @return void - */ - public function testAttribueContainObjectIdentity(bool $modifierCondition, string $assertMethod) - { - $this->subject = new Verify('value with identity', 'message with identity'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_with_identity'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'needle with identity', - 'attribute_with_identity', - 'value with identity', - 'message with identity', - Mockery::any(), - true, - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->withIdentity()->contain('needle with identity')); - - $this->subject = new Verify('value w/o identity', 'message w/o identity'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_without_identity'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'needle w/o identity', - 'attribute_without_identity', - 'value w/o identity', - 'message w/o identity', - Mockery::any(), - false, - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->withoutIdentity()->contain('needle w/o identity')); - } - /** * Test Verify::attribute(). * @@ -422,216 +278,6 @@ public function testAttribute(bool $modifierCondition, $actualValue, string $ass $this->assertSame($this->subject, $this->subject->attribute('attribute_name')); } - /** - * Test negative assertions for object attributes. - * - * @param mixed $expectedValue - * - * @dataProvider attributeMethods - * - * @return void - */ - public function testAttributeAssertions( - bool $modifierCondition, - string $verifyMethod, - string $assertMethod, - $expectedValue = 'some value' - ) { - $this->setModifierCondition($modifierCondition); - - $this->subject->attributeNamed('my_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with($expectedValue, 'my_attribute', 'actual value', 'some message') - ->once(); - - $this->assertSame($this->subject, $this->subject->{$verifyMethod}($expectedValue)); - } - - /** - * Test Verify::contain() basic case for attributes. - * - * @dataProvider attributeContainAssertMethods - * - * @return void - */ - public function testAttributeContain(bool $modifierCondition, string $assertMethod) - { - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_name'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with('needle', 'attribute_name', 'actual value', 'some message', Mockery::any(), Mockery::any(), Mockery::any()) - ->once(); - - $this->assertSame($this->subject, $this->subject->contain('needle')); - } - - /** - * Test Verify::containOnly() for object attributes. - * - * @dataProvider attributeContainOnlyAssertMethods - * - * @return void - */ - public function testAttributeContainOnly(bool $modifierCondition, string $assertMethod) - { - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('attribute_name'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with('data type', 'attribute_name', 'actual value', null, 'some message') - ->once(); - - $this->assertSame($this->subject, $this->subject->containOnly('data type')); - } - - /** - * Test Verify::equalTo() for attributes. - * - * @dataProvider attributeEqualToAssertMethods - * - * @return void - */ - public function testAttributeEqualTo(bool $modifierCondition, string $assertMethod) - { - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('my_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'expected value', - 'my_attribute', - 'actual value', - 'some message', - Mockery::any(), - Mockery::any(), - Mockery::any(), - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->equalTo('expected value')); - } - - /** - * Test Verify::equalTo() for attributes with or without case sensitivity. - * - * @dataProvider attributeEqualToAssertMethods - * - * @return void - */ - public function testAttributeEqualToCaseSensitive(bool $modifierCondition, string $assertMethod) - { - $this->subject = new Verify('actual with case', 'message with case'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('case_sensitive_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'expected with case', - 'case_sensitive_attribute', - 'actual with case', - 'message with case', - Mockery::any(), - Mockery::any(), - Mockery::any(), - false - )->once(); - - $this->assertSame($this->subject, $this->subject->withCase()->equalTo('expected with case')); - - $this->subject = new Verify('actual w/o case', 'message w/o case'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('uncase_sensitive_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'expected w/o case', - 'uncase_sensitive_attribute', - 'actual w/o case', - 'message w/o case', - Mockery::any(), - Mockery::any(), - Mockery::any(), - true - )->once(); - - $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('expected w/o case')); - } - - /** - * Test Verify::equalTo() for attributes with some float delta. - * - * @dataProvider attributeEqualToAssertMethods - * - * @return void - */ - public function testAttributeEqualToFloatDelta(bool $modifierCondition, string $assertMethod) - { - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('my_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'expected value', - 'my_attribute', - 'actual value', - 'some message', - 1.62, - Mockery::any(), - Mockery::any(), - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->within(1.62)->equalTo('expected value')); - } - - /** - * Test Verify::equalTo() for attributes with or without order. - * - * @dataProvider attributeEqualToAssertMethods - * - * @return void - */ - public function testAttributeEqualToOrder(bool $modifierCondition, string $assertMethod) - { - $this->subject = new Verify('actual with order', 'message with order'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('ordered_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'expected with order', - 'ordered_attribute', - 'actual with order', - 'message with order', - Mockery::any(), - Mockery::any(), - false, - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->withOrder()->equalTo('expected with order')); - - $this->subject = new Verify('actual w/o order', 'message w/o order'); - $this->setModifierCondition($modifierCondition); - $this->subject->attributeNamed('unordered_attribute'); - - $this->mockAssert->shouldReceive($assertMethod) - ->with( - 'expected w/o order', - 'unordered_attribute', - 'actual w/o order', - 'message w/o order', - Mockery::any(), - Mockery::any(), - true, - Mockery::any() - )->once(); - - $this->assertSame($this->subject, $this->subject->withoutOrder()->equalTo('expected w/o order')); - } - /** * Test exception for invalid conjunction. * @@ -641,7 +287,6 @@ public function testConjunctionException() { $this->expectException(BadMethodCallException::class); $this->subject->some_invalid_conjunction(); - $this->assertAttributeSame(null, 'modifierCondition', $this->subject); } /** @@ -655,14 +300,21 @@ public function testConjunctions() Verify::$negativeConjunctions = ['negative_conjunction']; Verify::$neutralConjunctions = ['neutral_conjunction']; + $reflection = new ReflectionObject($this->subject); + + $condition = $reflection->getProperty('modifierCondition'); + $condition->setAccessible(true); + $this->assertSame($this->subject, $this->subject->neutral_conjunction()); - $this->assertAttributeSame(null, 'modifierCondition', $this->subject); + $this->assertNull($condition->getValue($this->subject)); $this->assertSame($this->subject, $this->subject->positive_conjunction()); - $this->assertAttributeSame(true, 'modifierCondition', $this->subject); + $this->assertTrue($condition->getValue($this->subject)); $this->assertSame($this->subject, $this->subject->negative_conjunction()); - $this->assertAttributeSame(false, 'modifierCondition', $this->subject); + $this->assertFalse($condition->getValue($this->subject)); + + $condition->setAccessible(false); } /** @@ -1020,6 +672,67 @@ public function testEqualToXmlStructure() $this->assertSame($this->subject, $this->subject->withoutAttributes()->equalToXmlStructure($expected)); } + /** + * Test reading attribute values. + * + * @param class-string|object $subject + * + * @dataProvider attributeValues + * + * @return void + */ + public function testGetAttributeValue($subject, string $attributeName, string $attributeValue) + { + $this->subject = new Verify($subject); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertTrue') + ->with($attributeValue, Mockery::any()) + ->once(); + + $this->assertSame($this->subject, $this->subject->attributeNamed($attributeName)->true()); + } + + /** + * Test trying to read an invalid attribute will throw an exception. + * + * @param class-string|object $subject + * + * @dataProvider invalidAttributes + * + * @return void + */ + public function testMissingAttributeThrowsException($subject, string $exceptionMessage) + { + $this->subject = new Verify($subject); + $this->setModifierCondition(true); + + $this->expectException(InvalidAttributeException::class); + $this->expectExceptionMessage($exceptionMessage); + + $this->subject->attributeNamed('some_attribute')->true(); + } + + /** + * Test validation of subject when trying to read an attribute. + * + * @param mixed $subject + * + * @dataProvider invalidSubjects + * + * @return void + */ + public function testReadAttribueThrowsException($subject, string $exceptionMessage) + { + $this->subject = new Verify($subject); + $this->setModifierCondition(true); + + $this->expectException(InvalidSubjectException::class); + $this->expectExceptionMessage($exceptionMessage); + + $this->subject->attributeNamed('some_attribute')->true(); + } + /** * Test Verify::subset(). * From 731f89d5ffdb50872eb58a2e97e548b9fb28e0cc Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Tue, 21 Jul 2020 18:05:18 -0500 Subject: [PATCH 06/14] Add assertIs* type assertions Issue #51 --- src/Verify.php | 220 ++++++++++++++++++++++++++++++++++++++++++++ test/VerifyTest.php | 95 ++++++++++++------- 2 files changed, 284 insertions(+), 31 deletions(-) diff --git a/src/Verify.php b/src/Verify.php index b25bff2..ef66f78 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -84,6 +84,26 @@ public function __get(string $attr): self return $this->attributeNamed($attr); } + /** + * Assert that SUT is or is not an array. + * + * return self + */ + public function array(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsArray($this->getActualValue(), $this->description); + } else { + a::assertIsNotArray($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT does or does not have a given class attribute. * @@ -124,6 +144,46 @@ public function attributeNamed(string $attr): self return $this; } + /** + * Assert that SUT is or is not a boolean. + * + * return self + */ + public function bool(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsBool($this->getActualValue(), $this->description); + } else { + a::assertIsNotBool($this->getActualValue(), $this->description); + } + + return $this; + } + + /** + * Assert that SUT is or is not callable. + * + * return self + */ + public function callable(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsCallable($this->getActualValue(), $this->description); + } else { + a::assertIsNotCallable($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT does or does not contain a given value. * @@ -434,6 +494,26 @@ public function finite(): self return $this; } + /** + * Assert that SUT is or is not a float. + * + * return self + */ + public function float(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsFloat($this->getActualValue(), $this->description); + } else { + a::assertIsNotFloat($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT is or is not greater than or equal to a given value. * @@ -512,6 +592,26 @@ public function instanceOf(string $class): self return $this; } + /** + * Assert that SUT is or is not an integer. + * + * return self + */ + public function int(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsInt($this->getActualValue(), $this->description); + } else { + a::assertIsNotInt($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT is or is not a given PHP data type. * @@ -532,6 +632,26 @@ public function internalType(string $type): self return $this; } + /** + * Assert that SUT is or is not iterable. + * + * return self + */ + public function iterable(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsIterable($this->getActualValue(), $this->description); + } else { + a::assertIsNotIterable($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT is or is not a string containing valid JSON data. */ @@ -710,6 +830,66 @@ public function null(): self return $this; } + /** + * Assert that SUT is or is not numeric. + * + * return self + */ + public function numeric(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsNumeric($this->getActualValue(), $this->description); + } else { + a::assertIsNotNumeric($this->getActualValue(), $this->description); + } + + return $this; + } + + /** + * Assert that SUT is or is not an object. + * + * return self + */ + public function object(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsObject($this->getActualValue(), $this->description); + } else { + a::assertIsNotObject($this->getActualValue(), $this->description); + } + + return $this; + } + + /** + * Assert that SUT is or is not a resource. + * + * return self + */ + public function resource(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsResource($this->getActualValue(), $this->description); + } else { + a::assertIsNotResource($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT does or does not have both the same value and type as a given value. * @@ -750,6 +930,26 @@ public function sameSizeAs($expected): self return $this; } + /** + * Assert that SUT is or is not scalar. + * + * return self + */ + public function scalar(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsScalar($this->getActualValue(), $this->description); + } else { + a::assertIsNotScalar($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT does or does not start with a given value. * @@ -790,6 +990,26 @@ public function staticAttribute(string $attribute): self return $this; } + /** + * Assert that SUT is or is not a string. + * + * return self + */ + public function string(): self + { + if (!isset($this->modifierCondition)) { + throw new MissingConditionException(); + } + + if ($this->modifierCondition) { + a::assertIsString($this->getActualValue(), $this->description); + } else { + a::assertIsNotString($this->getActualValue(), $this->description); + } + + return $this; + } + /** * Assert SUT contains a given subset of values. * diff --git a/test/VerifyTest.php b/test/VerifyTest.php index 1279eee..c5a0e9c 100644 --- a/test/VerifyTest.php +++ b/test/VerifyTest.php @@ -33,41 +33,52 @@ final class VerifyTest extends UnitTestBase public function allMethods(): array { return [ - ['true'], - ['false'], - ['null'], - ['empty'], - ['json'], - ['count', 30], - ['key'], - ['startWith'], - ['endWith'], + ['array'], + ['attribute'], + ['bool'], + ['callable'], ['contain'], ['containOnly'], - ['matchRegExp'], - ['matchFormat'], - ['matchFormatFile'], - ['equalToJsonString'], + ['count', 30], + ['empty'], + ['endWith'], + ['equalTo'], + ['equalToFile'], ['equalToJsonFile'], - ['equalToXmlString'], + ['equalToJsonString'], ['equalToXmlFile'], + ['equalToXmlString'], ['equalToXmlStructure', new DOMElement('foo')], - ['greaterThan'], - ['greaterOrEqualTo'], - ['lessThan'], - ['lessOrEqualTo'], + ['false'], ['finite'], + ['float'], + ['greaterOrEqualTo'], + ['greaterThan'], ['infinite'], + ['instanceOf'], + ['int'], + ['internalType'], + ['iterable'], + ['json'], + ['key'], + ['lessOrEqualTo'], + ['lessThan'], + ['matchFormat'], + ['matchFormatFile'], + ['matchRegExp'], ['nan'], - ['equalTo'], - ['equalToFile'], + ['null'], + ['numeric'], + ['object'], + ['resource'], ['sameAs'], ['sameSizeAs'], - ['subset'], - ['instanceOf'], - ['internalType'], - ['attribute'], + ['scalar'], + ['startWith'], ['staticAttribute'], + ['string'], + ['subset'], + ['true'], ]; } @@ -190,20 +201,42 @@ public function methodsWithoutNegativeCondition(): array public function noParamMethods(): array { return [ - [true, 'true', 'assertTrue'], - [true, 'false', 'assertFalse'], - [true, 'null', 'assertNull'], + [true, 'array', 'assertIsArray'], + [true, 'bool', 'assertIsBool'], + [true, 'callable', 'assertIsCallable'], [true, 'empty', 'assertEmpty'], + [true, 'false', 'assertFalse'], [true, 'finite', 'assertFinite'], + [true, 'float', 'assertIsFloat'], [true, 'infinite', 'assertInfinite'], - [true, 'nan', 'assertNan'], + [true, 'int', 'assertIsInt'], + [true, 'iterable', 'assertIsIterable'], [true, 'json', 'assertJson'], - [false, 'true', 'assertNotTrue'], - [false, 'false', 'assertNotFalse'], - [false, 'null', 'assertNotNull'], + [true, 'nan', 'assertNan'], + [true, 'null', 'assertNull'], + [true, 'numeric', 'assertIsNumeric'], + [true, 'object', 'assertIsObject'], + [true, 'resource', 'assertIsResource'], + [true, 'scalar', 'assertIsScalar'], + [true, 'string', 'assertIsString'], + [true, 'true', 'assertTrue'], + [false, 'array', 'assertIsNotArray'], + [false, 'bool', 'assertIsNotBool'], + [false, 'callable', 'assertIsNotCallable'], [false, 'empty', 'assertNotEmpty'], + [false, 'false', 'assertNotFalse'], [false, 'finite', 'assertInfinite'], + [false, 'float', 'assertIsNotFloat'], [false, 'infinite', 'assertFinite'], + [false, 'int', 'assertIsNotInt'], + [false, 'iterable', 'assertIsNotIterable'], + [false, 'null', 'assertNotNull'], + [false, 'numeric', 'assertIsNotNumeric'], + [false, 'object', 'assertIsNotObject'], + [false, 'resource', 'assertIsNotResource'], + [false, 'scalar', 'assertIsNotScalar'], + [false, 'string', 'assertIsNotString'], + [false, 'true', 'assertNotTrue'], ]; } From 859be4c520f78b941f75274d9201afefa67b4bbf Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Wed, 22 Jul 2020 18:10:13 -0500 Subject: [PATCH 07/14] Add conditions to equalTo() and contain() for new methods. Issue #51 --- .php_cs | 19 +++--- composer.json | 4 +- phpstan.neon.dist | 1 + src/Verify.php | 156 ++++++++++++++++++++++++++++---------------- test/VerifyTest.php | 153 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 264 insertions(+), 69 deletions(-) diff --git a/.php_cs b/.php_cs index 4b0d21b..665589f 100644 --- a/.php_cs +++ b/.php_cs @@ -8,14 +8,17 @@ $finder = PhpCsFixer\Finder::create() return PhpCsFixer\Config::create() ->setRules([ - '@PHP70Migration' => true, - '@PHP70Migration:risky' => true, - '@PHPUnit60Migration:risky' => true, - '@PhpCsFixer' => true, - '@PhpCsFixer:risky' => true, - 'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], - 'backtick_to_shell_exec' => true, - 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], + '@PHP70Migration' => true, + '@PHP70Migration:risky' => true, + '@PHPUnit60Migration:risky' => true, + '@PhpCsFixer' => true, + '@PhpCsFixer:risky' => true, + 'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => [ + 'default' => 'align_single_space_minimal', + 'operators' => ['||' => null, '&&' => null] + ], 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], 'class_definition' => [ 'single_item_single_line' => true, diff --git a/composer.json b/composer.json index 45068a3..0f07ba0 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,9 @@ "phpstan/phpstan": "^0.12", "phpstan/phpstan-mockery": "^0.12", "phpstan/phpstan-phpunit": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12" + "phpstan/phpstan-strict-rules": "^0.12", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3" }, "suggest": { "codeception/specify": "Highly readable test code blocks for PHPUnit and Codeception" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index a49084b..00e8b0b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -23,5 +23,6 @@ parameters: - message: '/Call to an undefined method BeBat\\Verify\\Verify::[a-z_]+_conjunction\(\)/' path: %currentWorkingDirectory%/test/VerifyTest.php + - '/Mockery\\LegacyMockInterface::shouldNotReceive/' - '/Mockery\\LegacyMockInterface::shouldReceive/' - '/Mockery\\HigherOrderMessage::with/' diff --git a/src/Verify.php b/src/Verify.php index ef66f78..a4bb160 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -86,8 +86,6 @@ public function __get(string $attr): self /** * Assert that SUT is or is not an array. - * - * return self */ public function array(): self { @@ -146,8 +144,6 @@ public function attributeNamed(string $attr): self /** * Assert that SUT is or is not a boolean. - * - * return self */ public function bool(): self { @@ -166,8 +162,6 @@ public function bool(): self /** * Assert that SUT is or is not callable. - * - * return self */ public function callable(): self { @@ -195,24 +189,46 @@ public function contain($needle): self throw new MissingConditionException(); } + $value = $this->getActualValue(); + if ($this->modifierCondition) { - a::assertContains( - $needle, - $this->getActualValue(), - $this->description, - $this->ignoreCase, - $this->objectIdentity, - $this->dataType - ); + if (\is_string($value) && method_exists(a::class, 'assertStringContainsString')) { + if ($this->ignoreCase) { + a::assertStringContainsStringIgnoringCase($needle, $value, $this->description); + } else { + a::assertStringContainsString($needle, $value, $this->description); + } + } elseif (((\is_object($needle) && !$this->objectIdentity) || !$this->dataType) && method_exists(a::class, 'assertContainsEquals')) { + a::assertContainsEquals($needle, $value, $this->description); + } else { + a::assertContains( + $needle, + $value, + $this->description, + $this->ignoreCase, + $this->objectIdentity, + $this->dataType + ); + } } else { - a::assertNotContains( - $needle, - $this->getActualValue(), - $this->description, - $this->ignoreCase, - $this->objectIdentity, - $this->dataType - ); + if (\is_string($value) && method_exists(a::class, 'assertStringNotContainsString')) { + if ($this->ignoreCase) { + a::assertStringNotContainsStringIgnoringCase($needle, $value, $this->description); + } else { + a::assertStringNotContainsString($needle, $value, $this->description); + } + } elseif (((\is_object($needle) && !$this->objectIdentity) || !$this->dataType) && method_exists(a::class, 'assertNotContainsEquals')) { + a::assertNotContainsEquals($needle, $value, $this->description); + } else { + a::assertNotContains( + $needle, + $this->getActualValue(), + $this->description, + $this->ignoreCase, + $this->objectIdentity, + $this->dataType + ); + } } return $this; @@ -311,26 +327,68 @@ public function equalTo($expected): self throw new MissingConditionException(); } + $value = $this->getActualValue(); + if ($this->modifierCondition) { - a::assertEquals( - $expected, - $this->getActualValue(), - $this->description, - $this->floatDelta, - $this->maxDepth, - $this->ignoreOrder, - $this->ignoreCase - ); + if ( + is_numeric($value) && + $this->floatDelta !== 0.0 && + method_exists(a::class, 'assertEqualsWithDelta') + ) { + a::assertEqualsWithDelta($expected, $value, $this->floatDelta, $this->description); + } elseif ( + (\is_array($value) || \is_object($value)) && + $this->ignoreOrder && + method_exists(a::class, 'assertEqualsCanonicalizing') + ) { + a::assertEqualsCanonicalizing($expected, $value, $this->description); + } elseif ( + \is_string($value) && + $this->ignoreCase && + method_exists(a::class, 'assertEqualsIgnoringCase') + ) { + a::assertEqualsIgnoringCase($expected, $value, $this->description); + } else { + a::assertEquals( + $expected, + $value, + $this->description, + $this->floatDelta, + $this->maxDepth, + $this->ignoreOrder, + $this->ignoreCase + ); + } } else { - a::assertNotEquals( - $expected, - $this->getActualValue(), - $this->description, - $this->floatDelta, - $this->maxDepth, - $this->ignoreOrder, - $this->ignoreCase - ); + if ( + is_numeric($value) && + $this->floatDelta !== 0.0 && + method_exists(a::class, 'assertNotEqualsWithDelta') + ) { + a::assertNotEqualsWithDelta($expected, $value, $this->floatDelta, $this->description); + } elseif ( + (\is_array($value) || \is_object($value)) && + $this->ignoreOrder && + method_exists(a::class, 'assertNotEqualsCanonicalizing') + ) { + a::assertNotEqualsCanonicalizing($expected, $value, $this->description); + } elseif ( + \is_string($value) && + $this->ignoreCase && + method_exists(a::class, 'assertNotEqualsIgnoringCase') + ) { + a::assertNotEqualsIgnoringCase($expected, $value, $this->description); + } else { + a::assertNotEquals( + $expected, + $this->getActualValue(), + $this->description, + $this->floatDelta, + $this->maxDepth, + $this->ignoreOrder, + $this->ignoreCase + ); + } } return $this; @@ -496,8 +554,6 @@ public function finite(): self /** * Assert that SUT is or is not a float. - * - * return self */ public function float(): self { @@ -594,8 +650,6 @@ public function instanceOf(string $class): self /** * Assert that SUT is or is not an integer. - * - * return self */ public function int(): self { @@ -634,8 +688,6 @@ public function internalType(string $type): self /** * Assert that SUT is or is not iterable. - * - * return self */ public function iterable(): self { @@ -832,8 +884,6 @@ public function null(): self /** * Assert that SUT is or is not numeric. - * - * return self */ public function numeric(): self { @@ -852,8 +902,6 @@ public function numeric(): self /** * Assert that SUT is or is not an object. - * - * return self */ public function object(): self { @@ -872,8 +920,6 @@ public function object(): self /** * Assert that SUT is or is not a resource. - * - * return self */ public function resource(): self { @@ -932,8 +978,6 @@ public function sameSizeAs($expected): self /** * Assert that SUT is or is not scalar. - * - * return self */ public function scalar(): self { @@ -992,8 +1036,6 @@ public function staticAttribute(string $attribute): self /** * Assert that SUT is or is not a string. - * - * return self */ public function string(): self { @@ -1032,8 +1074,6 @@ public function subset($array): self /** * Assert that SUT is or is not true. - * - * return self */ public function true(): self { diff --git a/test/VerifyTest.php b/test/VerifyTest.php index c5a0e9c..5ab3207 100644 --- a/test/VerifyTest.php +++ b/test/VerifyTest.php @@ -10,6 +10,7 @@ use BeBat\Verify\Verify; use DOMElement; use Mockery; +use phpmock\mockery\PHPMockery; use ReflectionObject; use stdClass; @@ -88,9 +89,9 @@ public function allMethods(): array public function attributeAssertMethods(): array { return [ - [true, 'SomeClass', 'assertClassHasAttribute'], + [true, 'SomeClass', 'assertClassHasAttribute'], [true, new stdClass(), 'assertObjectHasAttribute'], - [false, 'SomeClass', 'assertClassNotHasAttribute'], + [false, 'SomeClass', 'assertClassNotHasAttribute'], [false, new stdClass(), 'assertObjectNotHasAttribute'], ]; } @@ -766,6 +767,154 @@ public function testReadAttribueThrowsException($subject, string $exceptionMessa $this->subject->attributeNamed('some_attribute')->true(); } + /** + * Test Verify::contains calls to specific assertContains*() methods. + * + * @runInSeparateProcess + * + * @return void + */ + public function testSpecificContainsMethods() + { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + + $this->mockAssert->shouldNotReceive('assertContains'); + $this->mockAssert->shouldNotReceive('assertNotContains'); + + $this->subject = new Verify('a string value', 'contains string in string'); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertStringContainsString') + ->with('case sensitive string', 'a string value', 'contains string in string') + ->once(); + $this->mockAssert->shouldReceive('assertStringContainsStringIgnoringCase') + ->with('case insensitive string', 'a string value', 'contains string in string') + ->once(); + + $this->assertSame($this->subject, $this->subject->withCase()->contain('case sensitive string')); + $this->assertSame($this->subject, $this->subject->withoutCase()->contain('case insensitive string')); + + $needle = new stdClass(); + $this->subject = new Verify(['some', 'value'], 'loose compare objects in array'); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertContainsEquals') + ->with($needle, ['some', 'value'], 'loose compare objects in array') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutIdentity()->contain($needle)); + + $this->subject = new Verify(['different', 'values', '21'], 'loose compare scalar value'); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertContainsEquals') + ->with(21, ['different', 'values', '21'], 'loose compare scalar value') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutType()->contain(21)); + + $this->subject = new Verify('different string value', 'not contains string in string'); + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertStringNotContainsString') + ->with('case sensitive string', 'different string value', 'not contains string in string') + ->once(); + $this->mockAssert->shouldReceive('assertStringNotContainsStringIgnoringCase') + ->with('case insensitive string', 'different string value', 'not contains string in string') + ->once(); + + $this->assertSame($this->subject, $this->subject->withCase()->contain('case sensitive string')); + $this->assertSame($this->subject, $this->subject->withoutCase()->contain('case insensitive string')); + + $needle = new stdClass(); + $this->subject = new Verify(['negative', 'value'], 'loose compare objects in array'); + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertNotContainsEquals') + ->with($needle, ['negative', 'value'], 'loose compare objects in array') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutIdentity()->contain($needle)); + + $this->subject = new Verify(['even', 'more', 'values'], 'loose compare scalar value'); + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertNotContainsEquals') + ->with('value', ['even', 'more', 'values'], 'loose compare scalar value') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutType()->contain('value')); + } + + /** + * Test Verify::equalTo() calls to specific assertEquals*() methods. + * + * @runInSeparateProcess + * + * @return void + */ + public function testSpecificEqualToMethods() + { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + + $this->mockAssert->shouldNotReceive('assertEquals'); + $this->mockAssert->shouldNotReceive('assertNotEquals'); + + $this->subject = new Verify(21, 'numeric value with delta'); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertEqualsWithDelta') + ->with(2.72, 21, 12.12, 'numeric value with delta') + ->once(); + + $this->assertSame($this->subject, $this->subject->within(12.12)->equalTo(2.72)); + + $this->subject = new Verify([3, 2, 1], 'array value without order'); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertEqualsCanonicalizing') + ->with([1, 2, 3], [3, 2, 1], 'array value without order') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutOrder()->equalTo([1, 2, 3])); + + $this->subject = new Verify('a string value', 'string value without case'); + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertEqualsIgnoringCase') + ->with('A STRING VALUE', 'a string value', 'string value without case') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('A STRING VALUE')); + + $this->subject = new Verify(5.2, 'numeric value with delta'); + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertNotEqualsWithDelta') + ->with(84, 5.2, 1.62, 'numeric value with delta') + ->once(); + + $this->assertSame($this->subject, $this->subject->within(1.62)->equalTo(84)); + + $this->subject = new Verify([2, 4, 8], 'array value without order'); + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertNotEqualsCanonicalizing') + ->with([16, 32, 64], [2, 4, 8], 'array value without order') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutOrder()->equalTo([16, 32, 64])); + + $this->subject = new Verify('a different string', 'string value without case'); + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertNotEqualsIgnoringCase') + ->with('yet another string', 'a different string', 'string value without case') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('yet another string')); + } + /** * Test Verify::subset(). * From 7b0fa19052f1bba4c7c21e41029291fadf580539 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Wed, 22 Jul 2020 18:46:26 -0500 Subject: [PATCH 08/14] Add case sensitivity methods for files Issue #51 --- src/Verify.php | 16 ++++++++++++---- src/VerifyFile.php | 16 ++++++++++++---- test/VerifyFileTest.php | 32 ++++++++++++++++++++++++++++++++ test/VerifyTest.php | 31 +++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/Verify.php b/src/Verify.php index a4bb160..57ae864 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -406,11 +406,19 @@ public function equalToFile(string $file): self } if ($this->modifierCondition) { - // $canonicalize hardcoded to false - a::assertStringEqualsFile($file, $this->getActualValue(), $this->description, false, $this->ignoreCase); + if ($this->ignoreCase && method_exists(a::class, 'assertStringEqualsFileIgnoringCase')) { + a::assertStringEqualsFileIgnoringCase($file, $this->getActualValue(), $this->description); + } else { + // $canonicalize hardcoded to false + a::assertStringEqualsFile($file, $this->getActualValue(), $this->description, false, $this->ignoreCase); + } } else { - // $canonicalize hardcoded to false - a::assertStringNotEqualsFile($file, $this->getActualValue(), $this->description, false, $this->ignoreCase); + if ($this->ignoreCase && method_exists(a::class, 'assertStringNotEqualsFileIgnoringCase')) { + a::assertStringNotEqualsFileIgnoringCase($file, $this->getActualValue(), $this->description); + } else { + // $canonicalize hardcoded to false + a::assertStringNotEqualsFile($file, $this->getActualValue(), $this->description, false, $this->ignoreCase); + } } return $this; diff --git a/src/VerifyFile.php b/src/VerifyFile.php index acef89f..396ac42 100644 --- a/src/VerifyFile.php +++ b/src/VerifyFile.php @@ -25,11 +25,19 @@ public function equalTo(string $expected): self } if ($this->modifierCondition) { - // $canonicalize hard coded to false as it has no effect. - a::assertFileEquals($expected, $this->actual, $this->description, false, $this->ignoreCase); + if ($this->ignoreCase && method_exists(a::class, 'assertFileEqualsIgnoringCase')) { + a::assertFileEqualsIgnoringCase($expected, $this->actual, $this->description); + } else { + // $canonicalize hard coded to false as it has no effect. + a::assertFileEquals($expected, $this->actual, $this->description, false, $this->ignoreCase); + } } else { - // $canonicalize hard coded to false as it has no effect. - a::assertFileNotEquals($expected, $this->actual, $this->description, false, $this->ignoreCase); + if ($this->ignoreCase && method_exists(a::class, 'assertFileNotEqualsIgnoringCase')) { + a::assertFileNotEqualsIgnoringCase($expected, $this->actual, $this->description); + } else { + // $canonicalize hard coded to false as it has no effect. + a::assertFileNotEquals($expected, $this->actual, $this->description, false, $this->ignoreCase); + } } return $this; diff --git a/test/VerifyFileTest.php b/test/VerifyFileTest.php index e658a45..ff23c87 100644 --- a/test/VerifyFileTest.php +++ b/test/VerifyFileTest.php @@ -6,6 +6,7 @@ use BeBat\Verify\VerifyFile; use Mockery; +use phpmock\mockery\PHPMockery; /** * @internal @@ -111,6 +112,37 @@ public function testEqualTo(bool $modifierConition, string $assertMethod) $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('expected file w/o case')); } + /** + * Test VerifyFile::equalTo() will call assertFileEqualsIgnoringCase() if available. + * + * @runInSeparateProcess + * + * @return void + */ + public function testEqualToSpecificMethods() + { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + + $this->mockAssert->shouldNotReceive('assertFileEquals'); + $this->mockAssert->shouldNotReceive('assertFileNotEquals'); + + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertFileEqualsIgnoringCase') + ->with('case insensitive filename', 'file under test', 'some message') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('case insensitive filename')); + + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertFileNotEqualsIgnoringCase') + ->with('different insensitive filename', 'file under test', 'some message') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutCase()->equalTo('different insensitive filename')); + } + protected function initSubject() { $this->subject = new VerifyFile($this->defaultActualValue, 'some message'); diff --git a/test/VerifyTest.php b/test/VerifyTest.php index 5ab3207..09473a9 100644 --- a/test/VerifyTest.php +++ b/test/VerifyTest.php @@ -599,6 +599,37 @@ public function testEqualToFileCaseSensitive(bool $modifierCondition, string $as $this->assertSame($this->subject, $this->subject->withoutCase()->equalToFile('file w/o case')); } + /** + * Test Verify::equalToFile() will call assertEqualToFileCaseSensitive() if available. + * + * @runInSeparateProcess + * + * @return void + */ + public function testEqualToFileSpecificMethods() + { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + + $this->mockAssert->shouldNotReceive('assertStringEqualsFile'); + $this->mockAssert->shouldNotReceive('assertStringNotEqualsFile'); + + $this->setModifierCondition(true); + + $this->mockAssert->shouldReceive('assertStringEqualsFileIgnoringCase') + ->with('case insensitive filename', 'actual value', 'some message') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutCase()->equalToFile('case insensitive filename')); + + $this->setModifierCondition(false); + + $this->mockAssert->shouldReceive('assertStringNotEqualsFileIgnoringCase') + ->with('different case insensitive file', 'actual value', 'some message') + ->once(); + + $this->assertSame($this->subject, $this->subject->withoutCase()->equalToFile('different case insensitive file')); + } + /** * Test Verify::equalTo() with some float delta. * From dd2d84373dbe9677d4db4ceb7d16aaf09791c066 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Wed, 22 Jul 2020 19:16:18 -0500 Subject: [PATCH 09/14] Add checks for methods that may not exist in PHPUnit Issue #51 --- src/Verify.php | 54 +++++++++++++++++++++++++++++++++++++++++++ test/UnitTestBase.php | 7 ++++++ test/VerifyTest.php | 7 ++++++ 3 files changed, 68 insertions(+) diff --git a/src/Verify.php b/src/Verify.php index 57ae864..4ccb169 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -93,6 +93,8 @@ public function array(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsArray', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsArray($this->getActualValue(), $this->description); } else { @@ -151,6 +153,8 @@ public function bool(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsBool', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsBool($this->getActualValue(), $this->description); } else { @@ -169,6 +173,8 @@ public function callable(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsCallable', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsCallable($this->getActualValue(), $this->description); } else { @@ -569,6 +575,8 @@ public function float(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsFloat', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsFloat($this->getActualValue(), $this->description); } else { @@ -665,6 +673,8 @@ public function int(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsInt', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsInt($this->getActualValue(), $this->description); } else { @@ -685,6 +695,8 @@ public function internalType(string $type): self throw new MissingConditionException(); } + $this->testForRemovedMethod('assertInternalType', __FUNCTION__); + if ($this->modifierCondition) { a::assertInternalType($type, $this->getActualValue(), $this->description); } else { @@ -703,6 +715,8 @@ public function iterable(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsIterable', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsIterable($this->getActualValue(), $this->description); } else { @@ -899,6 +913,8 @@ public function numeric(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsNumeric', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsNumeric($this->getActualValue(), $this->description); } else { @@ -917,6 +933,8 @@ public function object(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsObject', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsObject($this->getActualValue(), $this->description); } else { @@ -935,6 +953,8 @@ public function resource(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsResource', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsResource($this->getActualValue(), $this->description); } else { @@ -993,6 +1013,8 @@ public function scalar(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsScalar', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsScalar($this->getActualValue(), $this->description); } else { @@ -1051,6 +1073,8 @@ public function string(): self throw new MissingConditionException(); } + $this->testForUnimplementedMethod('assertIsString', __FUNCTION__); + if ($this->modifierCondition) { a::assertIsString($this->getActualValue(), $this->description); } else { @@ -1071,6 +1095,8 @@ public function subset($array): self throw new MissingConditionException(); } + $this->testForRemovedMethod('assertArraySubset', __FUNCTION__); + if ($this->modifierCondition) { a::assertArraySubset($array, $this->getActualValue(), $this->dataType, $this->description); } else { @@ -1289,4 +1315,32 @@ private function readAttribute() throw new InvalidSubjectException('Subject must be either an object or class name.'); } + + /** + * Test if a required PHPUnit method has been removed. + * + * @throws BadMethodCallException if the method is missing + * + * @return void + */ + private function testForRemovedMethod(string $phpunitMethod, string $verifyMethod) + { + if (!method_exists(a::class, $phpunitMethod)) { + throw new BadMethodCallException("The underlying method for {$verifyMethod}() has been removed. You should update your test accordingly."); + } + } + + /** + * Test if a required PHPUnit method comes from a newer version. + * + * @throws BadMethodCallException if the method is missing + * + * @return void + */ + private function testForUnimplementedMethod(string $phpunitMethod, string $verifyMethod) + { + if (!method_exists(a::class, $phpunitMethod)) { + throw new BadMethodCallException("The underlying method for {$verifyMethod}() comes from a newer version of PHPUnit. You should update your project's dependencies."); + } + } } diff --git a/test/UnitTestBase.php b/test/UnitTestBase.php index 45e7266..8f6690d 100644 --- a/test/UnitTestBase.php +++ b/test/UnitTestBase.php @@ -6,6 +6,7 @@ use BeBat\Verify\MissingConditionException; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; +use phpmock\mockery\PHPMockery; use PHPUnit\Framework\TestCase; use ReflectionObject; @@ -48,11 +49,14 @@ public function testMissingConditionException(string $verifyMethod, $value = 'du * Test VerifyFile methods that don't take any value. * * @dataProvider noParamMethods + * @runInSeparateProcess * * @return void */ public function testNoParamMethods(bool $modifierCondition, string $verifyMethod, string $assertMethod) { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + $this->setModifierCondition($modifierCondition); $this->mockAssert->shouldReceive($assertMethod) @@ -68,6 +72,7 @@ public function testNoParamMethods(bool $modifierCondition, string $verifyMethod * @param mixed $expectedValue * * @dataProvider singleParamMethods + * @runInSeparateProcess * * @return void */ @@ -77,6 +82,8 @@ public function testSingleParamMethods( string $assertMethod, $expectedValue = 'some value' ) { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + $this->setModifierCondition($modifierCondition); $this->mockAssert->shouldReceive($assertMethod) diff --git a/test/VerifyTest.php b/test/VerifyTest.php index 09473a9..d0b937b 100644 --- a/test/VerifyTest.php +++ b/test/VerifyTest.php @@ -949,10 +949,14 @@ public function testSpecificEqualToMethods() /** * Test Verify::subset(). * + * @runInSeparateProcess + * * @return void */ public function testSubset() { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + $this->setModifierCondition(true); $this->mockAssert->shouldReceive('assertArraySubset') @@ -986,11 +990,14 @@ public function testSubset() * @param mixed $value * * @dataProvider methodsWithoutNegativeCondition + * @runInSeparateProcess * * @return void */ public function testUnsupportedNegativeCondition(string $methodName, $value = 'dummy value') { + PHPMockery::mock('BeBat\\Verify', 'method_exists')->andReturn(true); + $this->setModifierCondition(false); $this->expectException(BadMethodCallException::class); From 434de2293cdc8d23202ce626d59acdfc81cf1d37 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Wed, 22 Jul 2020 23:15:56 -0500 Subject: [PATCH 10/14] Update README.md Document new methods Note deprecated methods Add section about PHP and PHPUnit compatibility Tweak language around attribute assertions --- README.md | 72 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 59fc0e5..51228ec 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Most of the original work was done by [@DavertMik](http://github.com/DavertMik) # Contents - [Installation](#installation) + - [Compatibility](#compatibility) - [Basic Usage](#basic-usage) - [Alternate Functions](#alternate-functions) - [Conjunctions](#conjunctions) @@ -35,7 +36,17 @@ To install the current version of Verify from [Packagist](https://packagist.org/ composer require --dev bebat/verify ``` -Verify will be added to your `composer.json` under `require-dev` and installed in your `vendor` directory. Verify uses namespaced functions, so to include it in your unit tests you should add `use function` statements to the top of your files: +Verify will be added to your `composer.json` under `require-dev` and installed in your `vendor` directory. + +### Compatibility + +As stated, Verify is built on top of PHPUnit's own assertions. It has been written to be compatibile with any version of PHPUnit from 6.0 through 9.x. That said, some assertions have been removed from later versions of PHPUnit, and others added. Those assertions are noted in documentation below. When using Verify, it is still good practice to declare what version of PHPUnit your project depends on so that there are no surprise compatibility issues. + +In addition, Verify is compatibile with any version of PHP 7. You should have no issues integrating it into your legacy projects. + +## Basic Usage + +Verify uses namespaced functions, so to include it in your unit tests you should add `use function` statements to the top of your files: ```php // assertions for code @@ -46,10 +57,6 @@ use function BeBat\Verify\verify_file; use function BeBat\Verify\verify_directory; ```` -You can then start using it in your unit tests. - -## Basic Usage - To use Verify in your unit tests, call the `verify()` function, followed by one or more conjunction, and then your assertion(s). For example: ```php @@ -138,6 +145,25 @@ verify($value)->is()->null(); verify($value)->is()->empty(); +// Type +verify($object)->is()->instanceOf('ClassName'); +verify($value)->is()->internalType('int'); +// Note: internalType() was deprecated in PHPUnit 8, and removed in version 9 + +// Node: The following assertions were added in PHPUnit 7 +verify($value)->is()->array(); +verify($value)->is()->bool(); +verify($value)->is()->callable(); +verify($value)->is()->float(); +verify($value)->is()->int(); +verify($value)->is()->iterable(); +verify($value)->is()->numeric(); +verify($value)->is()->object(); +verify($value)->is()->resource(); +verify($value)->is()->scalar(); +verify($value)->is()->string(); + + // Numeric Comparison verify($numericValue)->is()->greaterThan($tooSmall); verify($numericValue)->is()->greaterOrEqualTo($min); @@ -167,6 +193,7 @@ verify($arrayValue)->will()->contain('expected value'); verify($arrayValue)->will()->have()->subset($subsetOfValues); // Note: subset() does not support negative assertions +// Note: subset() was deprecated in PHPUnit 8, and removed in version 9 verify($arrayValue)->will()->have()->key('some-key'); @@ -177,15 +204,9 @@ verify($arrayValue)->is()->sameSizeAs($someOtherArray); verify($arrayValue)->will()->containOnly('string'); -// Objects, Classes, and Internal Types -verify($object)->is()->instanceOf('ClassName'); - -verify($value)->is()->internalType('int'); - +// Object & Class Properties verify($object)->has()->attribute('attributeName'); - verify('ClassName')->has()->attribute('attributeName'); - verify('ClassName')->has()->staticAttribute('attributeName'); @@ -229,36 +250,20 @@ verify_directory('/path/to/test/dir')->is()->writable(); ### Attribute Assertions -Verify (and PHPUnit) has the ability to test the value of protected and private object properties (or "attributes"). While this is typically considered a violation of best unit testing practice, there are times when inspecting a protected value can be the simplest way of checking your code. The attribute you wish to check can be tacked on after calling `verify()`, just like if you were accessing it as a public value. For example, if you had an object called `$user` with a private `first_name` property that should be equal to `'Alice'`, you can assert that with the following code: +Verify has the ability to test the value of object and static class properties (or "attributes"), even those that are protected or private. While writing assertions about a subject's internal state is not considered good practice, there are times when inspecting a protected value can be the simplest way of checking your code. The attribute you wish to check can be tacked on after calling `verify()`, just like if you were accessing it as a public value. For example, if you had an object called `$user` with a private `first_name` property that should be equal to `'Alice'`, you can assert that with the following code: ```php verify($user)->first_name->is()->equalTo('Alice'); ``` -The following subset of assertions support checking attribute values: +A similar assertion about a class's static properties might look like the following: ```php -verify($obj)->attribute_name->is()->equalTo('Some Value'); - -verify($obj)->attribute_name->does()->contain('Val'); - -verify($obj)->array_attribute->will()->have()->count(5); - -verify($obj)->attribute_name->will()->be()->empty(); - -verify($obj)->numeric_attribute->is()->greaterThan(0); -verify($obj)->numeric_attribute->is()->greaterOrEqualTo(1); -verify($obj)->numeric_attribute->is()->lessThan(10); -verify($obj)->numeric_attribute->is()->lessOrEqualTo(9.99); - -verify($obj)->attribute_name->is()->instanceOf('GoodClass'); -verify($obj)->attribute_name->is()->internalType('string'); - -verify($obj)->object_attriute->is()->sameAs($validObject); - -verify($obj)->array_attribute->will()->containOnly('bool'); +verify(Model::class)->dbc->is()->resource(); ``` +All of Verify's code assertions should be compatible with reading object or class attributes. + If you would rather explicitly identify your attribute/property, you can do so with the `attributeNamed()` method: ```php @@ -300,6 +305,7 @@ verify(['1', '2'])->withoutType()->will()->contain(1); verify(['1', '2', '3'])->withType()->has()->subset(['1', '3']); verify(['1', '2', '3'])->withoutType()->has()->subset([1, 3]); +// Note: subset() was deprecated in PHPUnit 8, and removed in version 9 // Whether to check element attributes when comparing XML documents verify($domDocument)->withAttributes()->is()->equalToXmlStructure($validDocument); From af31c2c0efb2296190190937d7bd61e62add91c4 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Wed, 22 Jul 2020 23:27:27 -0500 Subject: [PATCH 11/14] Reuse existing $value instead of duplicate call Issue #43 --- src/Verify.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Verify.php b/src/Verify.php index 4ccb169..529f3db 100644 --- a/src/Verify.php +++ b/src/Verify.php @@ -228,7 +228,7 @@ public function contain($needle): self } else { a::assertNotContains( $needle, - $this->getActualValue(), + $value, $this->description, $this->ignoreCase, $this->objectIdentity, @@ -387,7 +387,7 @@ public function equalTo($expected): self } else { a::assertNotEquals( $expected, - $this->getActualValue(), + $value, $this->description, $this->floatDelta, $this->maxDepth, From 4199fc1975c0fa2ba299b9cab456d6bfdf1beaf4 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Thu, 23 Jul 2020 00:26:04 -0500 Subject: [PATCH 12/14] Lord, how long has that been broken? Issue #50 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e20ad9d..8d1e766 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,9 +72,9 @@ install: - travis_retry composer install --dev --no-interaction --prefer-dist script: - - if [$TEST_SUITE == "static"]; then composer style:check; fi - - if [$TEST_SUITE == "static"]; then composer test:static; fi - - if [$TEST_SUITE == "unit"]; then composer test:coverage; fi + - if [ $TEST_SUITE == "static" ]; then composer style:check; fi + - if [ $TEST_SUITE == "static" ]; then composer test:static; fi + - if [ $TEST_SUITE == "unit" ]; then composer test:coverage; fi after_success: - bash <(curl -s https://codecov.io/bash) From 0e685c59e9ef2304f117881f09a3ccf9e3a2ddfa Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Thu, 23 Jul 2020 10:21:18 -0500 Subject: [PATCH 13/14] Fix compatibility with PHP 7.0 Add PHPStan configs for PHPUnit 7 & 9 Update Travis CI badge for .com Issues #50, #48, #51 --- .php_cs | 1 - .travis.yml | 49 ++++++++++++++++--------------- README.md | 2 +- phpstan.phpunit7.neon | 25 ++++++++++++++++ phpstan.phpunit9.neon | 42 ++++++++++++++++++++++++++ src/MissingConditionException.php | 2 +- 6 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 phpstan.phpunit7.neon create mode 100644 phpstan.phpunit9.neon diff --git a/.php_cs b/.php_cs index 665589f..df4cb25 100644 --- a/.php_cs +++ b/.php_cs @@ -35,7 +35,6 @@ return PhpCsFixer\Config::create() 'no_php4_constructor' => true, 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], 'no_unset_on_property' => false, - 'nullable_type_declaration_for_default_null_value' => true, 'ordered_class_elements' => ['sortAlgorithm' => 'alpha'], 'ordered_imports' => ['imports_order' => ['const', 'class', 'function']], 'phpdoc_line_span' => ['const' => 'single', 'property' => 'single'], diff --git a/.travis.yml b/.travis.yml index 8d1e766..cd2fd36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,64 +1,64 @@ language: php php: - - 7 + - 7.0 - 7.1 - 7.2 - 7.3 - 7.4 env: - - PHPUNIT_VERSION=6.0 TEST_SUITE=unit - - PHPUNIT_VERSION=7.0 TEST_SUITE=static - - PHPUNIT_VERSION=7.0 TEST_SUITE=unit - - PHPUNIT_VERSION=8.0 TEST_SUITE=static - - PHPUNIT_VERSION=8.0 TEST_SUITE=unit - - PHPUNIT_VERSION=9.0 TEST_SUITE=static - - PHPUNIT_VERSION=9.0 TEST_SUITE=unit + - PHPUNIT_VERSION=6 TEST_SUITE=unit + - PHPUNIT_VERSION=7 TEST_SUITE=static + - PHPUNIT_VERSION=7 TEST_SUITE=unit + - PHPUNIT_VERSION=8 TEST_SUITE=static + - PHPUNIT_VERSION=8 TEST_SUITE=unit + - PHPUNIT_VERSION=9 TEST_SUITE=static + - PHPUNIT_VERSION=9 TEST_SUITE=unit matrix: exclude: # PHP 7.0 - php: 7 - env: PHPUNIT_VERSION=7.0 TEST_SUITE=static + env: PHPUNIT_VERSION=7 TEST_SUITE=static - php: 7 - env: PHPUNIT_VERSION=7.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=7 TEST_SUITE=unit - php: 7 - env: PHPUNIT_VERSION=8.0 TEST_SUITE=static + env: PHPUNIT_VERSION=8 TEST_SUITE=static - php: 7 - env: PHPUNIT_VERSION=8.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=8 TEST_SUITE=unit - php: 7 - env: PHPUNIT_VERSION=9.0 TEST_SUITE=static + env: PHPUNIT_VERSION=9 TEST_SUITE=static - php: 7 - env: PHPUNIT_VERSION=9.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=9 TEST_SUITE=unit # PHP 7.1 - php: 7.1 - env: PHPUNIT_VERSION=8.0 TEST_SUITE=static + env: PHPUNIT_VERSION=8 TEST_SUITE=static - php: 7.1 - env: PHPUNIT_VERSION=8.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=8 TEST_SUITE=unit - php: 7.1 - env: PHPUNIT_VERSION=9.0 TEST_SUITE=static + env: PHPUNIT_VERSION=9 TEST_SUITE=static - php: 7.1 - env: PHPUNIT_VERSION=9.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=9 TEST_SUITE=unit # PHP 7.2 - php: 7.2 - env: PHPUNIT_VERSION=9.0 TEST_SUITE=static + env: PHPUNIT_VERSION=9 TEST_SUITE=static - php: 7.2 - env: PHPUNIT_VERSION=9.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=9 TEST_SUITE=unit # PHP 7.3 - php: 7.3 - env: PHPUNIT_VERSION=6.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=6 TEST_SUITE=unit # PHP 7.4 - php: 7.4 - env: PHPUNIT_VERSION=6.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=6 TEST_SUITE=unit - php: 7.4 - env: PHPUNIT_VERSION=7.0 TEST_SUITE=static + env: PHPUNIT_VERSION=7 TEST_SUITE=static - php: 7.4 - env: PHPUNIT_VERSION=7.0 TEST_SUITE=unit + env: PHPUNIT_VERSION=7 TEST_SUITE=unit sudo: false @@ -68,6 +68,7 @@ before_install: install: - if [ -e composer.lock ]; then rm -rf composer.lock vendor; fi + - if [ -e phpstan.phpunit${PHPUNIT_VERSION}.neon ]; then cp phpstan.phpunit${PHPUNIT_VERSION}.neon phpstan.neon; fi - composer require phpunit/phpunit:^$PHPUNIT_VERSION --update-no-dev --no-interaction --prefer-dist --no-progress --no-suggest --update-with-all-dependencies - travis_retry composer install --dev --no-interaction --prefer-dist diff --git a/README.md b/README.md index 51228ec..3d294f0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ With BDD assertions influenced by Chai, Jasmine, and RSpec your assertions would [![Latest Stable Version](https://img.shields.io/packagist/v/bebat/verify.svg?style=plastic)](https://packagist.org/packages/bebat/verify) [![Total Downloads](https://img.shields.io/packagist/dt/bebat/verify.svg?style=plastic)](https://packagist.org/packages/bebat/verify) [![License](https://img.shields.io/packagist/l/bebat/verify.svg?style=plastic)](https://packagist.org/packages/bebat/verify) -[![Build Status](https://img.shields.io/travis/bbatsche/Verify.svg?style=plastic)](https://travis-ci.org/bbatsche/Verify) +[![Build Status](https://img.shields.io/travis/com/bbatsche/Verify.svg?style=plastic)](https://travis-ci.com/bbatsche/Verify) [![Code Coverage](https://codecov.io/gh/bbatsche/Verify/branch/master/graph/badge.svg)](https://codecov.io/gh/bbatsche/Verify) Most of the original work was done by [@DavertMik](http://github.com/DavertMik) and [@Ragazzo](http://github.com/Ragazzo) in the [Codeception/Verify](http://github.com/Codeception/Verify) repo. This fork was created to address some issues and then expand the API & feature set. diff --git a/phpstan.phpunit7.neon b/phpstan.phpunit7.neon new file mode 100644 index 0000000..389116d --- /dev/null +++ b/phpstan.phpunit7.neon @@ -0,0 +1,25 @@ +# Ignorable errors specific to PHPUnit 7 + +includes: + - phpstan.neon.dist + +parameters: + ignoreErrors: + - + message: '/Call to an undefined static method .+Assert::assertContainsEquals/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Call to an undefined static method .+Assert::assertNotContainsEquals/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Call to an undefined static method .+Assert::assertStringEqualsFileIgnoringCase/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Call to an undefined static method .+Assert::assertStringNotEqualsFileIgnoringCase/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Call to an undefined static method .+Assert::assertFileEqualsIgnoringCase/' + path: %currentWorkingDirectory%/src/VerifyFile.php + - + message: '/Call to an undefined static method .+Assert::assertFileNotEqualsIgnoringCase/' + path: %currentWorkingDirectory%/src/VerifyFile.php diff --git a/phpstan.phpunit9.neon b/phpstan.phpunit9.neon new file mode 100644 index 0000000..6c17f56 --- /dev/null +++ b/phpstan.phpunit9.neon @@ -0,0 +1,42 @@ +# Ignorable errors specific to PHPUnit 7 + +includes: + - phpstan.neon.dist + +parameters: + ignoreErrors: + - + message: '/Call to an undefined static method .+Assert::assertInternalType/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Call to an undefined static method .+Assert::assertNotInternalType/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Call to an undefined static method .+Assert::assertArraySubset/' + path: %currentWorkingDirectory%/src/Verify.php + + - + message: '/Assert::assertContains\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Assert::assertNotContains\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Assert::assertEquals\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Assert::assertNotEquals\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Assert::assertStringEqualsFile\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/Verify.php + - + message: '/Assert::assertStringNotEqualsFile\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/Verify.php + + - + message: '/Assert::assertFileEquals\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/VerifyFile.php + - + message: '/Assert::assertFileNotEquals\(\) invoked with \d+ parameters, \d+-\d+ required/' + path: %currentWorkingDirectory%/src/VerifyFile.php diff --git a/src/MissingConditionException.php b/src/MissingConditionException.php index 4397f3a..8a67925 100644 --- a/src/MissingConditionException.php +++ b/src/MissingConditionException.php @@ -9,7 +9,7 @@ class MissingConditionException extends BadMethodCallException { - public function __construct(int $code = 0, ?Throwable $previous = null) + public function __construct(int $code = 0, Throwable $previous = null) { parent::__construct('Assertions must be prefaced by some condition method, such as "is()", "will()", "doesNot()", "isNot()", etc.', $code, $previous); } From 84f83ae7cb62e36f7426f642888378b72cc50eb6 Mon Sep 17 00:00:00 2001 From: Ben Batschelet Date: Thu, 23 Jul 2020 10:24:54 -0500 Subject: [PATCH 14/14] Fix Travis build matrix Issue #49 --- .travis.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd2fd36..a2bc4b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,17 +19,17 @@ env: matrix: exclude: # PHP 7.0 - - php: 7 + - php: 7.0 env: PHPUNIT_VERSION=7 TEST_SUITE=static - - php: 7 + - php: 7.0 env: PHPUNIT_VERSION=7 TEST_SUITE=unit - - php: 7 + - php: 7.0 env: PHPUNIT_VERSION=8 TEST_SUITE=static - - php: 7 + - php: 7.0 env: PHPUNIT_VERSION=8 TEST_SUITE=unit - - php: 7 + - php: 7.0 env: PHPUNIT_VERSION=9 TEST_SUITE=static - - php: 7 + - php: 7.0 env: PHPUNIT_VERSION=9 TEST_SUITE=unit # PHP 7.1 @@ -69,7 +69,7 @@ before_install: install: - if [ -e composer.lock ]; then rm -rf composer.lock vendor; fi - if [ -e phpstan.phpunit${PHPUNIT_VERSION}.neon ]; then cp phpstan.phpunit${PHPUNIT_VERSION}.neon phpstan.neon; fi - - composer require phpunit/phpunit:^$PHPUNIT_VERSION --update-no-dev --no-interaction --prefer-dist --no-progress --no-suggest --update-with-all-dependencies + - composer require phpunit/phpunit:^${PHPUNIT_VERSION}.0 --update-no-dev --no-interaction --prefer-dist --no-progress --no-suggest --update-with-all-dependencies - travis_retry composer install --dev --no-interaction --prefer-dist script: