diff --git a/python/.github/workflows/lint-and-test.yml b/python/.github/workflows/lint-and-test.yml new file mode 100644 index 00000000..c3dbf4a0 --- /dev/null +++ b/python/.github/workflows/lint-and-test.yml @@ -0,0 +1,55 @@ +name: Lint and Test + +on: + push: + branches: + - main + - test/my_changes + + pull_request: + branches: + - main + - test/my_changes + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Install dependencies + run: | + python -m venv venv + source venv/bin/activate + pip install -r python/requirements-dev.txt + + - name: Run Black (formatting) + run: | + black --check . + + - name: Run isort (imports) + run: | + isort --check-only . + + - name: Run flake8 (style) + run: | + flake8 . + + - name: Run pylint (quality) + run: | + pylint python/gilded_rose.py + + - name: Run mypy (type checking) + run: | + mypy python/gilded_rose.py + + - name: Run tests + run: | + python -m unittest discover -s python/tests diff --git a/python/aged_brie.py b/python/aged_brie.py new file mode 100644 index 00000000..2e0bfc11 --- /dev/null +++ b/python/aged_brie.py @@ -0,0 +1,12 @@ +from item_wrappers import ItemWrapper + +class AgedBrieItem(ItemWrapper): + def update(self): + self.increase_quality() + self.item.sell_in -= 1 + if self.item.sell_in < 0: + self.increase_quality() + + def increase_quality(self): + if self.item.quality < 50: + self.item.quality += 1 diff --git a/python/backstage.py b/python/backstage.py new file mode 100644 index 00000000..ceaeb05b --- /dev/null +++ b/python/backstage.py @@ -0,0 +1,19 @@ +from item_wrappers import ItemWrapper + +class BackstagePassItem(ItemWrapper): + def update(self): + self.increase_quality() + + if self.item.sell_in <= 10: + self.increase_quality() + if self.item.sell_in <= 5: + self.increase_quality() + + self.item.sell_in -= 1 + + if self.item.sell_in < 0: + self.item.quality = 0 + + def increase_quality(self): + if self.item.quality < 50: + self.item.quality += 1 diff --git a/python/conjured.py b/python/conjured.py new file mode 100644 index 00000000..3e28e2dd --- /dev/null +++ b/python/conjured.py @@ -0,0 +1,14 @@ +from item_wrappers import ItemWrapper + +class ConjuredItem(ItemWrapper): + def update(self): + self.decrease_quality() + self.decrease_quality() + self.item.sell_in -= 1 + if self.item.sell_in < 0: + self.decrease_quality() + self.decrease_quality() + + def decrease_quality(self): + if self.item.quality > 0: + self.item.quality -= 1 diff --git a/python/gilded_rose.py b/python/gilded_rose.py index 4f21ea64..57529af2 100755 --- a/python/gilded_rose.py +++ b/python/gilded_rose.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from item_wrappers import item_factory class GildedRose(object): @@ -7,40 +8,8 @@ class GildedRose(object): 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 - 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 + wrapper = item_factory(item) + wrapper.update() -class Item: - def __init__(self, name, sell_in, quality): - self.name = name - self.sell_in = sell_in - self.quality = quality - def __repr__(self): - return "%s, %s, %s" % (self.name, self.sell_in, self.quality) diff --git a/python/item_wrappers.py b/python/item_wrappers.py new file mode 100644 index 00000000..a2388076 --- /dev/null +++ b/python/item_wrappers.py @@ -0,0 +1,43 @@ +from models import Item + +class ItemWrapper: + """ + Classe abstraite représentant un item enrichi d'une logique métier propre. + """ + def __init__(self, item: Item): + self.item = item + + def update(self): + raise NotImplementedError("Subclasses must implement update().") + + +class NormalItem(ItemWrapper): + def update(self): + self.decrease_quality() + self.item.sell_in -= 1 + if self.item.sell_in < 0: + self.decrease_quality() + + def decrease_quality(self): + if self.item.quality > 0: + self.item.quality -= 1 + + +def item_factory(item: Item) -> ItemWrapper: + """ + Retourne un wrapper métier adapté à l'item donné. + """ + if item.name == "Aged Brie": + from aged_brie import AgedBrieItem + return AgedBrieItem(item) + elif item.name == "Sulfuras, Hand of Ragnaros": + from sulfuras import SulfurasItem + return SulfurasItem(item) + elif item.name == "Backstage passes to a TAFKAL80ETC concert": + from backstage import BackstagePassItem + return BackstagePassItem(item) + elif "Conjured" in item.name: + from conjured import ConjuredItem + return ConjuredItem(item) + else: + return NormalItem(item) diff --git a/python/models.py b/python/models.py new file mode 100644 index 00000000..c8415eba --- /dev/null +++ b/python/models.py @@ -0,0 +1,8 @@ +class Item: + def __init__(self, name, sell_in, quality): + self.name = name + self.sell_in = sell_in + self.quality = quality + + def __repr__(self): + return "%s, %s, %s" % (self.name, self.sell_in, self.quality) \ No newline at end of file diff --git a/python/requirements.txt b/python/requirements.txt index feb57930..653406b6 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -2,3 +2,9 @@ pytest approvaltests pytest-approvaltests coverage +black +flake8 +pylint +isort +mypy + diff --git a/python/sulfuras.py b/python/sulfuras.py new file mode 100644 index 00000000..f5f79f3e --- /dev/null +++ b/python/sulfuras.py @@ -0,0 +1,5 @@ +from item_wrappers import ItemWrapper + +class SulfurasItem(ItemWrapper): + def update(self): + pass # Sulfuras does not change in quality or sell_in diff --git a/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt b/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt index e69de29b..4e7237ff 100644 --- a/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt +++ b/python/tests/approved_files/test_gilded_rose_approvals.test_gilded_rose_approvals.approved.txt @@ -0,0 +1,373 @@ +OMGHAI! +-------- day 0 -------- +name, sellIn, quality ++5 Dexterity Vest, 10, 20 +Aged Brie, 2, 0 +Elixir of the Mongoose, 5, 7 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 15, 20 +Backstage passes to a TAFKAL80ETC concert, 10, 49 +Backstage passes to a TAFKAL80ETC concert, 5, 49 +Conjured Mana Cake, 3, 6 + +-------- day 1 -------- +name, sellIn, quality ++5 Dexterity Vest, 9, 19 +Aged Brie, 1, 1 +Elixir of the Mongoose, 4, 6 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 14, 21 +Backstage passes to a TAFKAL80ETC concert, 9, 50 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Conjured Mana Cake, 2, 4 + +-------- day 2 -------- +name, sellIn, quality ++5 Dexterity Vest, 8, 18 +Aged Brie, 0, 2 +Elixir of the Mongoose, 3, 5 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 13, 22 +Backstage passes to a TAFKAL80ETC concert, 8, 50 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Conjured Mana Cake, 1, 2 + +-------- day 3 -------- +name, sellIn, quality ++5 Dexterity Vest, 7, 17 +Aged Brie, -1, 4 +Elixir of the Mongoose, 2, 4 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 12, 23 +Backstage passes to a TAFKAL80ETC concert, 7, 50 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Conjured Mana Cake, 0, 0 + +-------- day 4 -------- +name, sellIn, quality ++5 Dexterity Vest, 6, 16 +Aged Brie, -2, 6 +Elixir of the Mongoose, 1, 3 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 11, 24 +Backstage passes to a TAFKAL80ETC concert, 6, 50 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Conjured Mana Cake, -1, 0 + +-------- day 5 -------- +name, sellIn, quality ++5 Dexterity Vest, 5, 15 +Aged Brie, -3, 8 +Elixir of the Mongoose, 0, 2 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 10, 25 +Backstage passes to a TAFKAL80ETC concert, 5, 50 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Conjured Mana Cake, -2, 0 + +-------- day 6 -------- +name, sellIn, quality ++5 Dexterity Vest, 4, 14 +Aged Brie, -4, 10 +Elixir of the Mongoose, -1, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 9, 27 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Conjured Mana Cake, -3, 0 + +-------- day 7 -------- +name, sellIn, quality ++5 Dexterity Vest, 3, 13 +Aged Brie, -5, 12 +Elixir of the Mongoose, -2, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 8, 29 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Conjured Mana Cake, -4, 0 + +-------- day 8 -------- +name, sellIn, quality ++5 Dexterity Vest, 2, 12 +Aged Brie, -6, 14 +Elixir of the Mongoose, -3, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 7, 31 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Conjured Mana Cake, -5, 0 + +-------- day 9 -------- +name, sellIn, quality ++5 Dexterity Vest, 1, 11 +Aged Brie, -7, 16 +Elixir of the Mongoose, -4, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 6, 33 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Conjured Mana Cake, -6, 0 + +-------- day 10 -------- +name, sellIn, quality ++5 Dexterity Vest, 0, 10 +Aged Brie, -8, 18 +Elixir of the Mongoose, -5, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 5, 35 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Conjured Mana Cake, -7, 0 + +-------- day 11 -------- +name, sellIn, quality ++5 Dexterity Vest, -1, 8 +Aged Brie, -9, 20 +Elixir of the Mongoose, -6, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 4, 38 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Conjured Mana Cake, -8, 0 + +-------- day 12 -------- +name, sellIn, quality ++5 Dexterity Vest, -2, 6 +Aged Brie, -10, 22 +Elixir of the Mongoose, -7, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 3, 41 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Conjured Mana Cake, -9, 0 + +-------- day 13 -------- +name, sellIn, quality ++5 Dexterity Vest, -3, 4 +Aged Brie, -11, 24 +Elixir of the Mongoose, -8, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 2, 44 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Conjured Mana Cake, -10, 0 + +-------- day 14 -------- +name, sellIn, quality ++5 Dexterity Vest, -4, 2 +Aged Brie, -12, 26 +Elixir of the Mongoose, -9, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 1, 47 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Conjured Mana Cake, -11, 0 + +-------- day 15 -------- +name, sellIn, quality ++5 Dexterity Vest, -5, 0 +Aged Brie, -13, 28 +Elixir of the Mongoose, -10, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Conjured Mana Cake, -12, 0 + +-------- day 16 -------- +name, sellIn, quality ++5 Dexterity Vest, -6, 0 +Aged Brie, -14, 30 +Elixir of the Mongoose, -11, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Conjured Mana Cake, -13, 0 + +-------- day 17 -------- +name, sellIn, quality ++5 Dexterity Vest, -7, 0 +Aged Brie, -15, 32 +Elixir of the Mongoose, -12, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Conjured Mana Cake, -14, 0 + +-------- day 18 -------- +name, sellIn, quality ++5 Dexterity Vest, -8, 0 +Aged Brie, -16, 34 +Elixir of the Mongoose, -13, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Conjured Mana Cake, -15, 0 + +-------- day 19 -------- +name, sellIn, quality ++5 Dexterity Vest, -9, 0 +Aged Brie, -17, 36 +Elixir of the Mongoose, -14, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Conjured Mana Cake, -16, 0 + +-------- day 20 -------- +name, sellIn, quality ++5 Dexterity Vest, -10, 0 +Aged Brie, -18, 38 +Elixir of the Mongoose, -15, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Conjured Mana Cake, -17, 0 + +-------- day 21 -------- +name, sellIn, quality ++5 Dexterity Vest, -11, 0 +Aged Brie, -19, 40 +Elixir of the Mongoose, -16, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Conjured Mana Cake, -18, 0 + +-------- day 22 -------- +name, sellIn, quality ++5 Dexterity Vest, -12, 0 +Aged Brie, -20, 42 +Elixir of the Mongoose, -17, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Conjured Mana Cake, -19, 0 + +-------- day 23 -------- +name, sellIn, quality ++5 Dexterity Vest, -13, 0 +Aged Brie, -21, 44 +Elixir of the Mongoose, -18, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Conjured Mana Cake, -20, 0 + +-------- day 24 -------- +name, sellIn, quality ++5 Dexterity Vest, -14, 0 +Aged Brie, -22, 46 +Elixir of the Mongoose, -19, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Conjured Mana Cake, -21, 0 + +-------- day 25 -------- +name, sellIn, quality ++5 Dexterity Vest, -15, 0 +Aged Brie, -23, 48 +Elixir of the Mongoose, -20, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Conjured Mana Cake, -22, 0 + +-------- day 26 -------- +name, sellIn, quality ++5 Dexterity Vest, -16, 0 +Aged Brie, -24, 50 +Elixir of the Mongoose, -21, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Backstage passes to a TAFKAL80ETC concert, -21, 0 +Conjured Mana Cake, -23, 0 + +-------- day 27 -------- +name, sellIn, quality ++5 Dexterity Vest, -17, 0 +Aged Brie, -25, 50 +Elixir of the Mongoose, -22, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Backstage passes to a TAFKAL80ETC concert, -22, 0 +Conjured Mana Cake, -24, 0 + +-------- day 28 -------- +name, sellIn, quality ++5 Dexterity Vest, -18, 0 +Aged Brie, -26, 50 +Elixir of the Mongoose, -23, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Backstage passes to a TAFKAL80ETC concert, -23, 0 +Conjured Mana Cake, -25, 0 + +-------- day 29 -------- +name, sellIn, quality ++5 Dexterity Vest, -19, 0 +Aged Brie, -27, 50 +Elixir of the Mongoose, -24, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Backstage passes to a TAFKAL80ETC concert, -24, 0 +Conjured Mana Cake, -26, 0 + +-------- day 30 -------- +name, sellIn, quality ++5 Dexterity Vest, -20, 0 +Aged Brie, -28, 50 +Elixir of the Mongoose, -25, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Backstage passes to a TAFKAL80ETC concert, -25, 0 +Conjured Mana Cake, -27, 0 + diff --git a/python/tests/test_gilded_rose.py b/python/tests/test_gilded_rose.py index 1c92f638..2ebae704 100644 --- a/python/tests/test_gilded_rose.py +++ b/python/tests/test_gilded_rose.py @@ -1,15 +1,112 @@ # -*- coding: utf-8 -*- import unittest +import os +import sys +from models import Item -from gilded_rose import Item, GildedRose +# insérer le dossier parent dans sys.path +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + +from gilded_rose import GildedRose -class GildedRoseTest(unittest.TestCase): - def test_foo(self): - items = [Item("foo", 0, 0)] - gilded_rose = GildedRose(items) - gilded_rose.update_quality() - self.assertEqual("fixme", items[0].name) + + +# class GildedRoseTest(unittest.TestCase): +# def test_foo(self): +# items = [Item("foo", 0, 0)] +# gilded_rose = GildedRose(items) +# gilded_rose.update_quality() +# self.assertEqual("fixme", items[0].name) + +class TestNormalItem(unittest.TestCase): + def test_quality_decreases_by_one_before_expiration(self): + items = [Item(name="+5 Dexterity Vest", sell_in=10, quality=20)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 19) + self.assertEqual(items[0].sell_in, 9) + + def test_quality_decreases_by_two_after_expiration(self): + items = [Item(name="Elixir of the Mongoose", sell_in=0, quality=6)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 4) + self.assertEqual(items[0].sell_in, -1) + + def test_quality_never_negative(self): + items = [Item(name="Elixir of the Mongoose", sell_in=0, quality=0)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 0) + + +class TestAgedBrie(unittest.TestCase): + def test_quality_increases_by_one_before_expiration(self): + items = [Item(name="Aged Brie", sell_in=2, quality=0)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 1) + self.assertEqual(items[0].sell_in, 1) + + def test_quality_increases_by_two_after_expiration(self): + items = [Item(name="Aged Brie", sell_in=0, quality=0)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 2) + self.assertEqual(items[0].sell_in, -1) + + def test_quality_never_exceeds_fifty(self): + items = [Item(name="Aged Brie", sell_in=5, quality=50)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 50) + + +class TestSulfuras(unittest.TestCase): + def test_quality_and_sellin_never_change(self): + items = [Item(name="Sulfuras, Hand of Ragnaros", sell_in=5, quality=80)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 80) + self.assertEqual(items[0].sell_in, 5) + + +class TestBackstagePasses(unittest.TestCase): + def test_quality_increases_by_one_above_10_days(self): + items = [Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 21) + + def test_quality_increases_by_two_between_10_and_6_days(self): + items = [Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=20)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 22) + + def test_quality_increases_by_three_between_5_and_1_days(self): + items = [Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=20)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 23) + + def test_quality_drops_to_zero_after_concert(self): + items = [Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=0, quality=20)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 0) + + def test_quality_never_exceeds_fifty(self): + items = [Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 50) + + +class TestConjuredItems(unittest.TestCase): + def test_quality_degrades_twice_as_fast_before_expiration(self): + items = [Item(name="Conjured Mana Cake", sell_in=3, quality=6)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 4) + + def test_quality_degrades_twice_as_fast_after_expiration(self): + items = [Item(name="Conjured Mana Cake", sell_in=0, quality=6)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 2) + + def test_quality_never_negative(self): + items = [Item(name="Conjured Mana Cake", sell_in=0, quality=1)] + GildedRose(items).update_quality() + self.assertEqual(items[0].quality, 0) if __name__ == '__main__': diff --git a/python/tests/test_gilded_rose_approvals.py b/python/tests/test_gilded_rose_approvals.py index 6c8f9db9..6e6404a2 100644 --- a/python/tests/test_gilded_rose_approvals.py +++ b/python/tests/test_gilded_rose_approvals.py @@ -1,9 +1,14 @@ import io import sys +import os + +# insérer le dossier parent dans sys.path +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from approvaltests.reporters import PythonNativeReporter from approvaltests import verify from texttest_fixture import main - +reporter = PythonNativeReporter() def test_gilded_rose_approvals(): orig_sysout = sys.stdout try: @@ -15,7 +20,7 @@ def test_gilded_rose_approvals(): finally: sys.stdout = orig_sysout - verify(answer) + verify(answer, reporter=reporter) if __name__ == "__main__": test_gilded_rose_approvals() \ No newline at end of file diff --git a/python/texttest_fixture.py b/python/texttest_fixture.py index 8f7e4940..2e360dd8 100644 --- a/python/texttest_fixture.py +++ b/python/texttest_fixture.py @@ -2,6 +2,7 @@ from __future__ import print_function from gilded_rose import * +from models import Item def main():