Skip to content

Assumptions that check for non-empty lists fail because empty lists are generated too often #76

@pvigliatore

Description

@pvigliatore

The following simplified examples are written in Kotlin and were tested with version 0.25 and 0.26 of QuickTheories

The test case below fails reliably. Even though the theory is asking for lists ranging from size 0 to 10,000 the assumption will claim to find 0 matching values.

    @Test
    fun whenUsingAssumptionsTheLowerBoundOfListSizeIsTooCommon() {
        qt().forAll(lists().of(integers().all()).ofSizeBetween(0, 10000))
            .assuming { it.isNotEmpty() }
            .check { true }
    }

The failure message for the above test is:

java.lang.IllegalStateException: Gave up after finding only 0 example(s) matching the assumptions

However, the upper bound and a non-zero lower bound do not have the same behavior as above. The following test cases always pass.

   @Test
    fun whenUsingAssumptionsTheUpperBoundOfListSizeINotTooCommon() {
        qt().forAll(lists().of(integers().all()).ofSizeBetween(0, 10000))
            .assuming { it.size < 10000 }
            .check { true }
    }

    @Test
    fun whenUsingAssumptionsTheNonZeroLowerBoundOfListsSizeIsNotTooCommon() {
        qt().forAll(lists().of(integers().all()).ofSizeBetween(1, 10000))
            .assuming { it.size > 1 }
            .check { true }
    }

Lastly, when capturing the input to the assumption, the supplied values are very different.

    @Test
    fun whenUsingAssumptionsTheLowerBoundOfListSizeIsTooCommon() {
        qt().forAll(lists().of(integers().all()).ofSizeBetween(0, 10000))
            .assuming { println(it.size); it.size > 0}
            .check { true }
    }

The output of the above test is:

9143
0
0
0
0
0
0
0
0
0
0


java.lang.IllegalStateException: Gave up after finding only 0 example(s) matching the assumptions

	at org.quicktheories.core.ExceptionReporter.valuesExhausted(ExceptionReporter.java:26)
	at org.quicktheories.impl.TheoryRunner.check(TheoryRunner.java:39)
	at org.quicktheories.dsl.TheoryBuilder.check(TheoryBuilder.java:132)

By changing the assumption to ALWAYS pass, the output is completely different:

    @Test
    fun whenUsingAssumptionsTheLowerBoundOfListSizeIsTooCommon() {
        qt().forAll(lists().of(integers().all()).ofSizeBetween(0, 10000))
            .assuming { println(it.size); true}
            .check { true }
    }

1277
0
0
10000
3202
2346
6106
823
1207
9146
5662
3457

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions