I have a seemingly simple property test (simplifie...
# kotest
e
I have a seemingly simple property test (simplified example below) that fails because Kotest doesn't allow it:
Copy code
test("foo") {
    Arb.bind<Set<Int>>().filter { it.isNotEmpty() }.checkAll { set ->
        val value = set.random()
        val newSet = set - value
        value shouldNotBeIn newSet
    }
}
It fails with:
Caused by java.lang.AssertionError: Asserting content on empty collection. Use Collection.shouldBeEmpty() instead.
There are two issues with this exception (1️⃣ and 2️⃣ below) I really intend to test that the value is not in the set (the business logic under test being
set - value
). Is there a fundamental reason that I don't know about that makes testing content on an empty collection nonsensical? I really want to test that the new set does not contain the value. 1️⃣ Looking at the implementation of
shouldNotBeIn
, it basically negates the
shouldBeIn
matcher. For the latter I understand the error: testing an element being in an empty collection makes no sense. However, testing an element not being in an empty collection could, or even should (?), always pass. Why not? 2️⃣ The error message assumes that I'm testing for emptiness, because it suggest to use
Collection.shouldBeEmpty()
. This is not what I'm testing. Therefore, the message isn't helpful.
l
Testing on empty collections is usually by mistake, as in the user filters all elements out of the collection and assert on it. For this reason we instead split it into two possibilities: You either assert it's empty OR you assert on elements. It's by design to deny assertions on empty collections, in a way to tell the user "Hey, this is usually a mistake. Make sure it isn't", and the only way to do it is to explicitly use an assertion for the empty case. 2️⃣ The error message assumes you are testing a collection with the wrong matcher, and disallows it. It then suggest using a specific matcher for empty collections I think the root of your issue is that when a set with 1 element is generated, you reduce it to empty and check that it doesn't contain your value. This is always true, the assertion isn't necessary as mathematically you already know it. If you're testing maths, you shouldn't
e
You can deal with the single-element set separately.
Copy code
Arb.set(<http://Arb.int|Arb.int>(), size = 1).checkAll { set ->
            (set - set.single()).shouldBeEmpty()
         }

         Arb.set(<http://Arb.int|Arb.int>(), 2..10).checkAll { set ->
            val value = set.random()
            val newSet = set - value
            value shouldNotBeIn newSet
         }
e
Thanks both!