Skip to content
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

Add samples to Generator and Shrinker documentation #218

Closed
kurtschelfthout opened this issue Apr 17, 2016 · 13 comments
Closed

Add samples to Generator and Shrinker documentation #218

kurtschelfthout opened this issue Apr 17, 2016 · 13 comments

Comments

@kurtschelfthout
Copy link
Member

While talking to people about FsCheck I had the following idea to improve the documentation.

The documentation page https://fscheck.github.io/FsCheck/TestData.html which is generated from https://github.com/fscheck/FsCheck/blob/master/docs/content/TestData.fsx currently feels very abstract - I think it would be improved if some of the generators and shrinkers discussed would show some actual output. This would also show people how to write/test generators/shrinkers and get a feel for what they do.

Concretely, I would suggest to add executed code samples (using FSharp.Formatting's output capturing, like in the other docs) that essentially call Gen.sample and the shrinker function with an example value.

@kurtschelfthout
Copy link
Member Author

Awesome work so far. I have pushed the updated docs.

@ploeh
Copy link
Member

ploeh commented May 27, 2016

With #266 we've now covered all the combinators under the Useful Generator Combinators with the exception of Gen.tryFilter/Gen.tryWhere. I'll be happy to write something about that as well, but I can't think of a simple example 😳 So far, I've never had the need to use this function.

Can anyone think of a simple, reasonable example?

@kurtschelfthout
Copy link
Member Author

Nice.

tryWhere is used in FsCheck itself to try and generate the next operation in a sequence of operations that satisfy a user-provided precondition. If it can't find any, it stops the sequence.

Perhaps an example where we are building a list or data structure, where with each added element the chance of finding another element with that satisfies some global invariant becomes smaller. If we get None from tryWhere we know we have tried "hard", and either give up and return where we are so far (if we are incrementally generating the data structure, i.e. adding one element with each recursive step, for example) or try to generate a smaller data structure (thus hopefully making the global invariant easier to satisfy)

E.g. concretely generate a list of distinct elements from a given generator - where the generator has a generic type, so we don't know much about how easy it is to generate a list of district elements, e.g. compare a list of distinct bools vs distinct floats. We can do this by calling Gen.listOfLength with the size, then using Gen.tryWhere to check if the elements are indeed distinct. If that returns None, we should try with a smaller length of list. If it returns Some l we can return l.

@moodmosaic
Copy link
Contributor

Should we document Gen.eval also? It's a bit low-level though...

If we should document it, I'd be happy to open a PR.

@ploeh
Copy link
Member

ploeh commented May 31, 2016

Would you ever use Gen.eval when writing properties?

@moodmosaic
Copy link
Contributor

moodmosaic commented May 31, 2016

I wouldn't use it when writing properties. I might rarely use it when writing generators, e.g.: instead of Gen.sample, one could use Gen.eval to define a custom version of Gen.sample.

I agree that it should be rarely used. We could still document why though, and also what it does...

@kurtschelfthout
Copy link
Member Author

Probably better not in this context. Unlikely it should have been part of the API in the first place anyway.

@moodmosaic
Copy link
Contributor

Right. See also #267 and #268.

@moodmosaic
Copy link
Contributor

Would it make sense to document Gen.sequence?

An easy way to document that generator can be via Gen.listOfLength's implementation, or by providing a simplified version of this test.

@ploeh
Copy link
Member

ploeh commented Jun 7, 2016

I think it'd be fine to add an example of Gen.sequence if it's possible to come up with an easy-to-understand example.

I have to admit, however, that I still don't understand when I'd ever use Gen.growingElements.

If I understand the intent of this GitHub issue correctly, its purpose is to make the introduction to Generators and Shrinkers more accessible, by showing some examples. The purpose of the TestData.html file isn't to act as API documentation; there's a separate page for that.

The reason I bring this up is that if we make the file too big, it'll have a detrimental effect, because people will give up when they see the sheer size of it.

@ploeh
Copy link
Member

ploeh commented Jun 7, 2016

All that said, another sometimes useful function is Gen.oneof.

@moodmosaic
Copy link
Contributor

True. Gen.sequence, and Gen.onef, can probably go into that other page...

@kurtschelfthout
Copy link
Member Author

I'm going to close this general topic, as great progress has been made here. Feel free to open specific issues if there is anything to discuss, or even better, a PR with additional documentation suggestions (though heeding @ploeh's wise words about the difference between introductory documentation and API docs.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants