James Eschner
02/21/2023, 3:21 AMdata class Foo(val x: Boolean)
val fooArb: Arb<Foo> = arbitrary {
Foo(x = false)
}
val stuck = fooArb.filter { it.x }.next()
Now, obviously this won't work. This is a simple example but in my case, the arb is much more complex (and transient) so the situation wasn't immediately obviously. What I would have hoped would happen is that the program would eventually time out or throw trying to generate the "next" arb, but what I am witnessing is the kotest test hangs seemingly indefinitely, making it very hard to debug.
What I am wonder is if there is a way to better detect this situation? Can I set a timeout? Force an error? Etc...
** Not a contributionAdam S
02/21/2023, 9:05 AMJames Eschner
02/21/2023, 2:11 PMAdam S
02/21/2023, 2:11 PM.sample() I think?James Eschner
02/21/2023, 2:30 PMsample and I was also using next above. You were suggesting that I use an assumption, I was wondering how that would work to grab a single value
** Not a contributionJames Eschner
02/21/2023, 2:32 PMfilter it's pretty clear, I can use
fooArb.filter { it.x }.next() // substitute sample here if you'd like
with assumptions it doesn't look like, based on the docs, that it's a drop-in replacement for filterAdam S
02/21/2023, 2:56 PMfilter and `assume are similar, but different
filter acts before the test has started, while assume acts during an active test.
I rarely use filter, because there's a risk of filter out all elements (as you found out), but also it can be slow. For example, f 90% of the generated values are discarded, then that's a waste of time.Adam S
02/21/2023, 2:57 PMWith filter it's pretty clear, I can use
this doesn't look like standard usage... are you using Arb in aCopy codefooArb.filter { it.x }.next() // substitute sample here if you'd like
checkAll() or forAll()?James Eschner
02/21/2023, 3:54 PMcheckAll and forAll , where appropriate. But if I don't want to incur the cost of the loop I will occasionally just call next so that I can generate a random arb. Additionally, using `checkAll`/`forAll` doesn't solve the problem at hand, if you pass a filtered arb into these functions it can still hang.
We could probably go back and forth for a bit on best practices for arb testing but the simple comment I have is that ideally calling .next() doesn't hang indefinitely and would either time out or throw an exception if there is no possible arb to be generated
** Not a contributionAdam S
02/21/2023, 4:20 PMcheckAll(), it's just not typical so I didn't understand your use case. assume() requires checkAll() or forAll(), so that won't work for you
Basically your question isn't related to Arbs really, because you could have the same problem with a Sequence. This example will loop infinitely, because all generated values are smaller than 100.
generateSequence { Random.nextInt(1, 100) }
.filter { it > 100 }
.first()
probably the simplest workaround is to just limit the number of samples you take
generateSequence { Random.nextInt(1, 100) }
.take(1000)
.filter { it > 100 }
.first()
which will fail, but at least it won't loop infinitely
You can use Arb.samples() to get a sequence of values, and then just make sure to limit them
https://github.com/kotest/kotest/blob/0f07e00794ee61bc9cfa4cdb9c0ac9113cf570ca/kotest-property/src/commonMain/kotlin/io/kotest/property/Gen.kt#L110-L116James Eschner
02/21/2023, 4:55 PMtake thing is an interesting bit, I will check it out thank you!James Eschner
12/08/2023, 3:24 PMnext on an impossible-to-generate arb). The most painful part about it is the test hangs indefinitely...
I thought that maybe setting a timeout would help (at least the test would complete), but it turns out the timeout does not work...
I tried setting from code (ShouldSpec) and system properties...
timeout = 5000L
invocationTimeout = 5000L
Any ideas?
* Not a contribution *sam
12/08/2023, 7:20 PM