diff --git a/scala/.gitignore b/scala/.gitignore index 5534fac1..ec0b3283 100644 --- a/scala/.gitignore +++ b/scala/.gitignore @@ -1,4 +1,5 @@ /bin/ +lib/ # OSX Finder .DS_Store @@ -6,6 +7,17 @@ # IntelliJ .idea *.iml +.bsp +.bloop + +#vscode +.vscode +.metals +.scala-build +metals.sbt + + + # Eclipse .worksheet @@ -17,3 +29,4 @@ .classpath target/ +approvaltests/gildedrose.testresult.txt diff --git a/scala/README.md b/scala/README.md index d8f35317..73c9a7c6 100644 --- a/scala/README.md +++ b/scala/README.md @@ -20,3 +20,26 @@ sbt "run 10" ``` cmd sbt test ``` + +## Run approval tests + +The approval test can be found in the src/test/scala/GildedRoseApprovalTest.scala. It uses the approval test framework from https://github.com/approvals/ApprovalTests.Java. + +The initial run will be a failing test and suggests an output to accept as the first approved version. Each subsequent run of the test will succeed until the output from the test changes. + +To approve a new version, simply accept some or all diffs between the existing approved files and the newly generated output. + +Approval tests are part of the test suite triggered by "sbt test". + +``` cmd +sbt test +``` + +## Run texttest version of approval tests + +To run the texttest version, first edit the texttest configuration file. It contains to sections for scala that need to be uncommented. + +* the executable and interpreter lines to run texttest_rig.py to trigger an sbt run +* the four lines in the run_dependent_text section to ignore sbt's info and success lines in the output. + +Be aware that running the texttest version is somewhat slow since starting sbt takes some time. \ No newline at end of file diff --git a/scala/build.sbt b/scala/build.sbt index 51404b8c..91a88ae6 100644 --- a/scala/build.sbt +++ b/scala/build.sbt @@ -1,11 +1,15 @@ -val scala3Version = "3.6.4" +val scala3Version = "3.7.3" lazy val root = project .in(file(".")) .settings( - name := "GildedRose", - version := "1.0", - scalaVersion := scala3Version, - - libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.19" % "test" + name := "GildedRose", + version := "1.0", + scalaVersion := scala3Version, + libraryDependencies ++= Seq( + "org.scalatest" %% "scalatest" % "3.2.19" % Test, + "com.approvaltests" % "approvaltests" % "25.4.3" % Test, + "com.github.sbt.junit" % "jupiter-interface" % "0.15.1" % Test + ), + testOptions += Tests.Argument(TestFrameworks.JUnit) ) diff --git a/scala/project/.gitignore b/scala/project/.gitignore deleted file mode 100644 index 6ba19f7f..00000000 --- a/scala/project/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -project/ -target/ diff --git a/scala/project/build.properties b/scala/project/build.properties index e97b2722..5e6884d3 100644 --- a/scala/project/build.properties +++ b/scala/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.10 +sbt.version=1.11.6 diff --git a/scala/project/plugins.sbt b/scala/project/plugins.sbt new file mode 100644 index 00000000..82244db7 --- /dev/null +++ b/scala/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.github.sbt.junit" % "sbt-jupiter-interface" % "0.15.1") diff --git a/scala/src/main/scala/com/gildedrose/Item.scala b/scala/src/main/scala/com/gildedrose/Item.scala index 8515ced7..ed4a21f3 100644 --- a/scala/src/main/scala/com/gildedrose/Item.scala +++ b/scala/src/main/scala/com/gildedrose/Item.scala @@ -1,5 +1,5 @@ package com.gildedrose -class Item(val name: String, var sellIn: Int, var quality: Int) { +case class Item(name: String, var sellIn: Int, var quality: Int) { } \ No newline at end of file diff --git a/scala/src/main/scala/com/gildedrose/Main.scala b/scala/src/main/scala/com/gildedrose/Main.scala index fbd1cd9b..bd943be9 100644 --- a/scala/src/main/scala/com/gildedrose/Main.scala +++ b/scala/src/main/scala/com/gildedrose/Main.scala @@ -3,16 +3,16 @@ package com.gildedrose object Main { def main(args: Array[String]): Unit = { val items = Array[Item]( - new Item("+5 Dexterity Vest", 10, 20), - new Item("Aged Brie", 2, 0), - new Item("Elixir of the Mongoose", 5, 7), - new Item("Sulfuras, Hand of Ragnaros", 0, 80), - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + 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 - new Item("Conjured Mana Cake", 3, 6) + Item("Conjured Mana Cake", 3, 6) ) val app = new GildedRose(items) diff --git a/scala/src/test/scala/com/gildedrose/GildedRoseApprovalTest.scala b/scala/src/test/scala/com/gildedrose/GildedRoseApprovalTest.scala new file mode 100644 index 00000000..b9dd58ef --- /dev/null +++ b/scala/src/test/scala/com/gildedrose/GildedRoseApprovalTest.scala @@ -0,0 +1,38 @@ +package com.gildedrose + +import org.approvaltests.Approvals +import org.approvaltests.reporters.DiffReporter +import org.approvaltests.reporters.UseReporter +import org.junit.jupiter.api.Test + +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.PrintStream + +@UseReporter(Array(classOf[DiffReporter])) +class GildedRoseApprovalTest { + + @Test + def foo(): Unit = { + + val items: Array[Item] = Array(Item("foo", 0, 0)) + val app: GildedRose = new GildedRose(items) + app.updateQuality() + + Approvals.verifyAll("Items", items) + } + + @Test + def thirtyDays(): Unit = { + + val fakeoutput: ByteArrayOutputStream = new ByteArrayOutputStream() + System.setOut(new PrintStream(fakeoutput)) + System.setIn(new ByteArrayInputStream("a\n".getBytes())) + + val args: Array[String] = Array("30") + TexttestFixture.main(args) + val output: String = fakeoutput.toString() + + Approvals.verify(output) + } +} \ No newline at end of file diff --git a/scala/src/test/scala/com/gildedrose/GildedRoseTest.scala b/scala/src/test/scala/com/gildedrose/GildedRoseTest.scala index 6d8c1732..a4a3d902 100644 --- a/scala/src/test/scala/com/gildedrose/GildedRoseTest.scala +++ b/scala/src/test/scala/com/gildedrose/GildedRoseTest.scala @@ -4,10 +4,10 @@ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class GildedRoseTest extends AnyFlatSpec with Matchers { - it should "foo" in { - val items = Array[Item](new Item("foo", 0, 0)) - val app = new GildedRose(items) - app.updateQuality() - app.items(0).name should equal ("fixme") - } + it should "foo" in { + val items = Array[Item](Item("foo", 0, 0)) + val app = new GildedRose(items) + app.updateQuality() + app.items(0).name should equal("fixme") + } } diff --git a/scala/src/test/scala/com/gildedrose/TexttestFixture.scala b/scala/src/test/scala/com/gildedrose/TexttestFixture.scala new file mode 100644 index 00000000..4e6fc7f4 --- /dev/null +++ b/scala/src/test/scala/com/gildedrose/TexttestFixture.scala @@ -0,0 +1,34 @@ +package com.gildedrose + +object TexttestFixture { + def main(args: Array[String]): Unit = { + System.out.println("OMGHAI!") + + val items = Array[Item]( + 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 = new GildedRose(items) + var days = 2 + + if (args.nonEmpty) days = args(0).toInt + 1 + + for (i <- 0 until days) { + System.out.println("-------- day " + i + " --------") + System.out.println("name, sellIn, quality") + for (item <- items) { + System.out.println(s"${item.name}, ${item.sellIn}, ${item.quality}") + } + System.out.println() + app.updateQuality() + } + } +} diff --git a/scala/texttest_rig.py b/scala/texttest_rig.py new file mode 100644 index 00000000..c4302638 --- /dev/null +++ b/scala/texttest_rig.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +""" +This script uses sbt to execute the TexttestFixture. +It is designed to be used by TextTest and specified in the file 'texttests/config.gr' in this repo. +It is more convenient for TextTest to use since Gradle needs +several arguments in addition to the one the TextTest fixture needs. +""" +import os +import subprocess +import sys + +args = " ".join(sys.argv[1:]) +TEXTTEST_HOME = os.environ.get("TEXTTEST_HOME", os.getcwd()) +subprocess.run(f"""(cd {TEXTTEST_HOME}/scala/; sbt -warn "Test / runMain com.gildedrose.TexttestFixture {args}") """, shell=True) diff --git a/texttests/config.gr b/texttests/config.gr index 8716d11d..8bafed03 100755 --- a/texttests/config.gr +++ b/texttests/config.gr @@ -70,4 +70,10 @@ interpreter:ruby # Settings for the Odin version #executable:${TEXTTEST_HOME}/odin/gilded_rose + +# Settings for the scala version using sbt wrapped in a python script +# executable:${TEXTTEST_HOME}/scala/texttest_rig.py +# interpreter:python + + filename_convention_scheme:standard