From 3dbbbb12e0233339a0d55b7ae241daf2fef57417 Mon Sep 17 00:00:00 2001 From: wunderwood Date: Mon, 14 Jun 2021 12:31:29 +0100 Subject: [PATCH] ktlo-0001 - Refactor update quality method and increase use case and edge case test coverage --- python/gilded_rose.py | 109 ++++++++++++++++++++++++++++--------- python/test_gilded_rose.py | 88 +++++++++++++++++++++++++++++- python/texttest_fixture.py | 22 ++++---- 3 files changed, 180 insertions(+), 39 deletions(-) diff --git a/python/gilded_rose.py b/python/gilded_rose.py index 4f21ea64..437bf8c9 100755 --- a/python/gilded_rose.py +++ b/python/gilded_rose.py @@ -1,39 +1,96 @@ # -*- coding: utf-8 -*- class GildedRose(object): + MAX_NON_LEGENDARY_QUALITY = 50 + STATIC_LEGENDARY_QUALITY = 80 + STANDARD_INCREMENT = 1 def __init__(self, items): self.items = items + @staticmethod + def _is_static_item(name: str) -> bool: + static_items = [ + 'Sulfuras, Hand of Ragnaros', + ] + return name in static_items + + @staticmethod + def _is_inverse_quality_item(name: str) -> bool: + inverse_quality_items = [ + 'Aged Brie', + ] + return name in inverse_quality_items + + @staticmethod + def _is_ranged_rule_based_item(name: str) -> bool: + inverse_quality_items = [ + 'Backstage passes to a TAFKAL80ETC concert', + ] + return name in inverse_quality_items + + @staticmethod + def _is_double_increment_keyword_item(name: str) -> bool: + ranged_rule_based_items = [ + 'Conjured', + ] + for keyword in ranged_rule_based_items: + if keyword in name: + return True + else: + return False + + def _increase_quality(self, item): + if item.quality < self.MAX_NON_LEGENDARY_QUALITY: + item.quality += self.STANDARD_INCREMENT + + def _update_inverse_quality_item(self, item): + self._increase_quality(item) + item.sell_in -= self.STANDARD_INCREMENT + if item.sell_in < 0: + self._increase_quality(item) + + def _update_ranged_rule_based_item(self, item): + if item.sell_in < 6: + item.quality += self.STANDARD_INCREMENT * 3 + elif item.sell_in < 11: + item.quality += self.STANDARD_INCREMENT * 2 + else: + item.quality += self.STANDARD_INCREMENT + item.sell_in -= self.STANDARD_INCREMENT + if item.quality > self.MAX_NON_LEGENDARY_QUALITY: + item.quality = self.MAX_NON_LEGENDARY_QUALITY + if item.sell_in < 0: + item.quality = 0 + + def _update_item(self, item, increment): + if item.quality > 0: + item.quality -= increment + item.sell_in -= self.STANDARD_INCREMENT + if item.sell_in < 0 < item.quality: + item.quality -= increment + def update_quality(self): for item in self.items: - if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert": - if item.quality > 0: - if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1 + # Catch static items + if self._is_static_item(item.name): + item.quality = self.STATIC_LEGENDARY_QUALITY + continue + # Catch items with inverse quality update + elif self._is_inverse_quality_item(item.name): + self._update_inverse_quality_item(item) + continue + # Catch items with range based rule + elif self._is_ranged_rule_based_item(item.name): + self._update_ranged_rule_based_item(item) + continue + # Catch conjured items + elif self._is_double_increment_keyword_item(item.name): + self._update_item(item, self.STANDARD_INCREMENT * 2) + continue + # Catch all other 'normal' items else: - if item.quality < 50: - item.quality = item.quality + 1 - if item.name == "Backstage passes to a TAFKAL80ETC concert": - if item.sell_in < 11: - if item.quality < 50: - item.quality = item.quality + 1 - if item.sell_in < 6: - if item.quality < 50: - item.quality = item.quality + 1 - if item.name != "Sulfuras, Hand of Ragnaros": - item.sell_in = item.sell_in - 1 - if item.sell_in < 0: - if item.name != "Aged Brie": - if item.name != "Backstage passes to a TAFKAL80ETC concert": - if item.quality > 0: - if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1 - else: - item.quality = item.quality - item.quality - else: - if item.quality < 50: - item.quality = item.quality + 1 + self._update_item(item, self.STANDARD_INCREMENT) class Item: diff --git a/python/test_gilded_rose.py b/python/test_gilded_rose.py index 616934e0..839fbaab 100644 --- a/python/test_gilded_rose.py +++ b/python/test_gilded_rose.py @@ -9,8 +9,92 @@ class GildedRoseTest(unittest.TestCase): items = [Item("foo", 0, 0)] gilded_rose = GildedRose(items) gilded_rose.update_quality() - self.assertEquals("fixme", items[0].name) + self.assertEquals("foo", items[0].name) + + def test_item_quality_degrades_double_when_sell_in_negative(self): + items = [Item("foo", -1, 15)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(13, items[0].quality) + + def test_item_quality_wont_go_negative(self): + items = [Item("foo", 5, 0)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(0, items[0].quality) + + def test_aged_brie_quality_cap(self): + items = [Item("Aged Brie", 10, 50)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(50, items[0].quality) + + def test_aged_brie_sell_in_decrease(self): + items = [Item("Aged Brie", 30, 30)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(29, items[0].sell_in) + + def test_aged_brie_quality_increase(self): + items = [Item("Aged Brie", 30, 30)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(31, items[0].quality) + + def test_aged_brie_quality_increase_double_when_sell_in_negative(self): + items = [Item("Aged Brie", -10, 20)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(22, items[0].quality) + + def test_sulfuras_quality_doesnt_change(self): + items = [Item("Sulfuras, Hand of Ragnaros", 10, 80)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(80, items[0].quality) + + def test_sulfuras_when_passed_sell_in(self): + items = [Item("Sulfuras, Hand of Ragnaros", -10, 80)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(80, items[0].quality) + + def test_backstage_pass_increases_quality(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 20, 20)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(21, items[0].quality) + + def test_backstage_pass_10_days_to_go(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 10, 20)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(22, items[0].quality) + + def test_backstage_pass_5_days_to_go(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 5, 20)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(23, items[0].quality) + + def test_backstage_pass_quality_after_concert(self): + items = [Item("Backstage passes to a TAFKAL80ETC concert", 0, 30)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(0, items[0].quality) + + def test_conjured_item_quality_decrease(self): + items = [Item("Conjured", 10, 30)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(28, items[0].quality) + + def test_conjured_item_quality_increase_double_when_sell_in_negative(self): + items = [Item("Conjured", 0, 30)] + gilded_rose = GildedRose(items) + gilded_rose.update_quality() + self.assertEquals(26, items[0].quality) + - if __name__ == '__main__': unittest.main() diff --git a/python/texttest_fixture.py b/python/texttest_fixture.py index 86af5ef7..6a4021dc 100644 --- a/python/texttest_fixture.py +++ b/python/texttest_fixture.py @@ -4,18 +4,18 @@ from __future__ import print_function from gilded_rose import * if __name__ == "__main__": - print ("OMGHAI!") + print("OMGHAI!") items = [ - Item(name="+5 Dexterity Vest", sell_in=10, quality=20), - Item(name="Aged Brie", sell_in=2, quality=0), - Item(name="Elixir of the Mongoose", sell_in=5, quality=7), - Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), - Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), - Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O - ] + Item(name="+5 Dexterity Vest", sell_in=10, quality=20), + Item(name="Aged Brie", sell_in=2, quality=0), + Item(name="Elixir of the Mongoose", sell_in=5, quality=7), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), + Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O + ] days = 2 import sys