diff --git a/pom.xml b/pom.xml index f089b00..9820f95 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.toolisticon.testing jgiven-kotlin - 1.2.2 + 1.2.2.1 ${project.artifactId} jgiven kotlin extension @@ -16,12 +16,14 @@ 11 ${java.version} ${java.version} - 1.6.21 + 1.7.10 true 1.2.2 2.3.7.RELEASE + + 3.23.1 @@ -63,6 +65,13 @@ test + + org.assertj + assertj-core + ${assertj.version} + test + + org.slf4j slf4j-simple @@ -262,7 +271,7 @@ org.jetbrains.dokka dokka-maven-plugin - 1.6.21 + 1.7.10 attach-javadocs @@ -377,7 +386,7 @@ maven-deploy-plugin - 3.0.0-M2 + 3.0.0 true @@ -408,14 +417,14 @@ maven-install-plugin - 2.5.2 + 3.0.0 org.apache.maven.plugins maven-enforcer-plugin - 3.0.0 + 3.1.0 enforce-maven diff --git a/src/main/kotlin/JGivenKotlin.kt b/src/main/kotlin/io/toolisticon/testing/jgiven/JGivenKotlin.kt similarity index 100% rename from src/main/kotlin/JGivenKotlin.kt rename to src/main/kotlin/io/toolisticon/testing/jgiven/JGivenKotlin.kt diff --git a/src/main/kotlin/JGivenKotlinStage.kt b/src/main/kotlin/io/toolisticon/testing/jgiven/JGivenKotlinStage.kt similarity index 100% rename from src/main/kotlin/JGivenKotlinStage.kt rename to src/main/kotlin/io/toolisticon/testing/jgiven/JGivenKotlinStage.kt diff --git a/src/main/kotlin/io/toolisticon/testing/jgiven/format/VarargsFormatter.kt b/src/main/kotlin/io/toolisticon/testing/jgiven/format/VarargsFormatter.kt new file mode 100644 index 0000000..d68c0eb --- /dev/null +++ b/src/main/kotlin/io/toolisticon/testing/jgiven/format/VarargsFormatter.kt @@ -0,0 +1,53 @@ +package io.toolisticon.testing.jgiven.format + +import com.tngtech.jgiven.annotation.Format +import com.tngtech.jgiven.format.ArgumentFormatter +import com.tngtech.jgiven.format.PrintfFormatter +import kotlin.annotation.AnnotationRetention.RUNTIME +import kotlin.annotation.AnnotationTarget.* + + +/** + * Varargs step parameters annotated with this annotation will be put into quotes (" ") in reports. + */ +@MustBeDocumented +@Format(value = VarargsFormatter::class, args = ["\"%s\""]) +@Target(FIELD, VALUE_PARAMETER, ANNOTATION_CLASS) +@Retention(RUNTIME) +annotation class VarargsQuoted + +/** + * Argument formatter for varargs delegating to [PrintfFormatter] + */ +class VarargsFormatter @JvmOverloads constructor(private val delimiter: String = ", ") : ArgumentFormatter { + companion object { + fun anyToList(instance: Any?): List? { + if (instance == null || !instance::class.java.isArray) { + return null + } + + // deal with the various primitive array (int[],...) wrappers in kotlin. + return when (instance) { + is IntArray -> instance.toList() + is ByteArray -> instance.toList() + is CharArray -> instance.toList() + is ShortArray -> instance.toList() + is LongArray -> instance.toList() + is DoubleArray -> instance.toList() + is FloatArray -> instance.toList() + is BooleanArray -> instance.toList() + else -> (instance as Array<*>).toList() + } + } + } + + private val formatter = PrintfFormatter() + + override fun format(argumentToFormat: Any?, vararg formatterArguments: String): String { + val argumentList = anyToList(argumentToFormat) + + return argumentList + ?.joinToString(separator = delimiter) { formatter.format(it, *formatterArguments) } + ?: formatter.format(argumentToFormat, *formatterArguments) + } +} diff --git a/src/test/kotlin/CalculatorExampleTest.kt b/src/test/kotlin/io/toolisticon/testing/jgiven/CalculatorExampleTest.kt similarity index 64% rename from src/test/kotlin/CalculatorExampleTest.kt rename to src/test/kotlin/io/toolisticon/testing/jgiven/CalculatorExampleTest.kt index a04b75b..4f4ed25 100644 --- a/src/test/kotlin/CalculatorExampleTest.kt +++ b/src/test/kotlin/io/toolisticon/testing/jgiven/CalculatorExampleTest.kt @@ -4,16 +4,17 @@ import com.tngtech.jgiven.Stage import com.tngtech.jgiven.annotation.ScenarioState import com.tngtech.jgiven.annotation.ScenarioState.Resolution.NAME import com.tngtech.jgiven.junit5.SimpleScenarioTest +import io.toolisticon.testing.jgiven.format.VarargsQuoted import org.junit.jupiter.api.Test import kotlin.test.assertEquals /** * Simple example using GIVEN/WHEN/THEN extensions, the step() lambda and the all open annotation. */ -class CalculatorExampleTest : SimpleScenarioTest() { +internal class CalculatorExampleTest : SimpleScenarioTest() { @Test - internal fun `calculator adds two numbers`() { + fun `calculator adds two numbers`() { GIVEN .`the first number is $`(4) .AND @@ -25,6 +26,18 @@ class CalculatorExampleTest : SimpleScenarioTest() { THEN .`the sum is $`(11) } + + @Test + fun `calculator adds two numbers as varargs`() { + GIVEN + .`numbers are $`(5, 4) + + WHEN + .`both numbers are added`() + + THEN + .`the sum is $`(9) + } } @JGivenKotlinStage @@ -39,6 +52,14 @@ class CalculatorStage : Stage() { @ScenarioState(resolution = NAME) var sum: Int = 0 + /** + * Sets both numbers via vararg, use to verify Vararg formatter. + */ + fun `numbers are $`(@VarargsQuoted vararg nums: Int) = step { + require(nums.size == 2) { "need to pass two numbers" } + `the first number is $`(nums[0]).`the second number is $`(nums[1]) + } + fun `the first number is $`(n: Int) = step { this.firstNumber = n } diff --git a/src/test/kotlin/io/toolisticon/testing/jgiven/format/VarargsFormatterTest.kt b/src/test/kotlin/io/toolisticon/testing/jgiven/format/VarargsFormatterTest.kt new file mode 100644 index 0000000..8718ae9 --- /dev/null +++ b/src/test/kotlin/io/toolisticon/testing/jgiven/format/VarargsFormatterTest.kt @@ -0,0 +1,77 @@ +package io.toolisticon.testing.jgiven.format + +import io.toolisticon.testing.jgiven.format.VarargsFormatter.Companion.anyToList +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + + +internal class VarargsFormatterTest { + + private var formatter: VarargsFormatter = VarargsFormatter() + + + @Test + fun `format a single value`() { + assertThat(formatter.format("value", "\"%s\"")).isEqualTo("\"value\"") + } + + @Test + fun `format single array values`() { + val varargs = arrayOf("value") + assertThat(formatter.format(varargs, "\"%s\"")).isEqualTo("\"value\"") + } + + @Test + fun `format multiple array values`() { + val varargs = arrayOf("value1", 1L) + assertThat(formatter.format(varargs, "\"%s\"")).isEqualTo("\"value1\", \"1\"") + } + + @Test + fun `fail without formatterArguments`() { + val varargs = arrayOf("value") + + assertThatThrownBy { formatter.format(varargs) } + .isInstanceOf(ArrayIndexOutOfBoundsException::class.java) + } + + @Test + fun `format null value`() { + val varargs: Array? = null + assertThat(formatter.format(varargs, "\"%s\"")).isEqualTo("\"null\"") + } + + @Nested + inner class AnyToList { + + + @Test + fun `null to null`() { + assertThat(anyToList(null)).isNull() + } + + @Test + fun `non-array to null`() { + assertThat(anyToList("")).isNull() + } + + @Test + fun `int to list`() { + val list: List = requireNotNull(anyToList(varargInt(1, 2, 3))) + + assertThat(list).containsExactly(1, 2, 3) + } + + @Test + fun `boolean to list`() { + val list = requireNotNull(anyToList(varargBoolean(true, false, null))) + + assertThat(list).containsExactly(true, false, null) + } + } + + private fun varargInt(vararg v: Int): Any? = v as Any? + private fun varargBoolean(vararg v: Boolean?): Any? = v as Any? +}