I need an Arbitrary java.lang.Number
.
Here is what I came up with:
@Provide
Arbitrary<Number> numbers(){
return
Combinators.combine(
Arbitraries.integers().between(0, 5),
Arbitraries.integers(),
Arbitraries.longs(),
Arbitraries.bigIntegers(),
Arbitraries.floats(),
Arbitraries.doubles(),
Arbitraries.bigDecimals()
).as((i, intA, longA, bigIntegerA, floatA, doubleA, bigDecimalA) ->
new Number[]{intA, longA, bigIntegerA, floatA, doubleA, bigDecimalA}[i]
);
}
This kind of works but causes
STANDARD_ERROR
10:17:38 Aug 24, 2022 2:17:38 PM net.jqwik.engine.properties.RandomizedShrinkablesGenerator logEdgeCasesOutnumberTriesIfApplicable
10:17:38 INFO: Edge case generation exceeds number of tries. Stopped after 1000 generated cases.
Is there a better way to implement an Arbitrary that represents all the possible values of java.lang.Number
?
Footnote:
For you set theorists out there:
Yes I know that I am forming a product and extracting a union, which is about the least efficient way to do this. Undoubtedly this confuses the shrinker to no end. This was the best I could do. If there is a way to do this as a simple union instead, please let me know.
There's a simpler solution, assuming that any concrete subtype of Number
should be generated:
@Property
void test(@ForAll Number aNumber) {
System.out.println(aNumber.getClass() + " = " + aNumber);
}
@Property
void test2(@ForAll("anyNumber") Number aNumber) {
System.out.println(aNumber.getClass() + " = " + aNumber);
}
@Provide
Arbitrary<Number> anyNumber() {
return Arbitraries.defaultFor(Number.class);
}
As you can see, trying to generate a Number
just works. Under the hood, jqwik checks for all registered arbitrary providers that are compatible with type Number
and randomly chooses between them.