adding first set of tests

This commit is contained in:
robbertvdzon 2022-05-08 08:38:24 +02:00
parent d20c40501b
commit f6aab4941b
10 changed files with 482 additions and 55 deletions

View File

@ -14,6 +14,7 @@ repositories {
dependencies { dependencies {
implementation(kotlin("stdlib")) implementation(kotlin("stdlib"))
testImplementation("org.junit.jupiter:junit-jupiter:5.8.2") testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")
testImplementation("org.assertj:assertj-core:3.22.0")
} }
tasks.test { tasks.test {

View File

@ -0,0 +1,58 @@
package com.gildedrose
class GildedRoseLegacy(var items: Array<Item>) {
fun updateQuality() {
for (i in items.indices) {
if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") {
if (items[i].quality > 0) {
if (items[i].name != "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 == "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 != "Sulfuras, Hand of Ragnaros") {
items[i].sellIn = items[i].sellIn - 1
}
if (items[i].sellIn < 0) {
if (items[i].name != "Aged Brie") {
if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") {
if (items[i].quality > 0) {
if (items[i].name != "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,108 @@
package com.gildedrose
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class GildedRoseAgedBrieTest : GildedRoseBaseTest() {
private val combinationsToTest = arrayOf(
// tests where sellIn and quality are initially the same
Arguments.of("Aged Brie", 5, 5, 1, 4, 6),
Arguments.of("Aged Brie", 5, 5, 2, 3, 7),
Arguments.of("Aged Brie", 5, 5, 3, 2, 8),
Arguments.of("Aged Brie", 5, 5, 4, 1, 9),
Arguments.of("Aged Brie", 5, 5, 5, 0, 10),// after here, the quality goes twice as fast
Arguments.of("Aged Brie", 5, 5, 6, -1, 12),
Arguments.of("Aged Brie", 5, 5, 7, -2, 14),
Arguments.of("Aged Brie", 5, 5, 8, -3, 16),
// skip a few days
Arguments.of("Aged Brie", 5, 5, 24, -19, 48),
Arguments.of("Aged Brie", 5, 5, 25, -20, 50),// after here, the quality stays as 50
Arguments.of("Aged Brie", 5, 5, 26, -21, 50),
Arguments.of("Aged Brie", 5, 5, 27, -22, 50),
// tests where sellIn is initially less then the quality
Arguments.of("Aged Brie", 5, 15, 1, 4, 16),
Arguments.of("Aged Brie", 5, 15, 2, 3, 17),
Arguments.of("Aged Brie", 5, 15, 3, 2, 18),
Arguments.of("Aged Brie", 5, 15, 4, 1, 19),
Arguments.of("Aged Brie", 5, 15, 5, 0, 20),// after here, the quality goes twice as fast
Arguments.of("Aged Brie", 5, 15, 6, -1, 22),
Arguments.of("Aged Brie", 5, 15, 7, -2, 24),
Arguments.of("Aged Brie", 5, 15, 8, -3, 26),
// skip a few days
Arguments.of("Aged Brie", 5, 15, 19, -14, 48),
Arguments.of("Aged Brie", 5, 15, 20, -15, 50),// after here, the quality stays as 50
Arguments.of("Aged Brie", 5, 15, 21, -16, 50),
Arguments.of("Aged Brie", 5, 15, 22, -17, 50),
// tests where sellIn is initially larger then the quality
Arguments.of("Aged Brie", 15, 5, 1, 14, 6),
Arguments.of("Aged Brie", 15, 5, 2, 13, 7),
Arguments.of("Aged Brie", 15, 5, 3, 12, 8),
Arguments.of("Aged Brie", 15, 5, 4, 11, 9),
Arguments.of("Aged Brie", 15, 5, 5, 10, 10),
Arguments.of("Aged Brie", 15, 5, 6, 9, 11),
Arguments.of("Aged Brie", 15, 5, 7, 8, 12),
Arguments.of("Aged Brie", 15, 5, 8, 7, 13),
// skip a few days
Arguments.of("Aged Brie", 15, 5, 13, 2, 18),
Arguments.of("Aged Brie", 15, 5, 14, 1, 19),
Arguments.of("Aged Brie", 15, 5, 15, 0, 20),// after here, the quality goes twice as fast
Arguments.of("Aged Brie", 15, 5, 16, -1, 22),
Arguments.of("Aged Brie", 15, 5, 17, -2, 24),
Arguments.of("Aged Brie", 15, 5, 29, -14, 48),
Arguments.of("Aged Brie", 15, 5, 30, -15, 50),// after here, the quality stays as 50
Arguments.of("Aged Brie", 15, 5, 31, -16, 50),
Arguments.of("Aged Brie", 15, 5, 32, -17, 50),
Arguments.of("Aged Brie", -1, 49, 1, -2, 50),
// tests other edge cases
Arguments.of("Aged Brie", -1, 15, 1, -2, 17),
Arguments.of("Aged Brie", -1, -10, 1, -2, -8),
Arguments.of("Aged Brie", -1, -1, 1, -2, 1),
Arguments.of("Aged Brie", -1, -2, 1, -2, 0),
Arguments.of("Aged Brie", -1, -2, 3, -4, 4),
Arguments.of("Aged Brie", 100, -1, 1, 99, 0),
Arguments.of("Aged Brie", 100, 100, 1, 99, 100),
Arguments.of("Aged Brie", 1, 0, 16, -15, 31),
)
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Legacy algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Legacy algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Refactored algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Refactored algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
fun combinationsSource(): Stream<Arguments> = Stream.of(*combinationsToTest)
}

View File

@ -0,0 +1,86 @@
package com.gildedrose
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class GildedRoseBackstageTest : GildedRoseBaseTest(){
private val combinationsToTest = arrayOf(
// tests where sellIn is initially less then the quality
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 1, 11, 26),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 2, 10, 27),// 10 days before concert, quality goes up by 2 each day
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 3, 9, 29),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 4, 8, 31),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 5, 7, 33),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 6, 6, 35),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 7, 5, 37),// 5 days before concert, quality goes up by 3 each day
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 8, 4, 40),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 9, 3, 43),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 10, 2, 46),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 11, 1, 49),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 12, 0, 50),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 13, -1, 0), // quality drops to zero after the concert
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 14, -2, 0),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 25, 100, -88, 0),
// tests where sellIn is initially larger then the quality
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 1, 11, 6),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 2, 10, 7),// 10 days before concert, quality goes up by 2 each day
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 3, 9, 9),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 4, 8, 11),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 5, 7, 13),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 6, 6, 15),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 7, 5, 17),// 5 days before concert, quality goes up by 3 each day
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 8, 4, 20),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 9, 3, 23),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 10, 2, 26),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 11, 1, 29),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 12, 0, 32),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 13, -1, 0), // quality drops to zero after the concert
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 14, -2, 0),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 5, 100, -88, 0),
// tests other edge cases
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 12, 45, 12, 0, 50),// quality is never above 50
Arguments.of("Backstage passes to a TAFKAL80ETC concert", -1, 45, 1, -2, 0),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", -1, 60, 1, -2, 0),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 10, 60, 1, 9, 60), // quality stays at 60
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 82, 78, 82, 0, 78),
Arguments.of("Backstage passes to a TAFKAL80ETC concert", 39, 17, 31, 8, 50),
)
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Legacy algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Legacy algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Refactored algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Refactored algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
fun combinationsSource(): Stream<Arguments> = Stream.of(*combinationsToTest)
}

