diff --git a/exercises/practice/forth/build.gradle.kts b/exercises/practice/forth/build.gradle.kts index 3db5dc4f..87bafbd2 100644 --- a/exercises/practice/forth/build.gradle.kts +++ b/exercises/practice/forth/build.gradle.kts @@ -10,12 +10,12 @@ repositories { dependencies { implementation(kotlin("stdlib-jdk8")) - - testImplementation("junit:junit:4.13.2") - testImplementation(kotlin("test-junit")) + + testImplementation(kotlin("test")) } tasks.withType { + useJUnitPlatform() testLogging { exceptionFormat = TestExceptionFormat.FULL events("passed", "failed", "skipped") diff --git a/exercises/practice/forth/gradle/wrapper/gradle-wrapper.properties b/exercises/practice/forth/gradle/wrapper/gradle-wrapper.properties index e750102e..070cb702 100644 --- a/exercises/practice/forth/gradle/wrapper/gradle-wrapper.properties +++ b/exercises/practice/forth/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/exercises/practice/forth/src/test/kotlin/ForthTest.kt b/exercises/practice/forth/src/test/kotlin/ForthTest.kt index dd49a88d..23a95901 100644 --- a/exercises/practice/forth/src/test/kotlin/ForthTest.kt +++ b/exercises/practice/forth/src/test/kotlin/ForthTest.kt @@ -1,219 +1,288 @@ -import org.junit.Rule -import org.junit.rules.ExpectedException +import org.junit.jupiter.api.Nested import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFails -abstract class ForthTest { - - @Rule - @JvmField - var expectedException = ExpectedException.none() - - class ParsingAndNumbersTest : ForthTest() { +@Nested +class ForthTest { + @Nested + inner class ParsingAndNumbersTest { @Test - fun `numbers just get pushed onto the stack`() = assertEquals(listOf(1, 2, 3, 4, 5), Forth().evaluate("1 2 3 4 5")) + fun `numbers just get pushed onto the stack`() = + assertEquals(listOf(1, 2, 3, 4, 5), Forth().evaluate("1 2 3 4 5")) } - class Addition : ForthTest() { + @Nested + inner class Addition { @Test fun `can add two numbers`() = assertEquals(listOf(3), Forth().evaluate("1 2 +")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("+") + val ex = assertFails { Forth().evaluate("+") } + assertEquals("empty stack", ex.message) } @Test fun `errors if there is only one value on the stack`() { - expectedException.expectMessage("only one value on the stack") - Forth().evaluate("1 +") + val ex = assertFails { Forth().evaluate("1 +") } + assertEquals("only one value on the stack", ex.message) } } - class Subtraction : ForthTest() { + @Nested + inner class Subtraction { @Test fun `can subtract two numbers`() = assertEquals(listOf(-1), Forth().evaluate("3 4 -")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("-") + val ex = assertFails { Forth().evaluate("-") } + assertEquals("empty stack", ex.message) } @Test fun `errors if there is only one value on the stack`() { - expectedException.expectMessage("only one value on the stack") - Forth().evaluate("1 -") + val ex = assertFails { Forth().evaluate("1 -") } + assertEquals("only one value on the stack", ex.message) } } - class Multiplication : ForthTest() { + @Nested + inner class Multiplication { @Test - fun `can multiply two numbers`() = assertEquals(listOf(8), Forth().evaluate("2 4 *")) + fun `can multiply two numbers`() = + assertEquals(listOf(8), Forth().evaluate("2 4 *")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("*") + val ex = assertFails { + Forth().evaluate("*") + } + assertEquals("empty stack", ex.message) } @Test fun `errors if there is only one value on the stack`() { - expectedException.expectMessage("only one value on the stack") - Forth().evaluate("1 *") + val ex = assertFails { + Forth().evaluate("1 *") + } + assertEquals("only one value on the stack", ex.message) } } - class Division : ForthTest() { + @Nested + inner class Division { @Test - fun `can divide two numbers`() = assertEquals(listOf(4), Forth().evaluate("12 3 /")) + fun `can divide two numbers`() = + assertEquals(listOf(4), Forth().evaluate("12 3 /")) @Test - fun `performs integer division`() = assertEquals(listOf(2), Forth().evaluate("8 3 /")) + fun `performs integer division`() = + assertEquals(listOf(2), Forth().evaluate("8 3 /")) @Test fun `errors if dividing by zero`() { - expectedException.expectMessage("divide by zero") - Forth().evaluate("4 0 /") + val ex = assertFails { Forth().evaluate("4 0 /") } + assertEquals("divide by zero", ex.message) } @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("/") + val ex = assertFails { Forth().evaluate("/") } + assertEquals("empty stack", ex.message) } @Test fun `errors if there is only one value on the stack`() { - expectedException.expectMessage("only one value on the stack") - Forth().evaluate("1 /") + val ex = assertFails { Forth().evaluate("1 /") } + assertEquals("only one value on the stack", ex.message) } } - class CombinedArithmetic : ForthTest() { + @Nested + inner class CombinedArithmetic { @Test - fun `addition and subtraction`() = assertEquals(listOf(-1), Forth().evaluate("1 2 + 4 -")) + fun `addition and subtraction`() = + assertEquals(listOf(-1), Forth().evaluate("1 2 + 4 -")) @Test - fun `multiplication and division`() = assertEquals(listOf(2), Forth().evaluate("2 4 * 3 /")) + fun `multiplication and division`() = + assertEquals(listOf(2), Forth().evaluate("2 4 * 3 /")) } - class Dup : ForthTest() { + @Nested + inner class Dup { @Test - fun `copies a value on the stack`() = assertEquals(listOf(1, 1), Forth().evaluate("1 dup")) + fun `copies a value on the stack`() = + assertEquals(listOf(1, 1), Forth().evaluate("1 dup")) @Test - fun `copies the top value on the stack`() = assertEquals(listOf(1, 2, 2), Forth().evaluate("1 2 dup")) + fun `copies the top value on the stack`() = + assertEquals(listOf(1, 2, 2), Forth().evaluate("1 2 dup")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("dup") + val ex = assertFails { Forth().evaluate("dup") } + assertEquals("empty stack", ex.message) } } - class Drop : ForthTest() { + @Nested + inner class Drop { @Test - fun `removes the top value on the stack if it is the only one`() = assertEquals(listOf(), Forth().evaluate("1 drop")) + fun `removes the top value on the stack if it is the only one`() = + assertEquals(emptyList(), Forth().evaluate("1 drop")) @Test - fun `removes the top value on the stack if it is not the only one`() = assertEquals(listOf(1), Forth().evaluate("1 2 drop")) + fun `removes the top value on the stack if it is not the only one`() = + assertEquals(listOf(1), Forth().evaluate("1 2 drop")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("drop") + val ex = assertFails { Forth().evaluate("drop") } + assertEquals("empty stack", ex.message) } } - class Swap : ForthTest() { + @Nested + inner class Swap { @Test - fun `swaps the top two values on the stack if they are the only ones`() = assertEquals(listOf(2, 1), Forth().evaluate("1 2 swap")) + fun `swaps the top two values on the stack if they are the only ones`() = + assertEquals(listOf(2, 1), Forth().evaluate("1 2 swap")) @Test - fun `swaps the top two values on the stack if they are not the only ones`() = assertEquals(listOf(1, 3, 2), Forth().evaluate("1 2 3 swap")) + fun `swaps the top two values on the stack if they are not the only ones`() = + assertEquals(listOf(1, 3, 2), Forth().evaluate("1 2 3 swap")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("swap") + val ex = assertFails { Forth().evaluate("swap") } + assertEquals("empty stack", ex.message) } @Test fun `errors if there is only one value on the stack`() { - expectedException.expectMessage("only one value on the stack") - Forth().evaluate("1 swap") + val ex = assertFails { Forth().evaluate("1 swap") } + assertEquals("only one value on the stack", ex.message) } } - class Over : ForthTest() { + @Nested + inner class Over { @Test - fun `copies the second element if there are only two`() = assertEquals(listOf(1, 2, 1), Forth().evaluate("1 2 over")) + fun `copies the second element if there are only two`() = + assertEquals(listOf(1, 2, 1), Forth().evaluate("1 2 over")) @Test - fun `copies the second element if there are more than two`() = assertEquals(listOf(1, 2, 3, 2), Forth().evaluate("1 2 3 over")) + fun `copies the second element if there are more than two`() = + assertEquals(listOf(1, 2, 3, 2), Forth().evaluate("1 2 3 over")) @Test fun `errors if there is nothing on the stack`() { - expectedException.expectMessage("empty stack") - Forth().evaluate("over") + val ex = assertFails { Forth().evaluate("over") } + assertEquals("empty stack", ex.message) } @Test fun `errors if there is only one value on the stack`() { - expectedException.expectMessage("only one value on the stack") - Forth().evaluate("1 over") + val ex = assertFails { Forth().evaluate("1 over") } + assertEquals("only one value on the stack", ex.message) } } - class UserDefinedWords : ForthTest() { + @Nested + inner class UserDefinedWords { @Test - fun `can consist of built-in words`() = assertEquals(listOf(1, 1, 1), Forth().evaluate(": dup-twice dup dup ;", "1 dup-twice")) + fun `can consist of built-in words`() = assertEquals( + listOf(1, 1, 1), + Forth().evaluate( + ": dup-twice dup dup ;", + "1 dup-twice", + ) + ) @Test - fun `execute in the right order`() = assertEquals(listOf(1, 2, 3), Forth().evaluate(": countup 1 2 3 ;", "countup")) + fun `execute in the right order`() = assertEquals( + listOf(1, 2, 3), + Forth().evaluate( + ": countup 1 2 3 ;", + "countup", + ) + ) @Test - fun `can override other user-defined words`() = assertEquals(listOf(1, 1, 1), Forth().evaluate(": foo dup ;", ": foo dup dup ;", "1 foo")) + fun `can override other user-defined words`() = + assertEquals( + listOf(1, 1, 1), + Forth().evaluate( + ": foo dup ;", + ": foo dup dup ;", + "1 foo", + ) + ) @Test - fun `can override built-in words`() = assertEquals(listOf(1, 1), Forth().evaluate(": swap dup ;", "1 swap")) + fun `can override built-in words`() = assertEquals( + listOf(1, 1), Forth().evaluate( + ": swap dup ;", + "1 swap", + ) + ) @Test - fun `can override built-in operators`() = assertEquals(listOf(12), Forth().evaluate(": + * ;", "3 4 +")) + fun `can override built-in operators`() = assertEquals( + listOf(12), Forth().evaluate( + ": + * ;", + "3 4 +", + ) + ) @Test - fun `can use different words with the same name`() = assertEquals(listOf(5, 6), Forth().evaluate(": foo 5 ;", ": bar foo ;", ": foo 6 ;", "bar foo")) + fun `can use different words with the same name`() = assertEquals( + listOf(5, 6), Forth().evaluate( + ": foo 5 ;", + ": bar foo ;", + ": foo 6 ;", + "bar foo", + ) + ) @Test - fun `can define word that uses word with the same name`() = assertEquals(listOf(11), Forth().evaluate(": foo 10 ;", ": foo foo 1 + ;", "foo")) + fun `can define word that uses word with the same name`() = assertEquals( + listOf(11), Forth().evaluate( + ": foo 10 ;", + ": foo foo 1 + ;", + "foo", + ) + ) @Test fun `cannot redefine numbers`() { - expectedException.expectMessage("illegal operation") - Forth().evaluate(": 1 2 ;") + val ex = assertFails { Forth().evaluate(": 1 2 ;") } + assertEquals("illegal operation", ex.message) } @Test fun `errors if executing a non-existent word`() { - expectedException.expectMessage("undefined operation") - Forth().evaluate("foo") + val ex = assertFails { Forth().evaluate("foo") } + assertEquals("undefined operation", ex.message) } } - class CaseInsensitivity : ForthTest() { + @Nested + inner class CaseInsensitivity { @Test fun `DUP is case-insensitive`() = assertEquals(listOf(1, 1, 1, 1), Forth().evaluate("1 DUP Dup dup")) @@ -228,9 +297,18 @@ abstract class ForthTest { fun `OVER is case-insensitive`() = assertEquals(listOf(1, 2, 1, 2, 1), Forth().evaluate("1 2 OVER Over over")) @Test - fun `user-defined words are case-insensitive`() = assertEquals(listOf(1, 1, 1, 1), Forth().evaluate(": foo dup ;", "1 FOO Foo foo")) + fun `user-defined words are case-insensitive`() = + assertEquals( + listOf(1, 1, 1, 1), + Forth().evaluate(": foo dup ;", "1 FOO Foo foo") + ) @Test - fun `definitions are case-insensitive`() = assertEquals(listOf(1, 1, 1, 1), Forth().evaluate(": SWAP DUP Dup dup ;", "1 swap")) + fun `definitions are case-insensitive`() = assertEquals( + listOf(1, 1, 1, 1), Forth().evaluate( + ": SWAP DUP Dup dup ;", + "1 swap", + ) + ) } }