Mikael Brockman wrote:

>>You might wanna check out the now a bit dated AutoTest stuff which
>>seems similar to your RickCheck but takes a somewhat different
>>approach using Generators that can generate different types of
>>data. This seems a bit more flexible than your approach since you can
>>have multiple Generators for objects of a certain type.
>>    
>>
>
>Ooh, that's interesting.  I think it's probably better to keep the
>generation out of the classes themselves.  Or maybe the default
>generator could be tacked onto the class, to make the common case
>easier.
>
>  
>
Yes, or we could even

class Object
  def rand_instance # or call it arbitrary if you want...
    __rand_generator.generate
  end

  def __rand_generator
    @@__rand_generator ||= __get_rand_generator
  end

  def __get_rand_generator
    gens = []
    ObjectSpace.each_object(Class) do |c|
      if c.ancestors.include?(Generator) && c.generates?(self.class)
        gens << c
      end
    end
    OrGenerator.new(*gens)
  end
end

so that it will use any loaded generators that can generate objects of 
its own class.

>>OTOH, it's more verbose; would be interesting to merge our
>>approaches
>>    
>>
>
>Definitely!
>
>  
>
Ok, lets do it. May I propose a different name? QuickcheckR or 
Test::Random? I think the latter is actually better...

>>and have it integrate nicely with Test::Unit (which I think yours
>>might already be doing?).
>>    
>>
>
>Yup, it does.  It defines a subclass of TestCase called QuickCase,
>which adds automatical testing of prop_* methods.  What I like best
>about RickCheck is how easy it is to use for small stuff, and how it
>blends nicely with Test::Unit:
>
>| class MyTest < QuickCase           # most contrived example ever
>|   def prop_foo(a)
>|     yield [Integer]
>|     assert_equal(a, (a + 1) - 1)
>|   end
>|
>|   def test_bar
>|     assert_equal(4, (4 * 2) / 2)
>|   end
>| end
>
>But the use of yield seems weird now, having seen AutoTest.  In
>retrospect, I can't believe I didn't think of just doing:
>
>| def test_foo
>|   assert_property(Integer) do |a|
>|     assert_equal(a, (a + 1) - 1)
>|   end
>| end
>
>I think that way is more natural, and it doesn't need as many changes
>to Test::Unit -- test_foo is just a regular test.  And it's just one
>line longer.  :-)
>
>  
>
Yes, this is probably the way to go.

>>Related to this is also paper 2 in my thesis (available at
>>http://www.ce.chalmers.se/~feldt/thesis/08_paper2_wise.ps) which
>>evolves tests by combining test cells (basically Generators above)
>>into more complex test behaviors. I am currently working on extending
>>these ideas.
>>    
>>
>
>Wow!  Most of that is _way_ over my head, but it seems extraordinarily
>cool.  Using biological ideas in computing always struck me as a
>beautiful idea.  I'm glad we have guys like you on the Ruby boat. :-)
>
>  
>
Thanks! I also think it's pretty cool... :)

>RickCheck used to do special treatment of `border cases'; for example,
>Integer had this definition:
>
>| class Integer
>|   def border_cases
>|     [1, 0, -1]
>|   end
>| end
>
>But I removed it for some reason that I seem to have forgotten.  I'd
>like to add it back in, but I'm not sure what's the best way to do it.
>But it's certainly a Good Thing to test the border cases as soon as
>possible; they're the most likely to screw up, after all.
>
>  
>
Boundary-Value Analysis is the common term yes.

>Another thing I'd like to add is manual seeding of the random number
>generator.  Every test run could tell you what it was seeded with, so
>that you can easily reproduce it later.
>
>  
>
Yep, good idea.

Regards,

Robert