Search code examples
kotlinproperty-based-testingkotest

Kotlin and kotest with arbitrary values: what am I doing wrong?


I've gone through the kotest documentation and am trying to incorporate some property based testing into my code. From the documentation, my impression was that if you use a forAll<T>, if kotest has a built-in Arb<T>, it would generate arbitrary values for T and then run the given tests on them.

So then, why does this example which should clearly fail claim to pass for me?

class PassesExample: ShouldSpec({
    should("I should fail") {
        forAll<Int> { a ->
            abs(a) shouldBe -1
        }
    }
})

The output is as follows:

> Task :wrapper
BUILD SUCCESSFUL in 98ms
1 actionable task: 1 executed
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :compileTestKotlin UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test
BUILD SUCCESSFUL in 1s
3 actionable tasks: 1 executed, 2 up-to-date
9:42:38 PM: Execution finished ':test --tests "abstractalgebra.PassesExample"'.

(Ignore the abstractalgebra... I'm trying to play around with some finite fields and just threw this in the same file as my test file.)

If I don't use the forAll<Int> and give it an obvious concrete fail case, everything works as expected, for example:

class PassesExample: ShouldSpec({
    should("I should fail") {
        abs(2) shouldBe -1
    }
})

and I get:

expected:<-1> but was:<2>
Expected :-1
Actual   :2

What am I doing wrong? It is obvious that no tests are executed at all, or this would not work.


Solution

  • Never mind: I found out the issue. I was importing the wrong forAll:

    import io.kotest.data.forAll
    

    when I should have been importing:

    import io.kotest.property.forAll