View File

@ -0,0 +1,26 @@
package com.gildedrose
import org.assertj.core.api.Assertions
open class GildedRoseBaseTest {
fun testGildedRose(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
val item = Item(name, initialSellIn, initialQuality)
val items = arrayOf(item)
val app = GildedRose(items)
(1..numberDays).forEach() {
app.updateQuality()
}
Assertions.assertThat(item.name).isEqualTo(name)
Assertions.assertThat(item.sellIn).isEqualTo(resultingSellIn)
Assertions.assertThat(item.quality).isEqualTo(resultingQuality)
}
}

View File

@ -0,0 +1,84 @@
package com.gildedrose
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class GildedRoseDefaultTest : GildedRoseBaseTest(){
private val combinationsToTest = arrayOf(
// tests where sellIn and quality are initially the same
Arguments.of("foo", 5, 5, 1, 4, 4),
Arguments.of("foo", 5, 5, 2, 3, 3),
Arguments.of("foo", 5, 5, 3, 2, 2),
Arguments.of("foo", 5, 5, 4, 1, 1),
Arguments.of("foo", 5, 5, 5, 0, 0),// after here, the quality stays at 0
Arguments.of("foo", 5, 5, 6, -1, 0),
Arguments.of("foo", 5, 5, 7, -2, 0),
// tests where sellIn is initially less then the quality
Arguments.of("foo", 5, 15, 1, 4, 14),
Arguments.of("foo", 5, 15, 2, 3, 13),
Arguments.of("foo", 5, 15, 3, 2, 12),
Arguments.of("foo", 5, 15, 4, 1, 11),
Arguments.of("foo", 5, 15, 5, 0, 10),// after here, the quality goes twice at fast
Arguments.of("foo", 5, 15, 6, -1, 8),
Arguments.of("foo", 5, 15, 7, -2, 6),
Arguments.of("foo", 5, 15, 8, -3, 4),
Arguments.of("foo", 5, 15, 9, -4, 2),
Arguments.of("foo", 5, 15, 10, -5, 0),// after here, the quality stays at 0
Arguments.of("foo", 5, 15, 11, -6, 0),
Arguments.of("foo", 5, 15, 12, -7, 0),
// tests where sellIn is initially larger then the quality
Arguments.of("foo", 15, 5, 1, 14, 4),
Arguments.of("foo", 15, 5, 2, 13, 3),
Arguments.of("foo", 15, 5, 3, 12, 2),
Arguments.of("foo", 15, 5, 4, 11, 1),
Arguments.of("foo", 15, 5, 5, 10, 0),// after here, the quality stays at 0
Arguments.of("foo", 15, 5, 6, 9, 0),
Arguments.of("foo", 15, 5, 7, 8, 0),
// tests other edge cases
Arguments.of("foo", -1, 15, 1, -2, 13),
Arguments.of("foo", -1, -1, 1, -2, -1),
Arguments.of("foo", -1, -2, 1, -2, -2),
Arguments.of("foo", -1, -2, 3, -4, -2),
Arguments.of("foo", 100, -1, 1, 99, -1),
Arguments.of("foo", 100, 100, 1, 99, 99),
)
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Legacy algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Legacy algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Refactored algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Refactored algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
fun combinationsSource(): Stream<Arguments> = Stream.of(*combinationsToTest)
}

