README.md in rubyqc-0.0.1 vs README.md in rubyqc-0.0.2

- old
+ new

@@ -68,18 +68,20 @@ [combinator]: http://en.wikipedia.org/wiki/Combinator_library ## REQUIREMENTS: -* Tested with MRI (official CRuby) 2.0.0, 2.1.0, Rubinius and JRuby. +* Tested with MRI (official CRuby), Rubinius and JRuby. ## INSTALLATION: gem install rubyqc ## SYNOPSIS: +### RubyQC::API.check + Here's a quick example using [Bacon][]. We check if `Array#sort` has the property that the front elements of the result array would be `<=` than the rear elements of the result array for all arrays. ``` ruby @@ -128,62 +130,89 @@ rand(RubyQC::FixnumMin..RubyQC::FixnumMax) end end ``` -You get the idea. See next section for the list of built-in generators. +You get the idea. -### Kernel +### RubyQC::API.forall +Other than `check`, we also have `forall` which would iterate through all the +possible choices in case you would simply like to test all combinations. +Here's an example for checking compare_by_identity: + +``` ruby +describe Hash do + describe 'compare_by_identity' do + should 'Treat diff arr with the same contents diff when set' do + arr = [0] + forall(booleans, [arr, [0]], [arr, [1]]) do |flag, a, b| + h = {} + h.compare_by_identity if flag + h[a] = h[b] = true + + if (flag && a.object_id != b.object_id) || a != b + h.size.should == 2 + else + h.size.should == 1 + end + end + end + end +end +``` + +### Kernel generator + The very default generator would simply return the instance itself. So if there's no generator defined for a given class or instance, it would merely take `self`. ``` ruby true.rubyqc # true ``` -### Class +### Class generator This default generator for classes would simply return a new instance via `new` method. This could fail if the `initialize` method for the particular class does not take zero argument. ``` ruby Object.rubyqc # kind_of?(Object) ``` -### Fixnum, Bignum, and Integer +### Fixnum, Bignum, and Integer generator This would give you a random integer. Fixnum and Bignum would guarantee to give you the particular class, whereas Integer would give you either a Fixnum or Bignum. ``` ruby Fixnum.rubyqc # kind_of?(Fixnum) ``` -### array +### array generator We also have instance level generator, which was used in the first example. The array instance generator would recursively call `rubyqc` for all elements of the array, and collect the results. ``` ruby [Fixnum, Fixnum].rubyqc # [kind_of?(Fixnum), kind_of?(Fixnum)] ``` -### hash +### hash generator This also applies to hashes which would do the same thing as arrays for the values, keeping the key. ``` ruby {:fixnum => Fixnum}.rubyqc # {:fixnum => kind_of?(Fixnum)} ``` -### range +### range generator Fixnum would actually give a very large or very small (negative) number in most cases. If you want to have a number with specific range, use a range object to specific the range. @@ -197,12 +226,34 @@ ### Define your own generator Just define `rubyqc` method for your classes or instances. This weird name was simply chosen to avoid name conflicting since we don't have [typeclass][] in Ruby, and it's quite natural to open and insert new methods into classes -in Ruby. +in Ruby. Here's a quick example: +``` ruby +class User < Struct.new(:id, :name) + def self.rubyqc + new(Fixnum.rubyqc, String.rubyqc) + end +end + +describe 'User.rubyqc' do + should 'Generate random users' do + check(User) do |user| + user .should.kind_of User + user.id .should.kind_of Fixnum + user.name.should.kind_of String + end + end +end +``` + [typeclass]: http://learnyouahaskell.com/types-and-typeclasses + +### Implementation reference + +[QuickCheck.hs](http://www.cse.chalmers.se/~rjmh/QuickCheck/QuickCheck.hs) ## CONTRIBUTORS: * Lin Jen-Shin (@godfat)