-
-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow Sharing of Generated Values Across Arbitraries #294
Comments
Frankly speaking, I would love to hide @Property
void myProperty(@ForAll("fullNames") String aString, @ForAll("firstNames") String firstName) { }
// It might come from extension or something like that
@Provide
Arbitrary<String> firstNames() {...}
@Provide
Arbitrary<String> lastNames() {...}
@Provide
Arbitrary<String> fullNames(@ForAll("firstNames") String firstName, @ForAll("lastNames") lastName) {
return firstName + lastName;
} |
Have you tried it? Should already work. |
Would that feature be useful if shared values couldn't be shrunk? Without shrinking this is rather easy to implement... |
What is the "easy" implementation you have in mind? |
The easy implementation is to just store the generated unshrinkable value on first access. Going for a full flatmap and flat combine behind the scenes would IMO require a data flow analysis across all generated values. I don’t even know if that’s possible. There may be a more hacky solution making use of stores and try lifecycle, but I could go with a first unshrinkable solution, if it provides value. |
I see. @Provide
Arbitrary<String> fullNames() {
Arbitrary<String> firstName = Arbitraries.strings().share("firstName");
Arbitrary<String> lastName = Arbitraries.strings().share("lastName");
return Combinators.combine(firstName, lastName).as( (f, l) -> f + " " + l);
} it does indeed need dataflow analysis. However, is dataflow needed if all the "sharing" is done via method parameters and return values? |
In other words, the definition like // combine, works
@Provide
Arbitrary<String> fullNames(@ForAll("firstNames") String firstName, @ForAll("lastNames") lastName) {
return just(firstName + lastName);
}
// combine, works
@Provide
Arbitrary<String> fullNames(@ForAll("firstNames") String firstName, @ForAll("lastNames") lastName) {
ints(..)
...
vs
@Provide
Arbitrary<String> fullNames(@ForAll("firstNames") String firstName, @ForAll("lastNames") lastName, @ForAll int ints) { means |
That code doesn’t compile though. Jqwik needs a clear criterion to decide if it has to flatMap/combine over parameters or if plain map/combine suffices. A return type A new annotation would do the trick, but there are already too many for my taste. |
I suggest it just uses combine |
By the way, it might make sense to organize a call to explore options. Wdyt? |
Sure, when would it suit you? |
Did some experimentation in https://github.com/jlink/jqwik/blob/main/engine/src/test/java/experiments/SharedArbitraryExperiments.java |
One more idea. What if @Provide
Arbitrary<String> aString(@ForAll Arbitrary<Integer> ints) {
return ints.map(i -> i.toString());
} This would not hide map/flatMap/combine but it could be used directly in provider methods. |
That would be useful as well. |
That was so easy to implement that I just did it. Now this works: @Property
void test(@ForAll("chessSquares") String square) {
System.out.println(square);
}
@Provide
Arbitrary<String> chessSquares(
@ForAll Arbitrary<@CharRange(from = 'a', to = 'h') Character> rows,
@ForAll Arbitrary<@IntRange(min = 1, max = 8) Integer> columns
) {
return Combinators.combine(rows, columns).as((r, c) -> r.toString() + c);
} Released and available in "1.6.3-SNAPSHOT" |
@vlsi Would |
|
|
|
Currently, I don't see any other types. |
What about |
Testing Problem
Sometimes a value generated by an arbitrary should be the same one for all usages of this arbitrary in the same try.
Currently, this can only be accomplished by flat mapping over this value and handing the value down to all other arbitraries.
It would simplify some properties and arbitrary definitions if there was a simpler way to accomplish the same effect
Suggested Solution
There are at least two situations in which you might want to use this feature:
In Arbitrary Creation API. E.g.:
This could create an arbitrary that will only generate a value the first time it is used with the same key!
Look at a similar Hypothesis feature
When using as property parameters, e.g.:
Discussion
Implementation has a few complications:
This has not been fully researched yet, though.
Sketched some half-working code: https://github.com/jlink/jqwik/blob/main/engine/src/test/java/experiments/SharedArbitraryExperiments.java
The text was updated successfully, but these errors were encountered: