Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JVM Test framework #541

Merged
merged 8 commits into from
Jan 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
37 changes: 37 additions & 0 deletions 00_Utilities/jvmTestUtils/kotlin/test/ConsoleTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.pcholt.console.testutils

import com.google.common.truth.Truth
import org.junit.Rule
import org.junit.contrib.java.lang.system.SystemOutRule
import org.junit.contrib.java.lang.system.TextFromStandardInputStream

abstract class ConsoleTest {
@get:Rule
val inputRule = TextFromStandardInputStream.emptyStandardInputStream()

@get:Rule
val systemOutRule = SystemOutRule().enableLog()

val regexInputCommand = "\\{(.*)}".toRegex()

fun assertConversation(conversation: String, runMain: () -> Unit) {

inputRule.provideLines(*regexInputCommand
.findAll(conversation)
.map { it.groupValues[1] }
.toList().toTypedArray())

runMain()

Truth.assertThat(
systemOutRule.log.trimWhiteSpace()
)
.isEqualTo(
regexInputCommand
.replace(conversation, "").trimWhiteSpace()
)
}

private fun String.trimWhiteSpace() =
replace("[\\s]+".toRegex(), " ")
}
6 changes: 3 additions & 3 deletions 03_Animal/java/Animal.java → 03_Animal/java/src/Animal.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ public static void main(String[] args) {
private static void askForInformationAndSave(Scanner scan, AnimalNode current, QuestionNode previous, boolean previousToCurrentDecisionChoice) {
//Failed to get it right and ran out of questions
//Let's ask the user for the new information
System.out.print("THE ANIMAL YOU WERE THINKING OF WAS A ");
System.out.print("THE ANIMAL YOU WERE THINKING OF WAS A ? ");
String animal = scan.nextLine();
System.out.printf("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A %s FROM A %s ", animal, current.getAnimal());
System.out.printf("PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A %s FROM A %s ? ", animal, current.getAnimal());
String newQuestion = scan.nextLine();
System.out.printf("FOR A %s THE ANSWER WOULD BE ", animal);
System.out.printf("FOR A %s THE ANSWER WOULD BE ? ", animal);
boolean newAnswer = readYesOrNo(scan);
//Add it to our question store
addNewAnimal(current, previous, animal, newQuestion, newAnswer, previousToCurrentDecisionChoice);
Expand Down
55 changes: 55 additions & 0 deletions 03_Animal/java/test/AnimalJavaTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import com.pcholt.console.testutils.ConsoleTest
import org.junit.Test

class AnimalJavaTest : ConsoleTest() {

@Test
fun `given a standard setup, find the fish`() {
assertConversation(
"""
$title
ARE YOU THINKING OF AN ANIMAL ? {YES}
DOES IT SWIM ? {YES}
IS IT A FISH ? {YES}
WHY NOT TRY ANOTHER ANIMAL?
ARE YOU THINKING OF AN ANIMAL ? {QUIT}
"""
) {
Animal.main(emptyArray())
}
}

@Test
fun `given a standard setup, create a cow, and verify`() {
assertConversation(
"""
$title
ARE YOU THINKING OF AN ANIMAL ? {YES}
DOES IT SWIM ? {NO}
IS IT A BIRD ? {NO}
THE ANIMAL YOU WERE THINKING OF WAS A ? {COW}
PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
COW FROM A BIRD
? {DOES IT EAT GRASS}
FOR A COW THE ANSWER WOULD BE ? {YES}
ARE YOU THINKING OF AN ANIMAL ? {YES}
DOES IT SWIM ? {NO}
DOES IT EAT GRASS ? {YES}
IS IT A COW ? {YES}
WHY NOT TRY ANOTHER ANIMAL?
ARE YOU THINKING OF AN ANIMAL ? {QUIT}
"""
) {
Animal.main(emptyArray())
}
}

private val title = """
ANIMAL
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY

PLAY 'GUESS THE ANIMAL'
THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.
"""
}

File renamed without changes.
55 changes: 55 additions & 0 deletions 03_Animal/kotlin/test/AnimalKtTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import com.pcholt.console.testutils.ConsoleTest
import org.junit.Test

class AnimalKtTest : ConsoleTest() {

@Test
fun `given a standard setup, find the fish`() {
assertConversation(
"""
$title
ARE YOU THINKING OF AN ANIMAL? {YES}
DOES IT SWIM? {YES}
IS IT A FISH? {YES}
WHY NOT TRY ANOTHER ANIMAL?
ARE YOU THINKING OF AN ANIMAL? {QUIT}
"""
) {
main()
}
}

@Test
fun `given a standard setup, create a cow, and verify`() {
assertConversation(
"""
$title
ARE YOU THINKING OF AN ANIMAL? {YES}
DOES IT SWIM? {NO}
IS IT A BIRD? {NO}
THE ANIMAL YOU WERE THINKING OF WAS A? {COW}
PLEASE TYPE IN A QUESTION THAT WOULD DISTINGUISH A
COW FROM A BIRD
? {DOES IT EAT GRASS}
FOR A COW THE ANSWER WOULD BE? {YES}
ARE YOU THINKING OF AN ANIMAL? {YES}
DOES IT SWIM? {NO}
DOES IT EAT GRASS? {YES}
IS IT A COW? {YES}
WHY NOT TRY ANOTHER ANIMAL?
ARE YOU THINKING OF AN ANIMAL? {QUIT}
"""
) {
main()
}
}

private val title = """
ANIMAL
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY

PLAY 'GUESS THE ANIMAL'
THINK OF AN ANIMAL AND THE COMPUTER WILL TRY TO GUESS IT.
"""
}

101 changes: 91 additions & 10 deletions buildJvm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,16 @@ directory for the java or kotlin file, and the class that contains the `main` me
The `build.gradle` file **should** be identical to all the other `build.gradle` files
in all the other subprojects:
```groovy
sourceSets {
main {
java {
srcDirs "../../$gameSource"
}
}
}
application {
mainClass = gameMain
}
sourceSets {
main {
java {
srcDirs "../../$gameSource"
}
}
}
application {
mainClass = gameMain
}
```

The `gradle.properties` file should look like this:
Expand All @@ -92,3 +92,84 @@ project to the list.
```groovy
include ":build_91_Train_java"
```

### Adding a game with tests

You can add tests for JVM games with a `build.gradle` looking a little different.
Use the build files from `03_Animal` as a template to add tests:

```groovy
sourceSets {
main {
java {
srcDirs "../../$gameSource"
}
}
test {
java {
srcDirs "../../$gameTest"
}
}
}

application {
mainClass = gameMain
}

dependencies {
testImplementation(project(":build_00_utilities").sourceSets.test.output)
}
```

The gradle.properties needs an additional directory name for the tests, as `gameTest` :
```
gameSource=03_Animal/java/src
gameTest=03_Animal/java/test
gameMain=Animal
```

Each project should have its own test, and shouldn't share test source directories
with other projects, even if they are for the same game.

Tests are constructed by subclassing `ConsoleTest`. This allows you to use the
`assertConversation` function to check for correct interactive conversations.
```kotlin
import com.pcholt.console.testutils.ConsoleTest
import org.junit.Test

class AnimalJavaTest : ConsoleTest() {
@Test
fun `should have a simple conversation`() {
assertConversation(
"""
WHAT'S YOUR NAME? {PAUL}
YOUR NAME IS PAUL? {YES}
THANKS FOR PLAYING
"""
) {
// The game's Main method
main()
}
}
}
```

Curly brackets are the expected user input.
Note - this is actually just a way of defining the expected input as "PAUL" and "YES"
and not that the input happens at the exact prompt position. Thus this is equivalent:
```kotlin
"""
{PAUL} {YES} WHAT'S YOUR NAME?
YOUR NAME IS PAUL?
THANKS FOR PLAYING
"""
```

Amounts of whitespace are not counted, but whitespace is significant: You will get a failure if
your game emits `"NAME?"` when it expects `"NAME ?"`.

Run all the tests from within the buildJvm project directory:
```bash
cd buildJvm
./gradlew test
```
22 changes: 15 additions & 7 deletions buildJvm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ version = "unspecified"

repositories {
mavenCentral()
google()
}

dependencies {
implementation(kotlin("stdlib"))
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

task("distributeBin", Copy::class) {
from(filesType("bin"))
Expand All @@ -43,9 +39,21 @@ task("copyAll") {
subprojects {
apply(plugin = "application")
apply(plugin = "kotlin")
repositories {
mavenCentral()
apply(plugin = "java")
repositories {
mavenCentral()
}
dependencies {
testImplementation("junit:junit:4.13.2")
testImplementation("com.github.stefanbirkner:system-rules:1.19.0")
testImplementation("com.google.truth:truth:1.1.3")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

}

fun filesType(type: String) =
Expand Down
7 changes: 7 additions & 0 deletions buildJvm/build_00_utilities/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
sourceSets {
test {
java {
srcDirs "../../$testSource"
}
}
}
1 change: 1 addition & 0 deletions buildJvm/build_00_utilities/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
testSource=00_Utilities/jvmTestUtils/kotlin/test
11 changes: 11 additions & 0 deletions buildJvm/build_01_Acey_Ducey_java17/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
sourceSets {
main {
java {
srcDirs "../../$gameSource"
}
}
}

application {
mainClass = gameMain
}
2 changes: 2 additions & 0 deletions buildJvm/build_01_Acey_Ducey_java17/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
gameSource=01_Acey_Ducey/java/src
gameMain=AceyDucey17
9 changes: 9 additions & 0 deletions buildJvm/build_03_Animal_java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ sourceSets {
srcDirs "../../$gameSource"
}
}
test {
java {
srcDirs "../../$gameTest"
}
}
}

application {
mainClass = gameMain
}

dependencies {
testImplementation(project(":build_00_utilities").sourceSets.test.output)
}
3 changes: 2 additions & 1 deletion buildJvm/build_03_Animal_java/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
gameSource=03_Animal/java
gameSource=03_Animal/java/src
gameTest=03_Animal/java/test
gameMain=Animal
9 changes: 9 additions & 0 deletions buildJvm/build_03_Animal_kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ sourceSets {
srcDirs "../../$gameSource"
}
}
test {
java {
srcDirs "../../$gameTest"
}
}
}

application {
mainClass = gameMain
}

dependencies {
testImplementation(project(":build_00_utilities").sourceSets.test.output)
}
3 changes: 2 additions & 1 deletion buildJvm/build_03_Animal_kotlin/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
gameSource=03_Animal/kotlin
gameSource=03_Animal/kotlin/src
gameTest=03_Animal/kotlin/test
gameMain=AnimalKt