Tests improved before another major refactory

This commit is contained in:
Erol Shaban 2019-08-21 14:51:04 +02:00
parent fa0aa29a17
commit df8e2f0d36
12 changed files with 285 additions and 104 deletions

0
Java/src/README.md Normal file
View File

View File

@ -3,8 +3,8 @@ package com.gildedrose;
public class AgedBrieUpdater extends ItemUpdater { public class AgedBrieUpdater extends ItemUpdater {
@Override @Override
void updateQuality(Item item) { void updateQuality(Item item) {
if (item.quality < 50) { if (canUpdateQuality(item)) {
item.quality += 1; item.quality += getDegradeValue(item);
} }
} }
@ -12,4 +12,14 @@ public class AgedBrieUpdater extends ItemUpdater {
void updateSellIn(Item item) { 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;
}
} }

View File

@ -3,18 +3,10 @@ package com.gildedrose;
public class BackstagePassUpdater extends ItemUpdater { public class BackstagePassUpdater extends ItemUpdater {
@Override @Override
void updateQuality(Item item) { void updateQuality(Item item) {
if (item.sellIn < 0) { if (sellByDateLessThan(item, 0)) {
item.quality = 0; item.quality = 0;
} else if (item.quality < 50) { } else if (canUpdateQuality(item)) {
item.quality += 1; item.quality += getDegradeValue(item);
if (item.sellIn < 11 && item.quality < 50) {
item.quality += 1;
}
if (item.sellIn < 6 && item.quality < 50) {
item.quality += 1;
}
} }
} }
@ -22,4 +14,23 @@ public class BackstagePassUpdater extends ItemUpdater {
void updateSellIn(Item item) { void updateSellIn(Item item) {
item.sellIn -=1; 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;
}
} }

View File

@ -3,10 +3,8 @@ package com.gildedrose;
public class ConjuredUpdater extends ItemUpdater { public class ConjuredUpdater extends ItemUpdater {
@Override @Override
void updateQuality(Item item) { void updateQuality(Item item) {
if (item.quality > 0) { if (canUpdateQuality(item)) {
item.quality -= 2; item.quality += getDegradeValue(item);
if (item.quality < 0 )
item.quality =0;
} }
} }
@ -14,4 +12,16 @@ public class ConjuredUpdater extends ItemUpdater {
void updateSellIn(Item item) { void updateSellIn(Item item) {
item.sellIn -= 1; 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;
}
} }

View File

@ -8,55 +8,9 @@ class GildedRose {
} }
public void updateQuality() { public void updateQuality() {
for (int i = 0; i < items.length; i++) { for (Item item : items) {
if (!items[i].name.equals("Aged Brie") ItemUpdaterFactory.getItemUpdater(item)
&& !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { .updateStateFor(item);
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;
}
}
}
} }
} }
} }

View File

@ -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;
}
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -1,10 +1,23 @@
package com.gildedrose; package com.gildedrose;
public abstract class ItemUpdater { 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){ public void updateStateFor(Item item){
updateSellIn(item); updateSellIn(item);
updateQuality(item); updateQuality(item);
} }
abstract void updateQuality(Item item); abstract void updateQuality(Item item);
abstract void updateSellIn(Item item); abstract void updateSellIn(Item item);
abstract boolean canUpdateQuality(Item item);
abstract int getDegradeValue(Item item);
public int getHighestQuality() {
return HIGHEST_QUALITY;
}
} }

View File

@ -11,7 +11,7 @@ public class ItemUpdaterFactory {
registeredCustomUpdaters.put("Aged Brie", new AgedBrieUpdater()); registeredCustomUpdaters.put("Aged Brie", new AgedBrieUpdater());
registeredCustomUpdaters.put("Backstage passes to a TAFKAL80ETC concert", new BackstagePassUpdater()); registeredCustomUpdaters.put("Backstage passes to a TAFKAL80ETC concert", new BackstagePassUpdater());
registeredCustomUpdaters.put("Sulfuras, Hand of Ragnaros", new SulfurasUpdater()); 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 ){ public static void registerCustomUpdater(String type, ItemUpdater updater ){
@ -22,17 +22,4 @@ public class ItemUpdaterFactory {
return Optional.ofNullable(registeredCustomUpdaters.get(item.name)) return Optional.ofNullable(registeredCustomUpdaters.get(item.name))
.orElse(new StandardItemUpdater()); .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();
}*/
} }

View File

@ -4,8 +4,8 @@ public class StandardItemUpdater extends ItemUpdater{
@Override @Override
void updateQuality(Item item) { void updateQuality(Item item) {
if (item.quality > 0) { if (canUpdateQuality(item)) {
item.quality -= 1; item.quality += getDegradeValue(item);
} }
} }
@ -13,4 +13,18 @@ public class StandardItemUpdater extends ItemUpdater{
void updateSellIn(Item item) { void updateSellIn(Item item) {
item.sellIn -= 1; 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;
}
}
} }

View File

@ -1,13 +1,32 @@
package com.gildedrose; package com.gildedrose;
public class SulfurasUpdater extends ItemUpdater { public class SulfurasUpdater extends ItemUpdater {
@Override @Override
void updateQuality(Item item) { void updateQuality(Item item) {
System.out.println("########Sulfuras is a legendary product"); System.out.println("########Sulfuras is a legendary product");
// TODO
item.quality = 80;
} }
@Override @Override
void updateSellIn(Item item) { void updateSellIn(Item item) {
System.out.println("########Never gets old"); 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;
}
} }

View File

@ -4,14 +4,131 @@ import static org.junit.Assert.*;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class GildedRoseTest { 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 @Test
public void foo() { public void standardItem_shouldDegradeNormal_whenSellByDateNotPassed() {
Item[] items = new Item[] { new Item("foo", 0, 0) }; final int originalQuality = 40;
GildedRose app = new GildedRose(items); final Item[] items = new Item[] { new Item("Standard", 4, originalQuality) };
final GildedRose app = new GildedRose(items);
app.updateQuality(); 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<Item> 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<Item> 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<Item> qualityNegative = Arrays.stream(app.items).filter(item -> item.quality < 0 ).findAny();
assertFalse(qualityNegative.isPresent());
app.updateQuality();
final Optional<Item> qualityNegativeAfter2ndUpdate = Arrays.stream(app.items).filter(item -> item.quality < 0 ).findAny();
assertFalse(qualityNegativeAfter2ndUpdate.isPresent());
} }
} }