View File

@ -0,0 +1,49 @@
package com.gildedrose
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource
import java.util.stream.Stream
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class GildedRoseSulfurasTest : GildedRoseBaseTest(){
private val combinationsToTest = arrayOf(
Arguments.of("Sulfuras, Hand of Ragnaros", 5, 5, 1, 5, 5),// sellIn and quality always stays unchanged
Arguments.of("Sulfuras, Hand of Ragnaros", 5, 5, 2, 5, 5),// sellIn and quality always stays unchanged
Arguments.of("Sulfuras, Hand of Ragnaros", 5, 5, 100, 5, 5),// sellIn and quality always stays unchanged
Arguments.of("Sulfuras, Hand of Ragnaros", -1, 5, 1, -1, 5),// sellIn and quality always stays unchanged
Arguments.of("Sulfuras, Hand of Ragnaros", -1, -1, 1, -1, -1),// sellIn and quality always stays unchanged
Arguments.of("Sulfuras, Hand of Ragnaros", 100, -1, 1, 100, -1),// sellIn and quality always stays unchanged
Arguments.of("Sulfuras, Hand of Ragnaros", 100, 100, 1, 100, 100),// sellIn and quality always stays unchanged
)
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Legacy algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Legacy algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
@ParameterizedTest(name = "{0}: initial sellIn:{1} and initial quality:{2}, after {3} days: sellIn:{4} and quality {5}, using Refactored algorithm")
@MethodSource("combinationsSource")
fun `given input item, when some days are passed, then the item state is correctly modified, using Refactored algorithm`(
name: String,
initialSellIn: Int,
initialQuality: Int,
numberDays: Int,
resultingSellIn: Int,
resultingQuality: Int
) {
testGildedRose(name, initialSellIn, initialQuality, numberDays, resultingSellIn, resultingQuality)
}
fun combinationsSource(): Stream<Arguments> = Stream.of(*combinationsToTest)
}

