-
Notifications
You must be signed in to change notification settings - Fork 40
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
How to write your own (complex) generator? #22
Comments
On first sight, the generator does not look that wrong to me. Though using the Sample() function in tests is kind of an anti-pattern since - in theory - it may not create a result for all generators (i.e. generators that have a SuchThat(...) sieve). Unluckily go has not language support for tuples, so writing a generator for two or more parameters always requires some kind of wrapper "object". So: If you need qspec and quorumSize the probably best way is to have a
in your tests and adapt the generator accordingly. A somewhat better approach might be to combine generators via. Map(...) and FlatMap(...) E.g.
Hope that helps, otherwise I might take a closer look at a less stressful moment than right now ;) |
Thanks for the input and proposed combined generator; much appreciated. I had been looking at the Map and FlatMap before, but found it a bit difficult to understand without a good example that matched the complexity I needed. Also, I agree that my use of Sample was perhaps the one thing that I disliked the most with my first approach and why I wanted to improve it. Anyway, I tried to set it up as you suggested (barring a few adjustments to satisfy the API): gen.IntRange(4, 100).FlatMap(func(n interface{}) gopter.Gen {
qspec, err := NewAuthDataQ(n.(int), priv, &priv.PublicKey)
if err != nil {
t.Fatalf("failed to create quorum specification for size %d", n)
}
return gen.IntRange(qspec.q+1, qspec.n).Map(func(quorumSize interface{}) gopter.Gen {
return func(*gopter.GenParameters) *gopter.GenResult {
return gopter.NewGenResult(&qfParams{quorumSize.(int), qspec}, gopter.NoShrinker)
}
})
}, reflect.TypeOf(&qfParams{})), See here for the full code: I'm not quite sure what I'm doing wrong, but I get the following (partial) stack trace. I suspect that it is related to the
|
At first glance, I would say that But you're right, the error is not very helpful, I'll look into that. |
Just checked your example: This here seems to work:
Though I think this one is what you're actually looking for:
But it actually might be a good idea to allow the map function to accept |
Thanks! I actually just discovered the same myself after you pointed out that I was returning a generator, which I thought was awkward... So that solved it!! Thanks for helping me with this. Moving on to testing more interesting properties. Feel free to close the issue. |
@meling I think you should use |
I'm having a similar but much simpler problem. I want to generate a bunch of values to restrict ranges in generators. However, the
|
@adrianmaurer there is also another way to create custom structs a more typesafe one:
Derive function accepts any number of generators - FirstNameGen,LastNameGen and runs them before creating the struct. Their artifacts are used as function arguments |
I've been playing around with
gopter
for a little while now, trying to understand how to write my own generator for my use case, which is not as straight forward as those in the repo. My use case is the following; I want to test a function (ReadQF
) that should return a value and true when enough, i.e. a quorum of replies have been received and passed in to theReadQF
function. It should return false otherwise.I've hacked together something that seems to work in the following:
https://github.com/relab/byzq/blob/master/authdataspec_property_test.go#L37
https://github.com/relab/byzq/blob/master/authdataspec_property_test.go#L63
However, I suspect it isn't quite in the spirit of property-based testing, and I'm struggling to break it up into multiple generators, since the input parameter
n
to theNewAuthDataQ
constructor that creates aqspec
object and computes the parameterq
, which is used to decide the minimal/maximal length of the replies array. And furthermore, I need access to theqspec
object in the end to decide if a quorum has been received.I would really appreciate to get some feedback on my two tests linked above, especially, if you can provide some advice on how to decouple things.
(Below is an initial attempt at writing a generator, but I don't know how to get both the
quorumSize
andqspec
parameters out of the generator for consumption in thecondition
function passed toprop.ForAll()
.)The text was updated successfully, but these errors were encountered: