README.md in prop_check-0.7.1 vs README.md in prop_check-0.8.0

- old
+ new

@@ -12,11 +12,11 @@ - Generators for common datatypes. - An easy DSL to define your own generators (by combining existing ones, or completely custom). - Shrinking to a minimal counter-example on failure. -## TODOs before release +## TODOs before stable release Before releasing this gem on Rubygems, the following things need to be finished: - [x] Finalize the testing DSL. - [x] Testing the library itself (against known 'true' axiomatically correct Ruby code.) @@ -28,11 +28,11 @@ - [x] Good, unicode-compliant, string generators. - [x] Filtering generator outputs. # Nice-to-haves -- [ ] Basic integration with RSpec. See also https://groups.google.com/forum/#!msg/rspec/U-LmL0OnO-Y/iW_Jcd6JBAAJ for progress on this. +- [x] Basic integration with RSpec. See also https://groups.google.com/forum/#!msg/rspec/U-LmL0OnO-Y/iW_Jcd6JBAAJ for progress on this. - [ ] `aggregate` , `resize` and similar generator-modifying calls (c.f. PropEr's variants of these) which will help with introspection/metrics. - [ ] Integration with other Ruby test frameworks. - Stateful property testing. If implemented at some point, will probably happen in a separate add-on library. @@ -64,21 +64,66 @@ _(to be precise: a method on the execution context is defined which returns the current generated value for that name)_ Raise an exception from the block if there is a problem. If there is no problem, just return normally. ```ruby +include PropCheck::Generators # testing that Enumerable#sort sorts in ascending order -PropCheck.forall(numbers: array(integer())) do +PropCheck.forall(array(integer)) do |numbers| sorted_numbers = numbers.sort # Check that no number is smaller than the previous number sorted_numbers.each_cons(2) do |former, latter| raise "Elements are not sorted! #{latter} is < #{former}" if latter < former end end ``` + +Here is another example, using it inside a test case. +Here we check if `naive_average` indeed always returns an integer for all arrays of numbers we can pass it: + +```ruby +# Somewhere you have this function definition: +def naive_average(array) + array.sum / array.length +end + +# And then in a test case: +include PropCheck::Generators +PropCheck.forall(array(integer)) do |array| + result = naive_average(array) + unless result.is_a?(Integer) do + raise "Expected the average to be an integer!" + end +end +``` + +When running this particular example PropCheck very quickly finds out that we have made a programming mistake: + +```ruby +ZeroDivisionError: +(after 6 successful property test runs) +Failed on: +`{ + :array => [] +}` + +Exception message: +--- +divided by 0 +--- + +(shrinking impossible) +--- +``` + +Clearly we forgot to handle the case of an empty array being passed to the function. +This is a good example of the kind of conceptual bugs that PropCheck (and property-based testing in general) +are able to check for. + + #### Shrinking When a failure is found, PropCheck will re-run the block given to `forall` to test 'smaller' inputs, in an attempt to give you a minimal counter-example, from which the problem can be easily understood. @@ -104,24 +149,31 @@ - Negative integers also attempt their positive alternative. - Floats shrink similarly to integers. - Arrays and hashes shrink to fewer elements, as well as shrinking their elements. - Strings shrink to shorter strings, as well as characters earlier in their alphabet. +### Builtin Generators +PropCheck comes with [many builtin generators in the PropCheck::Generators](https://www.rubydoc.info/github/Qqwy/ruby-prop_check/master/PropCheck/Generators) module. + +It contains generators for: +- (any, positive, negative, etc.) integers, +- (any, only real-valued) floats, +- (any, printable only, alphanumeric only, etc) strings and symbols +- fixed-size arrays and hashes +- as well as varying-size arrays and hashes. +- and many more! + +It is common to call `include PropCheck::Generators` in e.g. your testing-suite files to be able to use these. +If you want to be more explicit (but somewhat more verbose) when calling these functions. feel free to e.g. create a module-alias (like `PG = PropCheck::Generators`) instead. + ### Writing Custom Generators -PropCheck comes bundled with a bunch of common generators, for: -- integers -- floats -- strings -- symbols -- arrays -- hashes -etc. +As described in the previous section, PropCheck already comes bundled with a bunch of common generators. However, you can easily adapt them to generate your own datatypes: -#### Generator#wrap +#### Generators#constant / Generator#wrap Always returns the given value. No shrinking. #### Generator#map