diff --git a/php/README.md b/php/README.md index 0580b4a1..a2d15aa4 100644 --- a/php/README.md +++ b/php/README.md @@ -7,35 +7,14 @@ GildedRose Kata. The kata uses: -- [PHP 7.3 or 7.4 or 8.0+](https://www.php.net/downloads.php) +- [PHP 8.0+](https://www.php.net/downloads.php) - [Composer](https://getcomposer.org) - -Recommended: - - [Git](https://git-scm.com/downloads) -Clone the repository - -```sh -git clone git@github.com:emilybache/GildedRose-Refactoring-Kata.git -``` - -or - -```shell script -git clone https://github.com/emilybache/GildedRose-Refactoring-Kata.git -``` - -Install all the dependencies using composer - -```shell script -cd ./GildedRose-Refactoring-Kata/php -composer install -``` ## Dependencies -The project uses composer to install: +The project used composer to install: - [PHPUnit](https://phpunit.de/) - [ApprovalTests.PHP](https://github.com/approvals/ApprovalTests.php) @@ -46,19 +25,49 @@ The project uses composer to install: ## Folders - `src` - contains the two classes: - - `Item.php` - this class should not be changed - - `GildedRose.php` - this class needs to be refactored, and the new feature added -- `tests` - contains the tests + - `Item.php` - this class was not changed; + - `GildedRose.php` - this class was refactored, and the new feature added; +- `tests` - contains the tests: - `GildedRoseTest.php` - starter test. - - Tip: ApprovalTests has been included as a dev dependency, see the PHP version of - the [Theatrical Players Refactoring Kata](https://github.com/emilybache/Theatrical-Players-Refactoring-Kata/) - for an example - `Fixture` - - `texttest_fixture.php` this could be used by an ApprovalTests, or run from the command line + - `texttest_fixture.php` this was used by an ApprovalTests, and run from the command line ## Testing -PHPUnit is configured for testing, a composer script has been provided. To run the unit tests, from the root of the PHP +Tests were written for all the requirement specifications listed in ["Gilded Rose Requirements"](https://github.com/emilybache/GildedRose-Refactoring-Kata/tree/master/GildedRoseRequirements.txt). + +Test methods takes initial (starting) values, that can be changed accordingly. E.g., "31" for sell_in value and "50" for quality value: + +```shell +$items = [new Item('+5 Dexterity Vest', 31, 50)]; +``` +puts them in GildedRose Class updateQuality() method and checks for expected values. E.g., "30" for sell_in value and "49" for quality value: + +```shell +self::assertSame(30, $items[0]->sell_in); +self::assertSame(49, $items[0]->quality); +``` + +Furthermore, where more than one arbitrary arguments are desired for single test, @dataProvider method was used and relevant Scenarios were created. E.g., 'data' array accepts initial values for sell_in and quality and 'expect' array - expected ones. + +```shell +public function qualityNeverNegativeScenario(): array + { + return [ + [[ + 'data' => [ + 'sell_in' => 1, + 'quality' => 0, + ], + 'expect' => [ + 'sell_in' => 0, + 'quality' => 0, + + ] + ]] +``` + +To run the unit tests, from the root of the PHP project run: ```shell script @@ -72,6 +81,14 @@ PHPUnit `composer test` can be run: pu ``` +### Approval Test + +'sell_in' and 'quality' values of GildedRose items for 31 day were generated via terminal command from the root of the PHP project: + +```shell +php fixtures/texttest_fixture.php +``` +and compared to provided ["Approval Test document"](tests/approvals/ApprovalTest.testTestFixture.approved.txt) until data were identical. ### Tests with Coverage Report To run all test and generate a html coverage report run: diff --git a/php/composer.json b/php/composer.json index 71eff6c3..9e569823 100644 --- a/php/composer.json +++ b/php/composer.json @@ -16,7 +16,7 @@ }, "require-dev": { "phpunit/phpunit": "^9.5", - "phpstan/phpstan": "^0.12.85", + "phpstan/phpstan": "^0.12.86", "phpstan/phpstan-phpunit": "^0.12.18", "symplify/easy-coding-standard": "^9.3", "symplify/phpstan-extensions": "^9.3", diff --git a/php/composer.lock b/php/composer.lock index 22e7b9d4..89aa5220 100644 --- a/php/composer.lock +++ b/php/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aaa7d8275c5e59ff696fadc6432010fc", + "content-hash": "530fbe3fa428ed44b7424eef4500d9ef", "packages": [], "packages-dev": [ { @@ -1480,16 +1480,16 @@ }, { "name": "phpstan/phpstan", - "version": "0.12.85", + "version": "0.12.86", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "20e6333c0067875ad7697cd8acdf245c6ef69d03" + "reference": "a84fdc53ecca7643dbc89ef8880d8b393a6c155a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/20e6333c0067875ad7697cd8acdf245c6ef69d03", - "reference": "20e6333c0067875ad7697cd8acdf245c6ef69d03", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a84fdc53ecca7643dbc89ef8880d8b393a6c155a", + "reference": "a84fdc53ecca7643dbc89ef8880d8b393a6c155a", "shasum": "" }, "require": { @@ -1520,7 +1520,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.85" + "source": "https://github.com/phpstan/phpstan/tree/0.12.86" }, "funding": [ { @@ -1536,7 +1536,7 @@ "type": "tidelift" } ], - "time": "2021-04-27T14:13:16+00:00" + "time": "2021-05-08T11:29:01+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -6542,7 +6542,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.3 || ^8.0" + "php": "^8.0" }, "platform-dev": [], "plugin-api-version": "2.0.0" diff --git a/php/src/GildedRose.php b/php/src/GildedRose.php index 760147cf..44c020d6 100644 --- a/php/src/GildedRose.php +++ b/php/src/GildedRose.php @@ -4,7 +4,9 @@ namespace GildedRose; final class GildedRose { - public function __construct(private array $items) + public function __construct( + private array $items + ) { } @@ -17,7 +19,7 @@ final class GildedRose } $disabledNames = ['Aged Brie', 'Backstage passes to a TAFKAL80ETC concert']; - if (in_array($item->name, $disabledNames)) { + if (in_array($item->name, $disabledNames, true)) { if ($item->quality < 50) { $this->increaseQuality($item, 1); if ($item->name === 'Backstage passes to a TAFKAL80ETC concert') { @@ -45,9 +47,9 @@ final class GildedRose if ($item->quality < 50) { $this->increaseQuality($item, 1); } - } else if ($item->name === 'Backstage passes to a TAFKAL80ETC concert') { + } elseif ($item->name === 'Backstage passes to a TAFKAL80ETC concert') { $this->lowerQuality($item, $item->quality); - } else if ($item->quality > 0) { + } elseif ($item->quality > 0) { $this->lowerQuality($item, 1); } } @@ -75,6 +77,6 @@ final class GildedRose private function lowerSellIn(Item $item): void { - $item->sell_in -= 1; + --$item->sell_in; } -} \ No newline at end of file +} diff --git a/php/tests/GildedRoseTest.php b/php/tests/GildedRoseTest.php index e2938576..00b4192f 100644 --- a/php/tests/GildedRoseTest.php +++ b/php/tests/GildedRoseTest.php @@ -36,7 +36,9 @@ class GildedRoseTest extends TestCase self::assertSame(-2, $items[0]->sell_in); } - /** @dataProvider qualityNeverNegativeScenario */ + /** + * @dataProvider qualityNeverNegativeScenario + */ public function testQualityNeverNegative(array $qualityNeverNegativeScenario): void { $items = [new Item('foo', $qualityNeverNegativeScenario['data']['sell_in'], $qualityNeverNegativeScenario['data']['quality'])]; @@ -50,18 +52,35 @@ class GildedRoseTest extends TestCase { return [ [[ - 'data' => ['sell_in' => 1, 'quality' => 0], - 'expect' => ['sell_in' => 0, 'quality' => 0], + 'data' => [ + 'sell_in' => 1, + 'quality' => 0, + ], + 'expect' => [ + 'sell_in' => 0, + 'quality' => 0, + + ], ]], [[ - 'data' => ['sell_in' => -1, 'quality' => 1], - 'expect' => ['sell_in' => -2, 'quality' => 0], - ]] + 'data' => [ + 'sell_in' => -1, + 'quality' => 1, + ], + 'expect' => [ + 'sell_in' => -2, + 'quality' => 0, + + ], + ]], ]; } + /** end of QualityNeverNegativeScenario */ - /** @dataProvider agedBrieScenario */ + /** + * @dataProvider agedBrieScenario + */ public function testAgedBrieQualityIncreases(array $agedBrieScenario): void { $items = [new Item('Aged Brie', $agedBrieScenario['data']['sell_in'], $agedBrieScenario['data']['quality'])]; @@ -75,18 +94,35 @@ class GildedRoseTest extends TestCase { return [ [[ - 'data' => ['sell_in' => 11, 'quality' => 49], - 'expect' => ['sell_in' => 10, 'quality' => 50], + 'data' => [ + 'sell_in' => 11, + 'quality' => 49, + ], + 'expect' => [ + 'sell_in' => 10, + 'quality' => 50, + + ], ]], [[ - 'data' => ['sell_in' => 0, 'quality' => 47], - 'expect' => ['sell_in' => -1, 'quality' => 49], - ]] + 'data' => [ + 'sell_in' => 0, + 'quality' => 47, + ], + 'expect' => [ + 'sell_in' => -1, + 'quality' => 49, + + ], + ]], ]; } + /** end of agedBrieScenario */ - /** @dataProvider sulfurasScenario */ + /** + * @dataProvider sulfurasScenario + */ public function testSulfurasQualityAndSellinStays(array $sulfurasScenario): void { $items = [new Item('Sulfuras, Hand of Ragnaros', $sulfurasScenario['data']['sell_in'], $sulfurasScenario['data']['quality'])]; @@ -100,22 +136,46 @@ class GildedRoseTest extends TestCase { return [ [[ - 'data' => ['sell_in' => 31, 'quality' => 80], - 'expect' => ['sell_in' => 31, 'quality' => 80], + 'data' => [ + 'sell_in' => 31, + 'quality' => 80, + ], + 'expect' => [ + 'sell_in' => 31, + 'quality' => 80, + + ], ]], [[ - 'data' => ['sell_in' => 0, 'quality' => 80], - 'expect' => ['sell_in' => 0, 'quality' => 80], + 'data' => [ + 'sell_in' => 0, + 'quality' => 80, + ], + 'expect' => [ + 'sell_in' => 0, + 'quality' => 80, + + ], ]], [[ - 'data' => ['sell_in' => -1, 'quality' => 80], - 'expect' => ['sell_in' => -1, 'quality' => 80], - ]] + 'data' => [ + 'sell_in' => -1, + 'quality' => 80, + ], + 'expect' => [ + 'sell_in' => -1, + 'quality' => 80, + + ], + ]], ]; } + /** end of sulfurasScenario */ - /** @dataProvider backstagePassScenario */ + /** + * @dataProvider backstagePassScenario + */ public function testBackstagePassQuality(array $backstagePassScenario): void { $items = [new Item('Backstage passes to a TAFKAL80ETC concert', $backstagePassScenario['data']['sell_in'], $backstagePassScenario['data']['quality'])]; @@ -129,26 +189,57 @@ class GildedRoseTest extends TestCase { return [ [[ - 'data' => ['sell_in' => 31, 'quality' => 43], - 'expect' => ['sell_in' => 30, 'quality' => 44], + 'data' => [ + 'sell_in' => 31, + 'quality' => 43, + ], + 'expect' => [ + 'sell_in' => 30, + 'quality' => 44, + + ], ]], [[ - 'data' => ['sell_in' => 10, 'quality' => 44], - 'expect' => ['sell_in' => 9, 'quality' => 46], + 'data' => [ + 'sell_in' => 10, + 'quality' => 44, + ], + 'expect' => [ + 'sell_in' => 9, + 'quality' => 46, + + ], ]], [[ - 'data' => ['sell_in' => 1, 'quality' => 46], - 'expect' => ['sell_in' => 0, 'quality' => 49], + 'data' => [ + 'sell_in' => 1, + 'quality' => 46, + ], + 'expect' => [ + 'sell_in' => 0, + 'quality' => 49, + + ], ]], [[ - 'data' => ['sell_in' => 0, 'quality' => 49], - 'expect' => ['sell_in' => -1, 'quality' => 0], - ]] + 'data' => [ + 'sell_in' => 0, + 'quality' => 49, + ], + 'expect' => [ + 'sell_in' => -1, + 'quality' => 0, + + ], + ]], ]; } + /** end of backstageScenario */ - /** @dataProvider conjuredItemsScenario */ + /** + * @dataProvider conjuredItemsScenario + */ public function testConjuredItems(array $conjuredItemsScenario): void { $items = [new Item('Conjured Mana Cake', $conjuredItemsScenario['data']['sell_in'], $conjuredItemsScenario['data']['quality'])]; @@ -162,14 +253,29 @@ class GildedRoseTest extends TestCase { return [ [[ - 'data' => ['sell_in' => 31, 'quality' => 50], - 'expect' => ['sell_in' => 30, 'quality' => 48], + 'data' => [ + 'sell_in' => 31, + 'quality' => 50, + ], + 'expect' => [ + 'sell_in' => 30, + 'quality' => 48, + + ], ]], [[ - 'data' => ['sell_in' => 0, 'quality' => 48], - 'expect' => ['sell_in' => -1, 'quality' => 44], - ]] + 'data' => [ + 'sell_in' => 0, + 'quality' => 48, + ], + 'expect' => [ + 'sell_in' => -1, + 'quality' => 44, + + ], + ]], ]; } + /** end of conjuredItemsScenario */ -} \ No newline at end of file +}