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