diff --git a/gilded-rose/readme.md b/gilded-rose/readme.md
index 7b62fe7eb52880c9ceaa611b445a61b0d3b89563..66c0a2d85fa742be2e0747f698eebaed4bafe28e 100644
--- a/gilded-rose/readme.md
+++ b/gilded-rose/readme.md
@@ -6,7 +6,7 @@ Résolution préparée du kata [GildedRose](https://github.com/emilybache/Gilded
 -   **Date** : 12:08/2020
 -   **Langage** : Java
 -   **Niveau** : Enervé
--   **Replay** : //TODO
+-   **Replay** : [twitch (temporaire)](https://www.twitch.tv/videos/707923490)
 
 # Spécification de la Rose dorée (Gilded Rose)
 
diff --git a/gilded-rose/src/main/java/com/gildedrose/GildedRose.java b/gilded-rose/src/main/java/com/gildedrose/GildedRose.java
index 2afaa306eeb3075f961a95f341b08c12b9970655..895525c33dd2031c247a356564501eb6a6b62770 100644
--- a/gilded-rose/src/main/java/com/gildedrose/GildedRose.java
+++ b/gilded-rose/src/main/java/com/gildedrose/GildedRose.java
@@ -1,6 +1,9 @@
 package com.gildedrose;
 
 class GildedRose {
+  private static final String SULFURAS_NAME = "Sulfuras, Hand of Ragnaros";
+  private static final String BACKSTAGE_PASSES_NAME = "Backstage passes to a TAFKAL80ETC concert";
+  private static final String AGED_BRIE_NAME = "Aged Brie";
   Item[] items;
 
   public GildedRose(Item[] items) {
@@ -8,54 +11,64 @@ 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;
-              }
-            }
-          }
-        }
+    for (Item item : items) {
+      if (SULFURAS_NAME.equals(item.name)) {
+        continue;
       }
 
-      if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
-        items[i].sellIn = items[i].sellIn - 1;
-      }
+      item.sellIn = item.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;
-          }
-        }
+      if (AGED_BRIE_NAME.equals(item.name)) {
+        updateAgedBrie(item);
+      } else if (BACKSTAGE_PASSES_NAME.equals(item.name)) {
+        updateBackstagePass(item);
+      } else {
+        updateNormalItem(item);
       }
     }
   }
+
+  private void updateAgedBrie(Item item) {
+    increaseQuality(item);
+
+    if (item.sellIn < 0) {
+      increaseQuality(item);
+    }
+  }
+
+  private void updateBackstagePass(Item item) {
+    increaseQuality(item);
+
+    if (item.sellIn < 10) {
+      increaseQuality(item);
+    }
+
+    if (item.sellIn < 5) {
+      increaseQuality(item);
+    }
+
+    if (item.sellIn < 0) {
+      item.quality = 0;
+    }
+  }
+
+  private void updateNormalItem(Item item) {
+    decreaseQuality(item);
+
+    if (item.sellIn < 0) {
+      decreaseQuality(item);
+    }
+  }
+
+  private void increaseQuality(Item item) {
+    if (item.quality < 50) {
+      item.quality = item.quality + 1;
+    }
+  }
+
+  private void decreaseQuality(Item item) {
+    if (item.quality > 0) {
+      item.quality = item.quality - 1;
+    }
+  }
 }
diff --git a/gilded-rose/src/test/java/com/gildedrose/GildedRoseGolden.java b/gilded-rose/src/test/java/com/gildedrose/GildedRoseGolden.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ac08abce7552302f71befc53935f72667e3721f
--- /dev/null
+++ b/gilded-rose/src/test/java/com/gildedrose/GildedRoseGolden.java
@@ -0,0 +1,61 @@
+package com.gildedrose;
+
+class GildedRoseGolden {
+  Item[] items;
+
+  public GildedRoseGolden(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;
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/gilded-rose/src/test/java/com/gildedrose/GildedRoseTest.java b/gilded-rose/src/test/java/com/gildedrose/GildedRoseTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..58dbc4418aed0536e27175f7060089b51e3505c4
--- /dev/null
+++ b/gilded-rose/src/test/java/com/gildedrose/GildedRoseTest.java
@@ -0,0 +1,48 @@
+package com.gildedrose;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Arrays;
+import org.junit.jupiter.api.Test;
+
+class GildedRoseTest {
+
+  @Test
+  void shouldUpdateForOneDay() {
+    GildedRose rose = new GildedRose(ItemsProvider.get());
+
+    rose.updateQuality();
+
+    assertThat(rose.items).extracting(item -> item.sellIn).containsExactly(9, 1, 4, 0, -1, 14, 9, 4);
+    assertThat(rose.items).extracting(item -> item.quality).containsExactly(19, 1, 6, 80, 80, 21, 50, 50);
+  }
+
+  @Test
+  void shouldUpdateForTwoDays() {
+    GildedRose rose = new GildedRose(ItemsProvider.get());
+
+    rose.updateQuality();
+    rose.updateQuality();
+
+    assertThat(rose.items).extracting(item -> item.sellIn).containsExactly(8, 0, 3, 0, -1, 13, 8, 3);
+    assertThat(rose.items).extracting(item -> item.quality).containsExactly(18, 2, 5, 80, 80, 22, 50, 50);
+  }
+
+  @Test
+  void shouldBehaveLikeGoldenMaster() {
+    GildedRose rose = new GildedRose(ItemsProvider.get());
+    GildedRoseGolden golden = new GildedRoseGolden(ItemsProvider.get());
+
+    for (int day = 0; day < 100; day++) {
+      rose.updateQuality();
+      golden.updateQuality();
+
+      assertThat(rose.items)
+        .extracting(item -> item.sellIn)
+        .containsExactly(Arrays.stream(golden.items).map(item -> item.sellIn).toArray(Integer[]::new));
+      assertThat(rose.items)
+        .extracting(item -> item.quality)
+        .containsExactly(Arrays.stream(golden.items).map(item -> item.quality).toArray(Integer[]::new));
+    }
+  }
+}