View File

@ -1,19 +0,0 @@
package com.gildedrose
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
internal class GildedRoseTest {
@Test
fun foo() {
val items = arrayOf<Item>(Item("foo", 0, 0))
val app = GildedRose(items)
app.updateQuality()
assertEquals("fixme", app.items[0].name)
}
}

View File

@ -0,0 +1,70 @@
package com.gildedrose
import org.assertj.core.api.Assertions.assertThat
import kotlin.random.Random
/*
TODO:
- const voor maxNrDays, MaxNrItems, MaxInitialQuality, MaxInitialQuality
- run als unit test, draai 1 minuut, of 1.000.000 keer
- comment: deze kan flaky zijn, maar bij 1.000.000 is die kans wel erg klein
*/
val productLists = listOf(
"Aged Brie",
"Sulfuras, Hand of Ragnaros",
"Backstage passes to a TAFKAL80ETC concert",
"Foo"
)
val random = Random(System.currentTimeMillis())
fun main(args: Array<String>) {
(0..Int.MAX_VALUE).forEach(){
val nrItemsToTest = random.nextInt(1,5)
val nrDays = random.nextInt(1,100)
val initialItems = createRandomItemList(nrItemsToTest)
val legacyItems = initialItems.deepClone()
val refacturedItems = legacyItems.deepClone()
val legacyApp = GildedRoseLegacy(legacyItems)
val refactoredApp = GildedRose(refacturedItems)
println("testing round $it, with $nrItemsToTest items and $nrDays days")
(1..nrDays).forEach {
legacyApp.updateQuality()
refactoredApp.updateQuality()
}
val testDescription : String = describeTestcase(initialItems, nrDays, refactoredApp.items, legacyApp.items)
val actialItemsAsString = describeItems(refactoredApp.items)
val expectedItemsAsString = describeItems(legacyApp.items)
assertThat(actialItemsAsString).`as`("The following testcase failed: \n$testDescription").isEqualTo(expectedItemsAsString)
}
}
fun describeTestcase(initialItems: Array<Item>, nrDays: Int, actualItems: Array<Item>, expectedItems: Array<Item>) =
"Initial items: \n${describeItems(initialItems)}\n\n"+
"expected items after $nrDays days:\n"+
"${describeItems(expectedItems)}\n\n"+
"actual items after $nrDays days:\n"+
describeItems(actualItems)
fun describeItems(items: Array<Item>) = items.map { " -${it.name}: sellIn:${it.sellIn} quality:${it.quality}" }.joinToString("\n")
private fun createRandomItem(): Item{
val nameIndex = random.nextInt(productLists.size)
val name = productLists[nameIndex]
val sellIn =random.nextInt(-10, 100)
val quality = random.nextInt(100)
return Item(name,sellIn,quality)
}
private fun Item.clone() = Item(name,sellIn,quality)
private fun Array<Item>.deepClone() = map { it.clone() } .toTypedArray()
private fun createRandomItemList(count: Int) = (0..count).map { createRandomItem() }.toTypedArray()

View File

@ -1,36 +0,0 @@
package com.gildedrose
fun main(args: Array<String>) {
println("OMGHAI!")
val items = arrayOf(Item("+5 Dexterity Vest", 10, 20), //
Item("Aged Brie", 2, 0), //
Item("Elixir of the Mongoose", 5, 7), //
Item("Sulfuras, Hand of Ragnaros", 0, 80), //
Item("Sulfuras, Hand of Ragnaros", -1, 80),
Item("Backstage passes to a TAFKAL80ETC concert", 15, 20),
Item("Backstage passes to a TAFKAL80ETC concert", 10, 49),
Item("Backstage passes to a TAFKAL80ETC concert", 5, 49),
// this conjured item does not work properly yet
Item("Conjured Mana Cake", 3, 6))
val app = GildedRose(items)
var days = 2
if (args.size > 0) {
days = Integer.parseInt(args[0]) + 1
}
for (i in 0..days - 1) {
println("-------- day $i --------")
println("name, sellIn, quality")
for (item in items) {
println(item)
}
println()
app.updateQuality()
}
}