update README.md

This commit is contained in:
lemoncube1 2021-05-11 22:53:30 +03:00
parent b9ff3e1923
commit 6b46a831ca
5 changed files with 208 additions and 83 deletions

View File

@ -7,35 +7,14 @@ GildedRose Kata.
The kata uses: 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) - [Composer](https://getcomposer.org)
Recommended:
- [Git](https://git-scm.com/downloads) - [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 ## Dependencies
The project uses composer to install: The project used composer to install:
- [PHPUnit](https://phpunit.de/) - [PHPUnit](https://phpunit.de/)
- [ApprovalTests.PHP](https://github.com/approvals/ApprovalTests.php) - [ApprovalTests.PHP](https://github.com/approvals/ApprovalTests.php)
@ -46,19 +25,49 @@ The project uses composer to install:
## Folders ## Folders
- `src` - contains the two classes: - `src` - contains the two classes:
- `Item.php` - this class should not be changed - `Item.php` - this class was not changed;
- `GildedRose.php` - this class needs to be refactored, and the new feature added - `GildedRose.php` - this class was refactored, and the new feature added;
- `tests` - contains the tests - `tests` - contains the tests:
- `GildedRoseTest.php` - starter test. - `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` - `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 ## 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: project run:
```shell script ```shell script
@ -72,6 +81,14 @@ PHPUnit `composer test` can be run:
pu 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 ### Tests with Coverage Report
To run all test and generate a html coverage report run: To run all test and generate a html coverage report run:

View File

@ -16,7 +16,7 @@
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
"phpstan/phpstan": "^0.12.85", "phpstan/phpstan": "^0.12.86",
"phpstan/phpstan-phpunit": "^0.12.18", "phpstan/phpstan-phpunit": "^0.12.18",
"symplify/easy-coding-standard": "^9.3", "symplify/easy-coding-standard": "^9.3",
"symplify/phpstan-extensions": "^9.3", "symplify/phpstan-extensions": "^9.3",

16
php/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "aaa7d8275c5e59ff696fadc6432010fc", "content-hash": "530fbe3fa428ed44b7424eef4500d9ef",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@ -1480,16 +1480,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "0.12.85", "version": "0.12.86",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "20e6333c0067875ad7697cd8acdf245c6ef69d03" "reference": "a84fdc53ecca7643dbc89ef8880d8b393a6c155a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/20e6333c0067875ad7697cd8acdf245c6ef69d03", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/a84fdc53ecca7643dbc89ef8880d8b393a6c155a",
"reference": "20e6333c0067875ad7697cd8acdf245c6ef69d03", "reference": "a84fdc53ecca7643dbc89ef8880d8b393a6c155a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1520,7 +1520,7 @@
"description": "PHPStan - PHP Static Analysis Tool", "description": "PHPStan - PHP Static Analysis Tool",
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan/issues", "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": [ "funding": [
{ {
@ -1536,7 +1536,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2021-04-27T14:13:16+00:00" "time": "2021-05-08T11:29:01+00:00"
}, },
{ {
"name": "phpstan/phpstan-phpunit", "name": "phpstan/phpstan-phpunit",
@ -6542,7 +6542,7 @@
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": "^7.3 || ^8.0" "php": "^8.0"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.0.0" "plugin-api-version": "2.0.0"

View File

@ -4,7 +4,9 @@ namespace GildedRose;
final class 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']; $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) { if ($item->quality < 50) {
$this->increaseQuality($item, 1); $this->increaseQuality($item, 1);
if ($item->name === 'Backstage passes to a TAFKAL80ETC concert') { if ($item->name === 'Backstage passes to a TAFKAL80ETC concert') {
@ -45,9 +47,9 @@ final class GildedRose
if ($item->quality < 50) { if ($item->quality < 50) {
$this->increaseQuality($item, 1); $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); $this->lowerQuality($item, $item->quality);
} else if ($item->quality > 0) { } elseif ($item->quality > 0) {
$this->lowerQuality($item, 1); $this->lowerQuality($item, 1);
} }
} }
@ -75,6 +77,6 @@ final class GildedRose
private function lowerSellIn(Item $item): void private function lowerSellIn(Item $item): void
{ {
$item->sell_in -= 1; --$item->sell_in;
} }
} }

View File

@ -36,7 +36,9 @@ class GildedRoseTest extends TestCase
self::assertSame(-2, $items[0]->sell_in); self::assertSame(-2, $items[0]->sell_in);
} }
/** @dataProvider qualityNeverNegativeScenario */ /**
* @dataProvider qualityNeverNegativeScenario
*/
public function testQualityNeverNegative(array $qualityNeverNegativeScenario): void public function testQualityNeverNegative(array $qualityNeverNegativeScenario): void
{ {
$items = [new Item('foo', $qualityNeverNegativeScenario['data']['sell_in'], $qualityNeverNegativeScenario['data']['quality'])]; $items = [new Item('foo', $qualityNeverNegativeScenario['data']['sell_in'], $qualityNeverNegativeScenario['data']['quality'])];
@ -50,18 +52,35 @@ class GildedRoseTest extends TestCase
{ {
return [ return [
[[ [[
'data' => ['sell_in' => 1, 'quality' => 0], 'data' => [
'expect' => ['sell_in' => 0, 'quality' => 0], 'sell_in' => 1,
'quality' => 0,
],
'expect' => [
'sell_in' => 0,
'quality' => 0,
],
]], ]],
[[ [[
'data' => ['sell_in' => -1, 'quality' => 1], 'data' => [
'expect' => ['sell_in' => -2, 'quality' => 0], 'sell_in' => -1,
]] 'quality' => 1,
],
'expect' => [
'sell_in' => -2,
'quality' => 0,
],
]],
]; ];
} }
/** end of QualityNeverNegativeScenario */ /** end of QualityNeverNegativeScenario */
/** @dataProvider agedBrieScenario */ /**
* @dataProvider agedBrieScenario
*/
public function testAgedBrieQualityIncreases(array $agedBrieScenario): void public function testAgedBrieQualityIncreases(array $agedBrieScenario): void
{ {
$items = [new Item('Aged Brie', $agedBrieScenario['data']['sell_in'], $agedBrieScenario['data']['quality'])]; $items = [new Item('Aged Brie', $agedBrieScenario['data']['sell_in'], $agedBrieScenario['data']['quality'])];
@ -75,18 +94,35 @@ class GildedRoseTest extends TestCase
{ {
return [ return [
[[ [[
'data' => ['sell_in' => 11, 'quality' => 49], 'data' => [
'expect' => ['sell_in' => 10, 'quality' => 50], 'sell_in' => 11,
'quality' => 49,
],
'expect' => [
'sell_in' => 10,
'quality' => 50,
],
]], ]],
[[ [[
'data' => ['sell_in' => 0, 'quality' => 47], 'data' => [
'expect' => ['sell_in' => -1, 'quality' => 49], 'sell_in' => 0,
]] 'quality' => 47,
],
'expect' => [
'sell_in' => -1,
'quality' => 49,
],
]],
]; ];
} }
/** end of agedBrieScenario */ /** end of agedBrieScenario */
/** @dataProvider sulfurasScenario */ /**
* @dataProvider sulfurasScenario
*/
public function testSulfurasQualityAndSellinStays(array $sulfurasScenario): void public function testSulfurasQualityAndSellinStays(array $sulfurasScenario): void
{ {
$items = [new Item('Sulfuras, Hand of Ragnaros', $sulfurasScenario['data']['sell_in'], $sulfurasScenario['data']['quality'])]; $items = [new Item('Sulfuras, Hand of Ragnaros', $sulfurasScenario['data']['sell_in'], $sulfurasScenario['data']['quality'])];
@ -100,22 +136,46 @@ class GildedRoseTest extends TestCase
{ {
return [ return [
[[ [[
'data' => ['sell_in' => 31, 'quality' => 80], 'data' => [
'expect' => ['sell_in' => 31, 'quality' => 80], 'sell_in' => 31,
'quality' => 80,
],
'expect' => [
'sell_in' => 31,
'quality' => 80,
],
]], ]],
[[ [[
'data' => ['sell_in' => 0, 'quality' => 80], 'data' => [
'expect' => ['sell_in' => 0, 'quality' => 80], 'sell_in' => 0,
'quality' => 80,
],
'expect' => [
'sell_in' => 0,
'quality' => 80,
],
]], ]],
[[ [[
'data' => ['sell_in' => -1, 'quality' => 80], 'data' => [
'expect' => ['sell_in' => -1, 'quality' => 80], 'sell_in' => -1,
]] 'quality' => 80,
],
'expect' => [
'sell_in' => -1,
'quality' => 80,
],
]],
]; ];
} }
/** end of sulfurasScenario */ /** end of sulfurasScenario */
/** @dataProvider backstagePassScenario */ /**
* @dataProvider backstagePassScenario
*/
public function testBackstagePassQuality(array $backstagePassScenario): void public function testBackstagePassQuality(array $backstagePassScenario): void
{ {
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', $backstagePassScenario['data']['sell_in'], $backstagePassScenario['data']['quality'])]; $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 [ return [
[[ [[
'data' => ['sell_in' => 31, 'quality' => 43], 'data' => [
'expect' => ['sell_in' => 30, 'quality' => 44], 'sell_in' => 31,
'quality' => 43,
],
'expect' => [
'sell_in' => 30,
'quality' => 44,
],
]], ]],
[[ [[
'data' => ['sell_in' => 10, 'quality' => 44], 'data' => [
'expect' => ['sell_in' => 9, 'quality' => 46], 'sell_in' => 10,
'quality' => 44,
],
'expect' => [
'sell_in' => 9,
'quality' => 46,
],
]], ]],
[[ [[
'data' => ['sell_in' => 1, 'quality' => 46], 'data' => [
'expect' => ['sell_in' => 0, 'quality' => 49], 'sell_in' => 1,
'quality' => 46,
],
'expect' => [
'sell_in' => 0,
'quality' => 49,
],
]], ]],
[[ [[
'data' => ['sell_in' => 0, 'quality' => 49], 'data' => [
'expect' => ['sell_in' => -1, 'quality' => 0], 'sell_in' => 0,
]] 'quality' => 49,
],
'expect' => [
'sell_in' => -1,
'quality' => 0,
],
]],
]; ];
} }
/** end of backstageScenario */ /** end of backstageScenario */
/** @dataProvider conjuredItemsScenario */ /**
* @dataProvider conjuredItemsScenario
*/
public function testConjuredItems(array $conjuredItemsScenario): void public function testConjuredItems(array $conjuredItemsScenario): void
{ {
$items = [new Item('Conjured Mana Cake', $conjuredItemsScenario['data']['sell_in'], $conjuredItemsScenario['data']['quality'])]; $items = [new Item('Conjured Mana Cake', $conjuredItemsScenario['data']['sell_in'], $conjuredItemsScenario['data']['quality'])];
@ -162,14 +253,29 @@ class GildedRoseTest extends TestCase
{ {
return [ return [
[[ [[
'data' => ['sell_in' => 31, 'quality' => 50], 'data' => [
'expect' => ['sell_in' => 30, 'quality' => 48], 'sell_in' => 31,
'quality' => 50,
],
'expect' => [
'sell_in' => 30,
'quality' => 48,
],
]], ]],
[[ [[
'data' => ['sell_in' => 0, 'quality' => 48], 'data' => [
'expect' => ['sell_in' => -1, 'quality' => 44], 'sell_in' => 0,
]] 'quality' => 48,
],
'expect' => [
'sell_in' => -1,
'quality' => 44,
],
]],
]; ];
} }
/** end of conjuredItemsScenario */ /** end of conjuredItemsScenario */
} }