From df8e2f0d3616b040b81d9be7463bcac844a04f11 Mon Sep 17 00:00:00 2001 From: Erol Shaban Date: Wed, 21 Aug 2019 14:51:04 +0200 Subject: [PATCH] Tests improved before another major refactory --- Java/src/README.md | 0 .../java/com/gildedrose/AgedBrieUpdater.java | 16 ++- .../com/gildedrose/BackstagePassUpdater.java | 33 +++-- .../java/com/gildedrose/ConjuredUpdater.java | 18 ++- .../main/java/com/gildedrose/GildedRose.java | 52 +------- .../java/com/gildedrose/GildedRoseOld.java | 62 +++++++++ .../com/gildedrose/GildedRosePrototype.java | 16 --- .../main/java/com/gildedrose/ItemUpdater.java | 13 ++ .../com/gildedrose/ItemUpdaterFactory.java | 15 +-- .../com/gildedrose/StandardItemUpdater.java | 20 ++- .../java/com/gildedrose/SulfurasUpdater.java | 19 +++ .../java/com/gildedrose/GildedRoseTest.java | 125 +++++++++++++++++- 12 files changed, 285 insertions(+), 104 deletions(-) create mode 100644 Java/src/README.md create mode 100644 Java/src/main/java/com/gildedrose/GildedRoseOld.java delete mode 100644 Java/src/main/java/com/gildedrose/GildedRosePrototype.java diff --git a/Java/src/README.md b/Java/src/README.md new file mode 100644 index 00000000..e69de29b diff --git a/Java/src/main/java/com/gildedrose/AgedBrieUpdater.java b/Java/src/main/java/com/gildedrose/AgedBrieUpdater.java index 070c6690..f923d724 100644 --- a/Java/src/main/java/com/gildedrose/AgedBrieUpdater.java +++ b/Java/src/main/java/com/gildedrose/AgedBrieUpdater.java @@ -3,13 +3,23 @@ package com.gildedrose; public class AgedBrieUpdater extends ItemUpdater { @Override void updateQuality(Item item) { - if (item.quality < 50) { - item.quality += 1; + if (canUpdateQuality(item)) { + item.quality += getDegradeValue(item); } } @Override void updateSellIn(Item item) { - item.sellIn -=1; + item.sellIn -= 1; + } + + @Override + boolean canUpdateQuality(Item item) { + return item.quality < HIGHEST_QUALITY; + } + + @Override + int getDegradeValue(Item item) { + return INCREASE_NORMAL; } } diff --git a/Java/src/main/java/com/gildedrose/BackstagePassUpdater.java b/Java/src/main/java/com/gildedrose/BackstagePassUpdater.java index 5bad8662..7843970f 100644 --- a/Java/src/main/java/com/gildedrose/BackstagePassUpdater.java +++ b/Java/src/main/java/com/gildedrose/BackstagePassUpdater.java @@ -3,18 +3,10 @@ package com.gildedrose; public class BackstagePassUpdater extends ItemUpdater { @Override void updateQuality(Item item) { - if (item.sellIn < 0) { + if (sellByDateLessThan(item, 0)) { item.quality = 0; - } else if (item.quality < 50) { - item.quality += 1; - - if (item.sellIn < 11 && item.quality < 50) { - item.quality += 1; - } - - if (item.sellIn < 6 && item.quality < 50) { - item.quality += 1; - } + } else if (canUpdateQuality(item)) { + item.quality += getDegradeValue(item); } } @@ -22,4 +14,23 @@ public class BackstagePassUpdater extends ItemUpdater { void updateSellIn(Item item) { item.sellIn -=1; } + + @Override + boolean canUpdateQuality(final Item item) { + return item.quality < HIGHEST_QUALITY; + } + + @Override + int getDegradeValue(final Item item) { + if (sellByDateLessThan(item, 6)) { + return INCREASE_THRICE_AS_FAST; + } else if (sellByDateLessThan(item, 11) ) { + return INCREASE_TWICE_AS_FAST; + } + return INCREASE_NORMAL; + } + + private static boolean sellByDateLessThan(final Item item, final int remainingDayCount) { + return item.sellIn < remainingDayCount; + } } diff --git a/Java/src/main/java/com/gildedrose/ConjuredUpdater.java b/Java/src/main/java/com/gildedrose/ConjuredUpdater.java index 11562876..2cc66ef3 100644 --- a/Java/src/main/java/com/gildedrose/ConjuredUpdater.java +++ b/Java/src/main/java/com/gildedrose/ConjuredUpdater.java @@ -3,10 +3,8 @@ package com.gildedrose; public class ConjuredUpdater extends ItemUpdater { @Override void updateQuality(Item item) { - if (item.quality > 0) { - item.quality -= 2; - if (item.quality < 0 ) - item.quality =0; + if (canUpdateQuality(item)) { + item.quality += getDegradeValue(item); } } @@ -14,4 +12,16 @@ public class ConjuredUpdater extends ItemUpdater { void updateSellIn(Item item) { item.sellIn -= 1; } + + @Override + boolean canUpdateQuality(Item item) { + return item.quality < HIGHEST_QUALITY && item.quality > 0; + } + + @Override + int getDegradeValue(Item item) { + return item.quality + DEGRADE_TWICE_AS_FAST < 0 ? + DEGRADE_NORMAL : + DEGRADE_TWICE_AS_FAST; + } } diff --git a/Java/src/main/java/com/gildedrose/GildedRose.java b/Java/src/main/java/com/gildedrose/GildedRose.java index e6feb751..930c6dfb 100644 --- a/Java/src/main/java/com/gildedrose/GildedRose.java +++ b/Java/src/main/java/com/gildedrose/GildedRose.java @@ -8,55 +8,9 @@ class GildedRose { } public void updateQuality() { - for (int i = 0; i < items.length; i++) { - if (!items[i].name.equals("Aged Brie") - && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - - if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].sellIn < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) { - if (!items[i].name.equals("Aged Brie")) { - if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - items[i].quality = items[i].quality - items[i].quality; - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } + for (Item item : items) { + ItemUpdaterFactory.getItemUpdater(item) + .updateStateFor(item); } } } \ No newline at end of file diff --git a/Java/src/main/java/com/gildedrose/GildedRoseOld.java b/Java/src/main/java/com/gildedrose/GildedRoseOld.java new file mode 100644 index 00000000..d4e98431 --- /dev/null +++ b/Java/src/main/java/com/gildedrose/GildedRoseOld.java @@ -0,0 +1,62 @@ +package com.gildedrose; + +class GildedRoseOld { + Item[] items; + + public GildedRoseOld(Item[] items) { + this.items = items; + } + + public void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (!items[i].name.equals("Aged Brie") + && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + + if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) { + if (!items[i].name.equals("Aged Brie")) { + if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + items[i].quality = items[i].quality - items[i].quality; + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } +} \ No newline at end of file diff --git a/Java/src/main/java/com/gildedrose/GildedRosePrototype.java b/Java/src/main/java/com/gildedrose/GildedRosePrototype.java deleted file mode 100644 index 4ed8cf7c..00000000 --- a/Java/src/main/java/com/gildedrose/GildedRosePrototype.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gildedrose; - -class GildedRosePrototype { - Item[] items; - - public GildedRosePrototype(Item[] items) { - this.items = items; - } - - public void updateQuality() { - for (Item item : items) { - ItemUpdaterFactory.getItemUpdater(item) - .updateStateFor(item); - } - } -} \ No newline at end of file diff --git a/Java/src/main/java/com/gildedrose/ItemUpdater.java b/Java/src/main/java/com/gildedrose/ItemUpdater.java index 8a7d1f35..a94bda73 100644 --- a/Java/src/main/java/com/gildedrose/ItemUpdater.java +++ b/Java/src/main/java/com/gildedrose/ItemUpdater.java @@ -1,10 +1,23 @@ package com.gildedrose; public abstract class ItemUpdater { + static int HIGHEST_QUALITY = 50; + static int DEGRADE_NORMAL = -1; + static int DEGRADE_TWICE_AS_FAST = -2; + static int INCREASE_NORMAL = 1; + static int INCREASE_TWICE_AS_FAST = 2; + static int INCREASE_THRICE_AS_FAST = 3; + public void updateStateFor(Item item){ updateSellIn(item); updateQuality(item); } abstract void updateQuality(Item item); abstract void updateSellIn(Item item); + abstract boolean canUpdateQuality(Item item); + abstract int getDegradeValue(Item item); + + public int getHighestQuality() { + return HIGHEST_QUALITY; + } } diff --git a/Java/src/main/java/com/gildedrose/ItemUpdaterFactory.java b/Java/src/main/java/com/gildedrose/ItemUpdaterFactory.java index a5ce349a..7d54cdaa 100644 --- a/Java/src/main/java/com/gildedrose/ItemUpdaterFactory.java +++ b/Java/src/main/java/com/gildedrose/ItemUpdaterFactory.java @@ -11,7 +11,7 @@ public class ItemUpdaterFactory { registeredCustomUpdaters.put("Aged Brie", new AgedBrieUpdater()); registeredCustomUpdaters.put("Backstage passes to a TAFKAL80ETC concert", new BackstagePassUpdater()); registeredCustomUpdaters.put("Sulfuras, Hand of Ragnaros", new SulfurasUpdater()); - registeredCustomUpdaters.put("Conjured", new ConjuredUpdater()); + registeredCustomUpdaters.put("Conjured Mana Cake", new ConjuredUpdater()); } public static void registerCustomUpdater(String type, ItemUpdater updater ){ @@ -22,17 +22,4 @@ public class ItemUpdaterFactory { return Optional.ofNullable(registeredCustomUpdaters.get(item.name)) .orElse(new StandardItemUpdater()); } - - /*public static ItemUpdater getItemUpdater_(Item item) { - if ("Aged Brie".equals(item.name)) - return new AgedBrieUpdater(); - else if ("Backstage passes to a TAFKAL80ETC concert".equals(item.name)) - return new BackstagePassUpdater(); - else if ("Sulfuras, Hand of Ragnaros".equals(item.name)) - return new SulfurasUpdater(); - else if ("Conjured".equals(item.name)) - return new ConjuredUpdater(); - else - return new StandardItemUpdater(); - }*/ } diff --git a/Java/src/main/java/com/gildedrose/StandardItemUpdater.java b/Java/src/main/java/com/gildedrose/StandardItemUpdater.java index 1c3b586f..54d765fd 100644 --- a/Java/src/main/java/com/gildedrose/StandardItemUpdater.java +++ b/Java/src/main/java/com/gildedrose/StandardItemUpdater.java @@ -1,11 +1,11 @@ package com.gildedrose; -public class StandardItemUpdater extends ItemUpdater{ +public class StandardItemUpdater extends ItemUpdater { @Override void updateQuality(Item item) { - if (item.quality > 0) { - item.quality -= 1; + if (canUpdateQuality(item)) { + item.quality += getDegradeValue(item); } } @@ -13,4 +13,18 @@ public class StandardItemUpdater extends ItemUpdater{ void updateSellIn(Item item) { item.sellIn -= 1; } + + @Override + boolean canUpdateQuality(Item item) { + return item.quality < HIGHEST_QUALITY && item.quality > 0; + } + + @Override + int getDegradeValue(Item item) { + if (item.sellIn < 0) { + return item.quality + DEGRADE_TWICE_AS_FAST < 0 ? DEGRADE_NORMAL : DEGRADE_TWICE_AS_FAST; + } else { + return DEGRADE_NORMAL; + } + } } diff --git a/Java/src/main/java/com/gildedrose/SulfurasUpdater.java b/Java/src/main/java/com/gildedrose/SulfurasUpdater.java index e6dfe122..31f7b073 100644 --- a/Java/src/main/java/com/gildedrose/SulfurasUpdater.java +++ b/Java/src/main/java/com/gildedrose/SulfurasUpdater.java @@ -1,13 +1,32 @@ package com.gildedrose; public class SulfurasUpdater extends ItemUpdater { + @Override void updateQuality(Item item) { System.out.println("########Sulfuras is a legendary product"); + // TODO + item.quality = 80; } @Override void updateSellIn(Item item) { System.out.println("########Never gets old"); } + + @Override + boolean canUpdateQuality(Item item) { + // "Sulfuras", being a legendary item, never decreases in Quality + return false; + } + + @Override + int getDegradeValue(Item item) { + // "Sulfuras", being a legendary item, never has to be sold + return 0; + } + + public int getHighestQuality() { + return 80; + } } diff --git a/Java/src/test/java/com/gildedrose/GildedRoseTest.java b/Java/src/test/java/com/gildedrose/GildedRoseTest.java index 95bfddc4..d28d1166 100644 --- a/Java/src/test/java/com/gildedrose/GildedRoseTest.java +++ b/Java/src/test/java/com/gildedrose/GildedRoseTest.java @@ -4,14 +4,131 @@ import static org.junit.Assert.*; import org.junit.Test; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + public class GildedRoseTest { + /* + First an introduction to our system: + + - All items have a SellIn value which denotes the number of days we have to sell the item + - All items have a Quality value which denotes how valuable the item is + - At the end of each day our system lowers both values for every item + +Pretty simple, right? Well this is where it gets interesting: + + - Once the sell by date has passed, Quality degrades twice as fast + - The Quality of an item is never negative + - "Aged Brie" actually increases in Quality the older it gets + - The Quality of an item is never more than 50 + - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality + - "Backstage passes", like aged brie, increases in Quality as its SellIn value approaches; + Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but + Quality drops to 0 after the concert + + We have recently signed a supplier of conjured items. This requires an update to our system: + + - "Conjured" items degrade in Quality twice as fast as normal items + + Feel free to make any changes to the UpdateQuality method and add any new code as long as everything + still works correctly. However, do not alter the Item class or Items property as those belong to the + goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code + ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover + for you). + + Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a + legendary item and as such its Quality is 80 and it never alters. + + */ + private final Item sulfuras = new Item("Sulfuras, Hand of Ragnaros", 0, 80); + + private final Item standardWithHighestQuality = new Item("Standard", 5, 50); + private final Item agedBrieWithHighestQuality = new Item("Aged Brie", 5, 50); + private final Item conjuredWithHighestQuality = new Item("Conjured Mana Cake", 5, 50); + private final Item backstageWithHighestQuality = new Item("Backstage passes to a TAFKAL80ETC concert", 5, 50); + + private final Item standardWithLowQuality = new Item("Standard", 0, 1); + private final Item agedBrieWithLowQuality = new Item("Aged Brie", 0, 1); + private final Item conjuredWithLowQuality = new Item("Conjured Mana Cake", 0, 1); + private final Item backstageWithLowQuality = new Item("Backstage passes to a TAFKAL80ETC concert", 0, 1); + @Test - public void foo() { - Item[] items = new Item[] { new Item("foo", 0, 0) }; - GildedRose app = new GildedRose(items); + public void standardItem_shouldDegradeNormal_whenSellByDateNotPassed() { + final int originalQuality = 40; + final Item[] items = new Item[] { new Item("Standard", 4, originalQuality) }; + final GildedRose app = new GildedRose(items); app.updateQuality(); - assertEquals("fixme", app.items[0].name); + assertEquals("Standard", app.items[0].name); + assertEquals(3, app.items[0].sellIn); + assertEquals(originalQuality - 1, app.items[0].quality); + } + + @Test + public void standardItem_shouldDegradeTwiceAsFast_whenSellByDatePassed() { + final int originalQuality = 40; + final Item[] items = new Item[] { new Item("Standard", 0, originalQuality) }; + final GildedRose app = new GildedRose(items); + app.updateQuality(); + assertEquals("Standard", app.items[0].name); + assertEquals(-1, app.items[0].sellIn); + assertEquals(originalQuality - 2, app.items[0].quality); + + app.updateQuality(); + assertEquals(-2, app.items[0].sellIn); + assertEquals(originalQuality - 4, app.items[0].quality); + } + + + @Test + public void sulfurus_shouldNeverDegradeAndBeSold() { + final Item[] items = new Item[] { sulfuras}; + final GildedRose app = new GildedRose(items); + app.updateQuality(); + assertEquals("Sulfuras, Hand of Ragnaros", app.items[0].name); + assertEquals(0, app.items[0].sellIn); + assertEquals(80, app.items[0].quality); + } + + @Test + public void qualityOfItem_exceptLegendaryItems_cantBeMoreThan_50() { + final Item[] items = new Item[] {standardWithHighestQuality, backstageWithHighestQuality, + agedBrieWithHighestQuality, conjuredWithHighestQuality}; + final GildedRose app = new GildedRose(items); + app.updateQuality(); + final Optional qualityHigherThan80 = Arrays.stream(app.items).filter(item -> item.quality > 50).findAny(); + + assertFalse(qualityHigherThan80.isPresent()); + } + + @Test + public void qualityOfItem_onlyLegendaryItems_cantBeMoreThan_50() { + final Item[] items = new Item[] { sulfuras, standardWithHighestQuality, backstageWithHighestQuality, + agedBrieWithHighestQuality, conjuredWithHighestQuality}; + final GildedRose app = new GildedRose(items); + app.updateQuality(); + final List qualityHigherThan80List = Arrays.stream(app.items).filter(item -> item.quality > 50).collect(Collectors.toList()); + + assertEquals(1, qualityHigherThan80List.size()); + assertEquals(sulfuras.name, qualityHigherThan80List.get(0).name); + } + + @Test + public void qualityOfItem_canNeverBeNegative() { + final Item[] items = new Item[] {sulfuras, standardWithLowQuality, backstageWithLowQuality, + agedBrieWithLowQuality, conjuredWithLowQuality}; + final GildedRose app = new GildedRose(items); + app.updateQuality(); + final Optional qualityNegative = Arrays.stream(app.items).filter(item -> item.quality < 0 ).findAny(); + + assertFalse(qualityNegative.isPresent()); + + app.updateQuality(); + final Optional qualityNegativeAfter2ndUpdate = Arrays.stream(app.items).filter(item -> item.quality < 0 ).findAny(); + + assertFalse(qualityNegativeAfter2ndUpdate.isPresent()); } }