Skip to content

Commit

Permalink
Support nullable parameters (#56)
Browse files Browse the repository at this point in the history
* Support nullable parameters

Closes: #42

* Test nullable burstValues

---------

Co-authored-by: Jesse Wilson <[email protected]>
  • Loading branch information
swankjesse and squarejesse authored Oct 30, 2024
1 parent e0674da commit a856a66
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 24 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class DrinkSodaTest(
}
```

If the parameter is nullable, Burst will also test with null.

### Multiple Parameters

Use multiple parameters to test all variations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class BurstKotlinPluginTest {
assertEquals(KotlinCompilation.ExitCode.COMPILATION_ERROR, result.exitCode, result.messages)
assertThat(result.messages).contains(
"CoffeeTest.kt:7:12 " +
"@Burst parameter must be a boolean, enum, or have a burstValues() default value",
"@Burst parameter must be a boolean, an enum, or have a burstValues() default value",
)
}

Expand Down Expand Up @@ -135,7 +135,7 @@ class BurstKotlinPluginTest {
assertEquals(KotlinCompilation.ExitCode.COMPILATION_ERROR, result.exitCode, result.messages)
assertThat(result.messages).contains(
"CoffeeTest.kt:9:12 " +
"@Burst parameter default value must be burstValues(), a constant, or absent",
"@Burst parameter default must be burstValues(), a constant, null, or absent",
)
}

Expand Down Expand Up @@ -643,7 +643,6 @@ class BurstKotlinPluginTest {
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import app.cash.burst.burstValues
import kotlin.test.Test
@Burst
Expand Down Expand Up @@ -681,6 +680,246 @@ class BurstKotlinPluginTest {
)
}

@Test
fun nullableEnumNoDefault() {
val result = compile(
sourceFile = SourceFile.kotlin(
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import kotlin.test.Test
@Burst
class CoffeeTest {
val log = mutableListOf<String>()
@Test
fun test(espresso: Espresso?) {
log += "running ${'$'}espresso"
}
}
enum class Espresso { Decaf, Regular, Double }
""",
),
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)

val baseClass = result.classLoader.loadClass("CoffeeTest")
val baseInstance = baseClass.constructors.single().newInstance()
val baseLog = baseClass.getMethod("getLog").invoke(baseInstance) as MutableList<*>

baseClass.getMethod("test_Decaf").invoke(baseInstance)
baseClass.getMethod("test_Regular").invoke(baseInstance)
baseClass.getMethod("test_Double").invoke(baseInstance)
baseClass.getMethod("test_null").invoke(baseInstance)
assertThat(baseLog).containsExactly(
"running Decaf",
"running Regular",
"running Double",
"running null",
)
}

@Test
fun nullableBooleanNoDefault() {
val result = compile(
sourceFile = SourceFile.kotlin(
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import kotlin.test.Test
@Burst
class CoffeeTest {
val log = mutableListOf<String>()
@Test
fun test(iced: Boolean?) {
log += "running ${'$'}iced"
}
}
enum class Espresso { Decaf, Regular, Double }
""",
),
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)

val baseClass = result.classLoader.loadClass("CoffeeTest")
val baseInstance = baseClass.constructors.single().newInstance()
val baseLog = baseClass.getMethod("getLog").invoke(baseInstance) as MutableList<*>

baseClass.getMethod("test_false").invoke(baseInstance)
baseClass.getMethod("test_true").invoke(baseInstance)
baseClass.getMethod("test_null").invoke(baseInstance)
assertThat(baseLog).containsExactly(
"running false",
"running true",
"running null",
)
}

@Test
fun nullableBurstValuesNotDefault() {
val result = compile(
sourceFile = SourceFile.kotlin(
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import app.cash.burst.burstValues
import kotlin.test.Test
@Burst
class CoffeeTest {
val log = mutableListOf<String>()
@Test
fun test(volume: Int? = burstValues(12, 16, 20, null)) {
log += "running ${'$'}volume"
}
}
""",
),
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)

val baseClass = result.classLoader.loadClass("CoffeeTest")
val baseInstance = baseClass.constructors.single().newInstance()
val baseLog = baseClass.getMethod("getLog").invoke(baseInstance) as MutableList<*>

baseClass.getMethod("test").invoke(baseInstance)
baseClass.getMethod("test_16").invoke(baseInstance)
baseClass.getMethod("test_20").invoke(baseInstance)
baseClass.getMethod("test_null").invoke(baseInstance)
assertThat(baseLog).containsExactly(
"running 12",
"running 16",
"running 20",
"running null",
)
}

@Test
fun nullableEnumAsDefault() {
val result = compile(
sourceFile = SourceFile.kotlin(
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import kotlin.test.Test
@Burst
class CoffeeTest {
val log = mutableListOf<String>()
@Test
fun test(espresso: Espresso? = null) {
log += "running ${'$'}espresso"
}
}
enum class Espresso { Decaf, Regular, Double }
""",
),
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)

val baseClass = result.classLoader.loadClass("CoffeeTest")
val baseInstance = baseClass.constructors.single().newInstance()
val baseLog = baseClass.getMethod("getLog").invoke(baseInstance) as MutableList<*>

baseClass.getMethod("test_Decaf").invoke(baseInstance)
baseClass.getMethod("test_Regular").invoke(baseInstance)
baseClass.getMethod("test_Double").invoke(baseInstance)
baseClass.getMethod("test").invoke(baseInstance)
assertThat(baseLog).containsExactly(
"running Decaf",
"running Regular",
"running Double",
"running null",
)
}

@Test
fun nullableBooleanAsDefault() {
val result = compile(
sourceFile = SourceFile.kotlin(
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import kotlin.test.Test
@Burst
class CoffeeTest {
val log = mutableListOf<String>()
@Test
fun test(iced: Boolean? = null) {
log += "running ${'$'}iced"
}
}
enum class Espresso { Decaf, Regular, Double }
""",
),
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)

val baseClass = result.classLoader.loadClass("CoffeeTest")
val baseInstance = baseClass.constructors.single().newInstance()
val baseLog = baseClass.getMethod("getLog").invoke(baseInstance) as MutableList<*>

baseClass.getMethod("test_false").invoke(baseInstance)
baseClass.getMethod("test_true").invoke(baseInstance)
baseClass.getMethod("test").invoke(baseInstance)
assertThat(baseLog).containsExactly(
"running false",
"running true",
"running null",
)
}

@Test
fun nullableBurstValuesAsDefault() {
val result = compile(
sourceFile = SourceFile.kotlin(
"CoffeeTest.kt",
"""
import app.cash.burst.Burst
import app.cash.burst.burstValues
import kotlin.test.Test
@Burst
class CoffeeTest {
val log = mutableListOf<String>()
@Test
fun test(volume: Int? = burstValues(null, 12, 16, 20)) {
log += "running ${'$'}volume"
}
}
""",
),
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)

val baseClass = result.classLoader.loadClass("CoffeeTest")
val baseInstance = baseClass.constructors.single().newInstance()
val baseLog = baseClass.getMethod("getLog").invoke(baseInstance) as MutableList<*>

baseClass.getMethod("test_12").invoke(baseInstance)
baseClass.getMethod("test_16").invoke(baseInstance)
baseClass.getMethod("test_20").invoke(baseInstance)
baseClass.getMethod("test").invoke(baseInstance)
assertThat(baseLog).containsExactly(
"running 12",
"running 16",
"running 20",
"running null",
)
}

private val Class<*>.testSuffixes: List<String>
get() = methods.mapNotNull {
when {
Expand Down
Loading

0 comments on commit a856a66

Please sign in to comment.