rushcheck 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/data/rushcheck/doc/policy.txt +107 -0
- data/data/rushcheck/doc/rushcheck.thtml +832 -0
- data/data/rushcheck/examples/candy.rb +6 -8
- data/data/rushcheck/examples/printf.rb +3 -3
- data/data/rushcheck/examples/proc.rb +4 -4
- data/data/rushcheck/examples/roguetile.rb +16 -16
- data/data/rushcheck/examples/sample.rb +10 -10
- data/data/rushcheck/rdoc/classes/Arbitrary.html +5 -5
- data/data/rushcheck/rdoc/classes/Arbitrary.src/M000082.html +18 -0
- data/data/rushcheck/rdoc/classes/Assertion.html +11 -11
- data/data/rushcheck/rdoc/classes/Assertion.src/M000019.html +20 -0
- data/data/rushcheck/rdoc/classes/Assertion.src/M000020.html +50 -0
- data/data/rushcheck/rdoc/classes/Coarbitrary.html +5 -5
- data/data/rushcheck/rdoc/classes/Coarbitrary.src/M000105.html +18 -0
- data/data/rushcheck/rdoc/classes/FalseClass.html +15 -15
- data/data/rushcheck/rdoc/classes/FalseClass.src/M000022.html +18 -0
- data/data/rushcheck/rdoc/classes/FalseClass.src/M000023.html +18 -0
- data/data/rushcheck/rdoc/classes/FalseClass.src/M000024.html +18 -0
- data/data/rushcheck/rdoc/classes/Float.html +20 -20
- data/data/rushcheck/rdoc/classes/Float.src/M000052.html +21 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000053.html +18 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000054.html +22 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000055.html +20 -0
- data/data/rushcheck/rdoc/classes/Gen.html +102 -102
- data/data/rushcheck/rdoc/classes/Gen.src/M000030.html +4 -10
- data/data/rushcheck/rdoc/classes/Gen.src/M000031.html +29 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000032.html +6 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000033.html +14 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000034.html +10 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000035.html +4 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000036.html +4 -10
- data/data/rushcheck/rdoc/classes/Gen.src/M000037.html +4 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000038.html +4 -7
- data/data/rushcheck/rdoc/classes/Gen.src/M000039.html +4 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000040.html +10 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000041.html +4 -9
- data/data/rushcheck/rdoc/classes/Gen.src/M000042.html +7 -5
- data/data/rushcheck/rdoc/classes/Gen.src/M000043.html +4 -4
- data/data/rushcheck/rdoc/classes/Gen.src/M000044.html +4 -10
- data/data/rushcheck/rdoc/classes/Gen.src/M000045.html +23 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000046.html +19 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000047.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000048.html +24 -0
- data/data/rushcheck/rdoc/classes/Guard.html +10 -10
- data/data/rushcheck/rdoc/classes/Guard.src/M000028.html +27 -0
- data/data/rushcheck/rdoc/classes/Guard.src/M000029.html +18 -0
- data/data/rushcheck/rdoc/classes/HsRandom.html +20 -20
- data/data/rushcheck/rdoc/classes/HsRandom.src/M000088.html +22 -0
- data/data/rushcheck/rdoc/classes/HsRandom.src/M000089.html +32 -0
- data/data/rushcheck/rdoc/classes/HsRandom.src/M000090.html +18 -0
- data/data/rushcheck/rdoc/classes/Integer.html +20 -20
- data/data/rushcheck/rdoc/classes/Integer.src/M000010.html +18 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000011.html +18 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000012.html +21 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000013.html +19 -0
- data/data/rushcheck/rdoc/classes/NilClass.html +15 -15
- data/data/rushcheck/rdoc/classes/NilClass.src/M000064.html +18 -0
- data/data/rushcheck/rdoc/classes/NilClass.src/M000065.html +18 -0
- data/data/rushcheck/rdoc/classes/NilClass.src/M000066.html +18 -0
- data/data/rushcheck/rdoc/classes/Property.html +10 -10
- data/data/rushcheck/rdoc/classes/Property.src/M000077.html +26 -0
- data/data/rushcheck/rdoc/classes/Property.src/M000078.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomArray.html +15 -15
- data/data/rushcheck/rdoc/classes/RandomArray.src/M000025.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomArray.src/M000026.html +35 -0
- data/data/rushcheck/rdoc/classes/RandomArray.src/M000027.html +22 -0
- data/data/rushcheck/rdoc/classes/RandomBool.html +10 -10
- data/data/rushcheck/rdoc/classes/RandomBool.src/M000086.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomBool.src/M000087.html +19 -0
- data/data/rushcheck/rdoc/classes/RandomGen.html +20 -20
- data/data/rushcheck/rdoc/classes/RandomGen.src/M000083.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomGen.src/M000084.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomGen.src/M000085.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomHash.html +16 -16
- data/data/rushcheck/rdoc/classes/RandomHash.src/M000049.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomHash.src/M000050.html +26 -0
- data/data/rushcheck/rdoc/classes/RandomHash.src/M000051.html +22 -0
- data/data/rushcheck/rdoc/classes/RandomProc.html +20 -20
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000060.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000061.html +30 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000062.html +26 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000063.html +20 -0
- data/data/rushcheck/rdoc/classes/Result.html +19 -19
- data/data/rushcheck/rdoc/classes/Result.src/M000056.html +18 -0
- data/data/rushcheck/rdoc/classes/Result.src/M000057.html +18 -0
- data/data/rushcheck/rdoc/classes/Result.src/M000058.html +18 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.html +41 -11
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000001.html +1 -1
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000002.html +1 -1
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000003.html +8 -4
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000004.html +4 -24
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000005.html +22 -39
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000006.html +55 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000007.html +50 -0
- data/data/rushcheck/rdoc/classes/SpecialString.html +5 -5
- data/data/rushcheck/rdoc/classes/SpecialString.src/M000021.html +37 -0
- data/data/rushcheck/rdoc/classes/StdGen.html +27 -27
- data/data/rushcheck/rdoc/classes/StdGen.src/M000014.html +9 -4
- data/data/rushcheck/rdoc/classes/StdGen.src/M000015.html +21 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000016.html +21 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000017.html +18 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000018.html +18 -0
- data/data/rushcheck/rdoc/classes/String.html +20 -20
- data/data/rushcheck/rdoc/classes/String.src/M000073.html +24 -0
- data/data/rushcheck/rdoc/classes/String.src/M000074.html +18 -0
- data/data/rushcheck/rdoc/classes/String.src/M000075.html +25 -0
- data/data/rushcheck/rdoc/classes/String.src/M000076.html +22 -0
- data/data/rushcheck/rdoc/classes/TestExausted.html +113 -0
- data/data/rushcheck/rdoc/classes/TestFailed.html +155 -0
- data/data/rushcheck/rdoc/classes/TestFailed.src/M000067.html +18 -0
- data/data/rushcheck/rdoc/classes/TestOk.html +113 -0
- data/data/rushcheck/rdoc/classes/TestOptions.html +180 -0
- data/data/rushcheck/rdoc/classes/TestOptions.src/M000008.html +18 -0
- data/data/rushcheck/rdoc/classes/TestOptions.src/M000009.html +18 -0
- data/data/rushcheck/rdoc/classes/TestResult.html +164 -0
- data/data/rushcheck/rdoc/classes/TestResult.src/M000068.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.html +96 -51
- data/data/rushcheck/rdoc/classes/Testable.src/M000091.html +4 -4
- data/data/rushcheck/rdoc/classes/Testable.src/M000092.html +4 -4
- data/data/rushcheck/rdoc/classes/Testable.src/M000095.html +4 -4
- data/data/rushcheck/rdoc/classes/Testable.src/M000096.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000097.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000099.html +19 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000100.html +21 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000101.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000103.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000104.html +18 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.html +20 -20
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000069.html +18 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000070.html +20 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000071.html +21 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000072.html +18 -0
- data/data/rushcheck/rdoc/classes/TrueClass.html +15 -15
- data/data/rushcheck/rdoc/classes/TrueClass.src/M000079.html +18 -0
- data/data/rushcheck/rdoc/classes/TrueClass.src/M000080.html +18 -0
- data/data/rushcheck/rdoc/classes/TrueClass.src/M000081.html +18 -0
- data/data/rushcheck/rdoc/created.rid +1 -1
- data/data/rushcheck/rdoc/files/rushcheck/config_rb.html +8 -1
- data/data/rushcheck/rdoc/files/rushcheck/testable_rb.html +3 -1
- data/data/rushcheck/rdoc/files/rushcheck/testoptions_rb.html +109 -0
- data/data/rushcheck/rdoc/files/rushcheck/testresult_rb.html +105 -0
- data/data/rushcheck/rdoc/files/rushcheck_rb.html +127 -0
- data/data/rushcheck/rdoc/fr_class_index.html +5 -0
- data/data/rushcheck/rdoc/fr_file_index.html +3 -1
- data/data/rushcheck/rdoc/fr_method_index.html +103 -94
- data/lib/rushcheck/arbitrary.rb +16 -12
- data/lib/rushcheck/array.rb +7 -6
- data/lib/rushcheck/assertion.rb +53 -50
- data/lib/rushcheck/bool.rb +26 -24
- data/lib/rushcheck/config.rb +131 -81
- data/lib/rushcheck/float.rb +4 -4
- data/lib/rushcheck/gen.rb +194 -182
- data/lib/rushcheck/guard.rb +9 -10
- data/lib/rushcheck/hash.rb +4 -3
- data/lib/rushcheck/integer.rb +11 -6
- data/lib/rushcheck/proc.rb +7 -7
- data/lib/rushcheck/property.rb +19 -15
- data/lib/rushcheck/random.rb +162 -159
- data/lib/rushcheck/result.rb +16 -12
- data/lib/rushcheck/string.rb +12 -12
- data/lib/rushcheck/testable.rb +99 -25
- data/lib/rushcheck/testoptions.rb +20 -0
- data/lib/rushcheck/testresult.rb +25 -0
- data/lib/{rushcheck/rushcheck.rb → rushcheck.rb} +2 -1
- metadata +93 -4
- data/data/rushcheck/doc/rushcheck.txt +0 -670
@@ -0,0 +1,832 @@
|
|
1
|
+
<address>
|
2
|
+
last-modified: 2006-10-06 Daisuke IKEGAMI <ikegami@madscientist.jp>
|
3
|
+
</address>
|
4
|
+
|
5
|
+
This tutorial is written in a simple markup language
|
6
|
+
"RedCloth3":http://whytheluckystiff.net/ruby/redcloth/.
|
7
|
+
This file is also dawnloadable from "rushcheck.txt":rushcheck.txt
|
8
|
+
and also in the distribution.
|
9
|
+
|
10
|
+
h1. Index
|
11
|
+
|
12
|
+
# <a href="#Getting start">Getting start</a>
|
13
|
+
## <a href="#install by RubyGems">(Option 1.) install by RubyGems</a>
|
14
|
+
## <a href="#using setup.rb after download source codes">(Option 2.) using setup.rb after download source codes</a>
|
15
|
+
# <a href="#Tutorial for writing testcase">Tutorial for writing testcase</a>
|
16
|
+
## <a href="#At first, we have to require the library.">At first, we have to require the library.</a>
|
17
|
+
## <a href="#Start writing testcases">Start writing testcases</a>
|
18
|
+
## <a href="#Watching the statistics">Watching the statistics</a>
|
19
|
+
### <a href="#trivial">'trivial'</a>
|
20
|
+
### <a href="#classify">'classify'</a>
|
21
|
+
## <a href="#With another basic classes for assertions">With another basic classes for assertions</a>
|
22
|
+
### <a href="#SpecialString">SpecialString</a>
|
23
|
+
### <a href="#Array and RandomArray">Array and RandomArray</a>
|
24
|
+
### <a href="#Hash and RandomHash">Hash and RandomHash</a>
|
25
|
+
### <a href="#Proc and RandomProc">Proc and RandomProc</a>
|
26
|
+
## <a href="#How to define random generators for user defined class">How to define random generators for user defined class</a>
|
27
|
+
### <a href="#using Gen.create">using Gen.create</a>
|
28
|
+
### <a href="#using Gen.bind and Gen.unit">using Gen.bind and Gen.unit</a>
|
29
|
+
### <a href="#using Gen.new">using Gen.new</a>
|
30
|
+
## <a href="#Another staffs in Gen class">Another staffs in Gen class</a>
|
31
|
+
### <a href="#Gen.choose">Gen.choose</a>
|
32
|
+
### <a href="#Gen.frequency">Gen.frequency</a>
|
33
|
+
### <a href="#Gen.lift_array">Gen.lift_array</a>
|
34
|
+
### <a href="#Gen.oneof">Gen.oneof</a>
|
35
|
+
### <a href="#Gen.promote">Gen.promote</a>
|
36
|
+
### <a href="#Gen.rand">Gen.rand</a>
|
37
|
+
### <a href="#Gen.sized">Gen.sized</a>
|
38
|
+
### <a href="#Gen.unit">Gen.unit</a>
|
39
|
+
### <a href="#Gen.vector">Gen.vector</a>
|
40
|
+
## <a href="#how to write random Proc which returns objects in YourClass">how to write random Proc which returns objects in YourClass</a>
|
41
|
+
# <a href="#Further information">Further information</a>
|
42
|
+
|
43
|
+
h1. <a name="Getting start">Getting start</a>
|
44
|
+
|
45
|
+
There are two ways to install RushCheck.
|
46
|
+
|
47
|
+
h2. <a name="install by RubyGems">(Option 1.) install by RubyGems</a>
|
48
|
+
|
49
|
+
You can install RushCheck easily with
|
50
|
+
"rubygems":http://docs.rubygems.org/.
|
51
|
+
|
52
|
+
<pre>% sudo gem install rushcheck</pre>
|
53
|
+
|
54
|
+
Done!
|
55
|
+
|
56
|
+
h2. <a name="using setup.rb after download source codes">(Option 2.) using setup.rb after download source codes.</a>
|
57
|
+
|
58
|
+
Instead, if you don't have rubygems, or like to install from source
|
59
|
+
codes, then you can follow the steps.
|
60
|
+
|
61
|
+
# Get the tar-ball of current release from
|
62
|
+
"download page":http://rubyforge.org/frs/?group_id=2027
|
63
|
+
# Expand it
|
64
|
+
# finally, type as follows
|
65
|
+
|
66
|
+
<pre>% sudo ruby setup.rb</pre>
|
67
|
+
|
68
|
+
See also the following;
|
69
|
+
|
70
|
+
<pre>% setup.rb help</pre>
|
71
|
+
|
72
|
+
h1. <a name="Tutorial for writing testcase">Tutorial for writing testcase</a>
|
73
|
+
|
74
|
+
h2. <a name="At first, we have to require the library.">At first, we have to require the library.</a>
|
75
|
+
|
76
|
+
If you have installed RushCheck using RubyGems, then you should add
|
77
|
+
the following two lines to your test codes.
|
78
|
+
|
79
|
+
<pre>
|
80
|
+
require 'rubygems'
|
81
|
+
require_gem 'rushcheck'
|
82
|
+
</pre>
|
83
|
+
|
84
|
+
Otherwise, if you have installed RushCheck by setup.rb, then
|
85
|
+
add the simple one line.
|
86
|
+
|
87
|
+
<pre>
|
88
|
+
require 'rushcheck'
|
89
|
+
</pre>
|
90
|
+
|
91
|
+
The following maybe useful if you don't matter whether you use
|
92
|
+
rubygems or not.
|
93
|
+
<pre>
|
94
|
+
begin
|
95
|
+
require 'rubygems'
|
96
|
+
require_gem 'rushcheck'
|
97
|
+
rescue LoadError
|
98
|
+
require 'rushcheck'
|
99
|
+
end
|
100
|
+
</pre>
|
101
|
+
|
102
|
+
h2. Don't forget to require also your library file if the class you want to test is included in it.
|
103
|
+
|
104
|
+
<pre>
|
105
|
+
require 'your_library'
|
106
|
+
</pre>
|
107
|
+
|
108
|
+
h2. <a name="Start writing testcases">Start writing testcases</a>
|
109
|
+
|
110
|
+
OK, then we can start to write test codes. RushCheck requires to
|
111
|
+
write __assertion based__ testcases. An assertion of function (or
|
112
|
+
method) consists of triple where inputs, guard conditions and a
|
113
|
+
testing property block. Here is a templete of assertion:
|
114
|
+
|
115
|
+
<pre>
|
116
|
+
RushCheck::Assertion.new(Class1, Class2, ...) do |var1, var2, ...|
|
117
|
+
# testing property block
|
118
|
+
# this block should return boolean value (true, false or nil)
|
119
|
+
# in Ruby
|
120
|
+
end
|
121
|
+
</pre>
|
122
|
+
|
123
|
+
For example, assume that we want to test the method 'sort' in
|
124
|
+
Array. The following assertion is a simple testcase:
|
125
|
+
|
126
|
+
<pre>
|
127
|
+
ast_zero =
|
128
|
+
RushCheck::Assertion.new() do
|
129
|
+
[].sort == []
|
130
|
+
end
|
131
|
+
</pre>
|
132
|
+
|
133
|
+
whether if we sort empty array the result is also empty.
|
134
|
+
This assertion does not have any inputs and guards but only have
|
135
|
+
the property block.
|
136
|
+
|
137
|
+
Let's see another example:
|
138
|
+
<pre>
|
139
|
+
ast_one =
|
140
|
+
RushCheck::Assertion.new(Integer) do |x|
|
141
|
+
[x].sort == [x]
|
142
|
+
end
|
143
|
+
</pre>
|
144
|
+
|
145
|
+
This assertion defines that we claim for any integer 'x', an array
|
146
|
+
[x] is not changed after sorting. We can test the property 100 times:
|
147
|
+
|
148
|
+
<pre>
|
149
|
+
irb> ast_one.verbose_check
|
150
|
+
1:
|
151
|
+
[-1]
|
152
|
+
2:
|
153
|
+
[-2]
|
154
|
+
... (snip) ...
|
155
|
+
99:
|
156
|
+
[6]
|
157
|
+
100:
|
158
|
+
[1]
|
159
|
+
OK, passed 100 tests.
|
160
|
+
true
|
161
|
+
irb> ast_one.check
|
162
|
+
OK, passed 100 tests.
|
163
|
+
true
|
164
|
+
irb>
|
165
|
+
</pre>
|
166
|
+
|
167
|
+
RushCheck supports random testing such as above. We will see later
|
168
|
+
how to change the number of test, how to change the distribution,
|
169
|
+
etc. Here we learned two testing methods, verbose_check and check.
|
170
|
+
'verbose_check' displays every instances of test, on the other hand
|
171
|
+
'check' does not display inputs but only the result.
|
172
|
+
|
173
|
+
Next example shows how RushCheck displays the counter example. If
|
174
|
+
an assertion is failed, then there is a counter example of the
|
175
|
+
assertion.
|
176
|
+
|
177
|
+
<pre>
|
178
|
+
ast_two =
|
179
|
+
RushCheck::Assertion.new(Integer, Integer) do |x, y|
|
180
|
+
[x, y].sort == [x, y]
|
181
|
+
end
|
182
|
+
</pre>
|
183
|
+
|
184
|
+
The above test is failed sometimes and we can find the result after
|
185
|
+
checking.
|
186
|
+
|
187
|
+
<pre>
|
188
|
+
irb> ast_two.check
|
189
|
+
Falsifiable, after 3 tests:
|
190
|
+
[2, -1]
|
191
|
+
false
|
192
|
+
irb>
|
193
|
+
</pre>
|
194
|
+
|
195
|
+
Here, the counter example [2, -1] of the assertion is appeared. In
|
196
|
+
fact, [2, -1].sort equals [-1, 2] and does not equal [2, -1].
|
197
|
+
|
198
|
+
Sometimes, we need several pre-conditions for tests. For example,
|
199
|
+
if we have a pre-condition 'x <= y' in the previous assertion, then
|
200
|
+
the assertion should be succeeded. We can write pre-conditions as
|
201
|
+
guards in the property block:
|
202
|
+
|
203
|
+
<pre>
|
204
|
+
ast_two_sorted =
|
205
|
+
RushCheck::Assertion.new(Integer, Integer) do |x, y|
|
206
|
+
RushCheck::guard { x <= y }
|
207
|
+
[x, y].sort == [x, y]
|
208
|
+
end
|
209
|
+
</pre>
|
210
|
+
<pre>
|
211
|
+
irb> ast_two_sorted.check
|
212
|
+
OK, passed 100 tests.
|
213
|
+
true
|
214
|
+
irb>
|
215
|
+
</pre>
|
216
|
+
|
217
|
+
Note that it is always assumed that the number of arguments of
|
218
|
+
Assertion.new must be equal to the number of variables of the block.
|
219
|
+
(Until ver 0.3, experimentally the number of arguments can be
|
220
|
+
differed, however from ver 0.4, they must be equal.)
|
221
|
+
The arguments of Assertion.new corresponds to the variables of block
|
222
|
+
one to one. We can have any number of guards in the property block.
|
223
|
+
If the guard property does not hold in random testing, then the test
|
224
|
+
is abort and try to take another random instances. We can imagine the
|
225
|
+
following test sequences in ast_two_sorted.
|
226
|
+
|
227
|
+
# x, y = 1, 2
|
228
|
+
-> guard g is passed
|
229
|
+
-> check the test block and succeed
|
230
|
+
# x, y = 3, 1
|
231
|
+
-> guard g is failed and abort
|
232
|
+
(not counted)
|
233
|
+
# x, y = 2, 3
|
234
|
+
-> ...
|
235
|
+
# ... (whether passed 100 tests or not)
|
236
|
+
|
237
|
+
h2. <a name="Watching the statistics">Watching the statistics</a>
|
238
|
+
|
239
|
+
In the previous section, we saw two methods 'check' and
|
240
|
+
'verbose_check'. Sometimes, we want to watch the statistics of
|
241
|
+
random testing. However 'check' shows less information, and
|
242
|
+
'verbose_check' is too noisy. RushCheck has several options to
|
243
|
+
watch the statistics.
|
244
|
+
|
245
|
+
h3. <a name="trivial">'trivial'</a>
|
246
|
+
|
247
|
+
You may not want to check the trivial case in random test. As we
|
248
|
+
have seen, we can ignore the trivial case using the guard
|
249
|
+
condition. However, on the other hand, we can watch how many
|
250
|
+
trivial cases are appeared in random test.
|
251
|
+
|
252
|
+
<pre>
|
253
|
+
ast_sort_triv =
|
254
|
+
RushCheck::Assertion.new(Integer, Integer) do |x, y|
|
255
|
+
RushCheck::guard {x <= y}
|
256
|
+
([x, y].sort == [x, y]).trivial{ x == y }
|
257
|
+
end
|
258
|
+
</pre>
|
259
|
+
<pre>
|
260
|
+
irb> ast_sort_triv.check
|
261
|
+
OK, passed 100 tests(14%, trivial).
|
262
|
+
true
|
263
|
+
</pre>
|
264
|
+
|
265
|
+
Here, we have 14% (i.e. 14 times) trivial (x == y) cases in the
|
266
|
+
test.
|
267
|
+
|
268
|
+
h3. <a name="classify">'classify'</a>
|
269
|
+
|
270
|
+
In addition, we can give another names to watching statistics.
|
271
|
+
|
272
|
+
<pre>
|
273
|
+
ast_sort_classify =
|
274
|
+
RushCheck::Assertion.new(Integer, Integer) do |x, y|
|
275
|
+
RushCheck::guard {x <= y}
|
276
|
+
test = ([x, y].sort == [x, y])
|
277
|
+
test.classify('same'){ x == y }.
|
278
|
+
classify('bit diff'){ (x - y).abs == 1 }
|
279
|
+
end
|
280
|
+
</pre>
|
281
|
+
<pre>
|
282
|
+
irb> ast_sort_classify.check
|
283
|
+
OK, passed 100 tests.
|
284
|
+
18%, same.
|
285
|
+
11%, bit diff.
|
286
|
+
true
|
287
|
+
irb>
|
288
|
+
</pre>
|
289
|
+
|
290
|
+
h2. <a name="With another basic classes for assertions">With another basic classes for assertions</a>
|
291
|
+
|
292
|
+
In previous sections, we have seen how to check assertions for any
|
293
|
+
integers. In similar way, we can define the assertions for any float
|
294
|
+
numbers or any string.
|
295
|
+
|
296
|
+
<pre>
|
297
|
+
RushCheck::Assertion.new(Float, String, ...) do |ratio, name,...|
|
298
|
+
# testcase
|
299
|
+
end
|
300
|
+
</pre>
|
301
|
+
|
302
|
+
RushCheck has default random generators for the following basic classes:
|
303
|
+
|
304
|
+
* Integer
|
305
|
+
* Float
|
306
|
+
* String
|
307
|
+
|
308
|
+
If you want to change the distribution of randomness, then you have
|
309
|
+
to write a code for generator. There are some examples for writing
|
310
|
+
generators. In the next section, I will introduce SpecialString
|
311
|
+
whose distribution differs to the default implementation of String.
|
312
|
+
|
313
|
+
Even Array, Hash and Proc are also primitive classes, however the
|
314
|
+
randomness of them should be changed in testing codes. Therefore,
|
315
|
+
RushCheck provides an abstract generators for them. Programmer need
|
316
|
+
to write a subclass of the abstract generators. Later
|
317
|
+
I will show you how to write a subclass of RandomArray, etc.
|
318
|
+
|
319
|
+
h3. <a name="SpecialString">SpecialString</a>
|
320
|
+
|
321
|
+
Sometimes, we want to check special characters, for example the
|
322
|
+
backslash '\' or unprinted characters 'ESC', 'NUL' and so on.
|
323
|
+
SpecialString is a subclass of String which is defined in
|
324
|
+
'rushcheck/string'. This library is already required in
|
325
|
+
'rushcheck/rushcheck' and don't need to require again.
|
326
|
+
|
327
|
+
The output of random generator of SpecialString has different
|
328
|
+
distribution of its of String. At String, the distribution of
|
329
|
+
characters are normalized. On the other hand, the distribution in
|
330
|
+
SpecialString is weighted and the generator provides special
|
331
|
+
characters more often than alphabets. In detail, the distribution is
|
332
|
+
as follows:
|
333
|
+
|
334
|
+
|_.the distribution of SpecialString |
|
335
|
+
|Alphabet |15% |
|
336
|
+
|Control characters|50% (such as NUL)|
|
337
|
+
|Number |10% |
|
338
|
+
|Special characters|25% (such as '\')|
|
339
|
+
|
340
|
+
Using SpecialString in assertions, it is more likely to find the
|
341
|
+
counter example. The following example is the famous bug which is
|
342
|
+
called 'malformed format bug'.
|
343
|
+
|
344
|
+
<pre>
|
345
|
+
malformed_format_string =
|
346
|
+
RushCheck::Assertion.new(String) { |s| sprintf(s); true}
|
347
|
+
|
348
|
+
malformed_format_string2 =
|
349
|
+
RushCheck::Assertion.new(SpecialString) { |s| sprintf(s); true}
|
350
|
+
</pre>
|
351
|
+
<pre>
|
352
|
+
irb> malformed_format_string.check
|
353
|
+
Falsifiable, after 86 tests:
|
354
|
+
Unexpected exception: #<ArgumentError: malformed format string - %&>
|
355
|
+
... snip error traces ...
|
356
|
+
["\n&'e!]hr(%&\031Vi\003 }ss"]
|
357
|
+
false
|
358
|
+
irb> malformed_format_string2.check
|
359
|
+
Falsifiable, after 15 tests:
|
360
|
+
Unexpected exception: #<ArgumentError: malformed format string>
|
361
|
+
["%\037-R"]
|
362
|
+
false
|
363
|
+
</pre>
|
364
|
+
|
365
|
+
In these results, we can see RushCheck find the counter example
|
366
|
+
after 86 tests with String, on the other hand, find it quickly after 15
|
367
|
+
tests with SpecialString.
|
368
|
+
|
369
|
+
It is easy to change the distribution in SpecialString. You can
|
370
|
+
define your subclass of SpecialString as follows:
|
371
|
+
|
372
|
+
<pre>
|
373
|
+
class YourSpecialString < SpecialString
|
374
|
+
@@frequency = { 'alphabet' => 1,
|
375
|
+
'control' => 0,
|
376
|
+
'number' => 0,
|
377
|
+
'special' => 9 }
|
378
|
+
end
|
379
|
+
</pre>
|
380
|
+
|
381
|
+
h3. <a name="Array and RandomArray">Array and RandomArray</a>
|
382
|
+
|
383
|
+
The meaning of randomness for Array must be changed in testing
|
384
|
+
codes. Sometimes you needs a random array of Integer, and another a
|
385
|
+
random array of String. So what is random array?
|
386
|
+
|
387
|
+
RushCheck provides an abstract class RandomArray for abstract random
|
388
|
+
generator. Programmer have to write a subclass of RandomArray as
|
389
|
+
follows:
|
390
|
+
|
391
|
+
<pre>
|
392
|
+
# for random array of integers
|
393
|
+
class MyRandomArray < RandomArray; end
|
394
|
+
MyRandomArray.set_pattern(Integer) {|ary, i| Integer}
|
395
|
+
</pre>
|
396
|
+
|
397
|
+
The class method set_pattern takes a variable and a block.
|
398
|
+
Because array is __inductive__ structure, it can be defined by the
|
399
|
+
basecase and the inductive step.
|
400
|
+
|
401
|
+
For example, let's consider a random array in the following pattern
|
402
|
+
@[Integer, String, Integer, String, ...]@
|
403
|
+
where it has a random Integer at the odd index and a random String at
|
404
|
+
the even index. Then we can write a random array with this pattern:
|
405
|
+
|
406
|
+
<pre>
|
407
|
+
MyRandomArray.set_pattern(Integer) do |ary, i|
|
408
|
+
if i % 2 == 0
|
409
|
+
then Integer
|
410
|
+
else String
|
411
|
+
end
|
412
|
+
end
|
413
|
+
</pre>
|
414
|
+
|
415
|
+
More complecated example? OK, let's consider a stream:
|
416
|
+
* the first component is Integer
|
417
|
+
* if the i-th component is positive integer
|
418
|
+
** then (i+1)-th component is String
|
419
|
+
** otherwise the (i+1)-th component is Integer
|
420
|
+
|
421
|
+
<pre>
|
422
|
+
MyRandomArray.set_pattern(Integer) do |ary, i|
|
423
|
+
if ary[i].kind_of?(Integer) && ary[i] >= 0
|
424
|
+
then String
|
425
|
+
else Integer
|
426
|
+
end
|
427
|
+
end
|
428
|
+
</pre>
|
429
|
+
|
430
|
+
In this way, we can define any random array with any pattern.
|
431
|
+
|
432
|
+
h3. <a name="Hash and RandomHash">Hash and RandomHash</a>
|
433
|
+
|
434
|
+
Hash is also primitive and not so clear what is a random hash, like
|
435
|
+
array. RushCheck provides an abstract random generator RandomHash,
|
436
|
+
and programmer can write a subclass of RandomHash.
|
437
|
+
|
438
|
+
<pre>
|
439
|
+
class MyRandomHash < RandomHash; end
|
440
|
+
pat = { 'key1' => Integer, 'key2' => String }
|
441
|
+
MyRandomHash.set_pattern(pat)
|
442
|
+
</pre>
|
443
|
+
|
444
|
+
In this example, we can get a random Hash with two keys ('key1' and
|
445
|
+
'key2'). Here the keys are String, but we can give any object as
|
446
|
+
usual in Hash. Is it clear to define random hash? I think so.
|
447
|
+
(If not it is clear, then the interface may be changed in future)
|
448
|
+
|
449
|
+
h3. <a name="Proc and RandomProc">Proc and RandomProc</a>
|
450
|
+
|
451
|
+
It is not difficult to create a random Proc object.
|
452
|
+
As we saw in the previous sections, we have to write a subclass of
|
453
|
+
RandomProc.
|
454
|
+
|
455
|
+
<pre>
|
456
|
+
class MyRandomProc < RandomProc; end
|
457
|
+
MyRandomProc.set_pattern([Integer], [Integer])
|
458
|
+
</pre>
|
459
|
+
|
460
|
+
Here, we define a random procedure which takes an integer and
|
461
|
+
returns an integer also. In general, Ruby's function and method can
|
462
|
+
be regarded as a relation. (not a function in mathematics!)
|
463
|
+
Therefore I think random procedures can be generated by a pair of
|
464
|
+
inputs and outputs.
|
465
|
+
|
466
|
+
Let's consider a simple example. In general, any functions f, g, and
|
467
|
+
h should satisfy the associativity property:
|
468
|
+
<pre>
|
469
|
+
for all x, f(g(h(x)) === (f . g)(h (x))
|
470
|
+
where f . g is a composition of functions in mathematical way
|
471
|
+
</pre>
|
472
|
+
|
473
|
+
<pre>
|
474
|
+
class Proc
|
475
|
+
# application
|
476
|
+
def **(other)
|
477
|
+
Proc.new do |*args|
|
478
|
+
res = other.call(*args)
|
479
|
+
call(*res)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
class MyRandomProc < RandomProc; end
|
485
|
+
|
486
|
+
def associativity_integer
|
487
|
+
MyRandomProc.set_pattern([Integer], [Integer])
|
488
|
+
RushCheck::Assertion.new(MyRandomProc, MyRandomProc,
|
489
|
+
MyRandomProc, Integer) do
|
490
|
+
|f, g, h, x|
|
491
|
+
(f ** (g ** h)).call(x) == ((f ** g) ** h).call(x)
|
492
|
+
end.check
|
493
|
+
end
|
494
|
+
</pre>
|
495
|
+
|
496
|
+
P.S.
|
497
|
+
The arbitrary method is used to create a random object for test
|
498
|
+
instance. Then you may wonder what is the coarbitrary method?
|
499
|
+
The coarbitrary method is used to generate a random procedure
|
500
|
+
(lambda), which is one of central idea in QuickCheck.
|
501
|
+
|
502
|
+
h2. <a name="How to define random generators for user defined class">How to define random generators for user defined class</a>
|
503
|
+
|
504
|
+
h3. Understand your class. What is a random object?
|
505
|
+
|
506
|
+
To use your class in the assertion, like follows
|
507
|
+
<pre>
|
508
|
+
RushCheck::Assertion.new(YourClass) { |obj, ...| ...}
|
509
|
+
</pre>
|
510
|
+
you have to write a code which generates a random object in your
|
511
|
+
class. Therefore, at first we have to consider
|
512
|
+
__what is a random object in YourClass?__
|
513
|
+
|
514
|
+
Sometimes the answer is not unique; there may be several ways for
|
515
|
+
generating random objects. Like SpecialString in RushCheck, you can
|
516
|
+
also write an abstract random generator.
|
517
|
+
|
518
|
+
OK, after thinking about the question, we have to write a code.
|
519
|
+
To define random generators, we have to add a class method arbitrary
|
520
|
+
in YourClass.
|
521
|
+
|
522
|
+
<pre>
|
523
|
+
class YourClass
|
524
|
+
extend RushCheck::Arbitrary
|
525
|
+
|
526
|
+
def self.arbitrary
|
527
|
+
# override the class method arbitrary
|
528
|
+
...
|
529
|
+
end
|
530
|
+
end
|
531
|
+
</pre>
|
532
|
+
|
533
|
+
If you need to define a random proc which returns a object in
|
534
|
+
YourClass, you have to include Coarbitrary, also.
|
535
|
+
|
536
|
+
<pre>
|
537
|
+
class YourClass
|
538
|
+
extend RushCheck::Arbitrary
|
539
|
+
include RushCheck::Coarbitrary
|
540
|
+
|
541
|
+
def self.arbitrary
|
542
|
+
...
|
543
|
+
end
|
544
|
+
|
545
|
+
def coarbitrary(g)
|
546
|
+
...
|
547
|
+
end
|
548
|
+
end
|
549
|
+
</pre>
|
550
|
+
|
551
|
+
However, because it is little complecated to implement both
|
552
|
+
arbitrary and coarbitrary, let's focus how to implement arbitrary
|
553
|
+
first.
|
554
|
+
|
555
|
+
Let's consider the first example Candy. The Candy class requires its
|
556
|
+
name and its price at initialize. The name should be a String, and the
|
557
|
+
price Integer. The Candy class may have several instance methods, but
|
558
|
+
they are omitted because not important to define the random object.
|
559
|
+
|
560
|
+
<pre>
|
561
|
+
class Candy
|
562
|
+
|
563
|
+
def initialize(name, price)
|
564
|
+
raise unless price >= 0
|
565
|
+
@name, @price = name, price
|
566
|
+
end
|
567
|
+
|
568
|
+
def foo
|
569
|
+
...
|
570
|
+
end
|
571
|
+
|
572
|
+
def bar
|
573
|
+
...
|
574
|
+
end
|
575
|
+
|
576
|
+
end
|
577
|
+
</pre>
|
578
|
+
|
579
|
+
To write random generator, we have to look up 'initialize'.
|
580
|
+
Here, assume that @name belongs String and @price belongs Integer.
|
581
|
+
It is natural that we assumes @price should be positive.
|
582
|
+
|
583
|
+
One simple random generator for Candy:
|
584
|
+
|
585
|
+
h3. <a name="using Gen.create">(1) using Gen.create</a>
|
586
|
+
|
587
|
+
<pre>
|
588
|
+
class Candy
|
589
|
+
extend Arbitrary
|
590
|
+
|
591
|
+
def self.arbitrary
|
592
|
+
RushCheck::Gen.create(String, Integer) do |name, price|
|
593
|
+
RushCheck::guard { price >= 0 }
|
594
|
+
new(name, price)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
</pre>
|
599
|
+
|
600
|
+
Gen.create takes an array of Gen object (here, [Integer.arbitrary,
|
601
|
+
String.arbitrary]) and a block. The block takes variables which is
|
602
|
+
corresponded to the array, as Assertion.new. If guard is failed,
|
603
|
+
then RushCheck retry to create another random instance.
|
604
|
+
|
605
|
+
Note that we can use a trick instead of the guard property.
|
606
|
+
<pre>
|
607
|
+
price = - price if price < 0 # g.guard { price >= 0 }
|
608
|
+
</pre>
|
609
|
+
In this case, this is more efficient to generate random instance
|
610
|
+
than with the guard. However, sometimes we don't have this kind
|
611
|
+
trick and we can use some guards.
|
612
|
+
|
613
|
+
Remark: from version 0.4, Gen.create is changed to require classes
|
614
|
+
in its argument from Gen objects.
|
615
|
+
|
616
|
+
h3. <a name="using Gen.bind and Gen.unit">(2) using Gen#bind and Gen.unit</a>
|
617
|
+
|
618
|
+
<pre>
|
619
|
+
class Candy
|
620
|
+
extend RushCheck::Arbitrary
|
621
|
+
|
622
|
+
def self.arbitrary
|
623
|
+
String.arbitrary.bind do |name|
|
624
|
+
Integer.arbitrary.bind do |price|
|
625
|
+
price = - price if price < 0 # trick as I described above
|
626
|
+
RushCheck::Gen.unit(new(name, price))
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|
631
|
+
</pre>
|
632
|
+
|
633
|
+
Puzzled? OK, they can be readed as follows:
|
634
|
+
|
635
|
+
* take a random (arbitrary) string and call it 'name'
|
636
|
+
** take a random integer and call it 'price'
|
637
|
+
*** return a Gen object which has a new Candy(name, price)
|
638
|
+
|
639
|
+
In general, the class method arbitrary should return a Gen object.
|
640
|
+
Check also gen.rb in RushCheck. There are several combinators to
|
641
|
+
create random generators.
|
642
|
+
|
643
|
+
There are several way to implement random generators. The next
|
644
|
+
example is to use Gen.new without bind and unit.
|
645
|
+
|
646
|
+
h3. <a name="using Gen.new">(3) using Gen.new</a>
|
647
|
+
|
648
|
+
<pre>
|
649
|
+
class Candy
|
650
|
+
extend RushCheck::Arbitrary
|
651
|
+
|
652
|
+
def self.arbitrary
|
653
|
+
RushCheck::Gen.new do |n, r|
|
654
|
+
r2 = r
|
655
|
+
name, price = [String, Integer].map do |c|
|
656
|
+
r1, r2 = r2.split
|
657
|
+
c.arbitrary.value(n. r1)
|
658
|
+
end
|
659
|
+
price = - price if price < 0 # trick
|
660
|
+
new(name, price)
|
661
|
+
end
|
662
|
+
end
|
663
|
+
end
|
664
|
+
</pre>
|
665
|
+
|
666
|
+
This pattern is useful if your class has many valiables for
|
667
|
+
initialize. Because binding patterns needs much depth of method call
|
668
|
+
chains, it may be failed. This technique is used to avoid the stack
|
669
|
+
overflow. This is one difference between Haskell and Ruby.
|
670
|
+
|
671
|
+
The implementation can be understanded as follows:
|
672
|
+
* self.arbitrary returns a new Gen object.
|
673
|
+
** let n be an integer and r be a random generator.
|
674
|
+
** let r2 equal r
|
675
|
+
** name and price are both random objects where
|
676
|
+
*** get new two random generator r1 and r2 from old r2
|
677
|
+
*** assign a random value by generating 'arbitrary.value(n, r1)'
|
678
|
+
**** and discard the random generator r1
|
679
|
+
**** ...
|
680
|
+
|
681
|
+
Note that we need new random generator for each random object.
|
682
|
+
Here we create new random generator by spliting. If you use same
|
683
|
+
random generator for generating different objects, then the
|
684
|
+
distribution of objects are same (not generated randomly).
|
685
|
+
|
686
|
+
Because sometimes the initialize of YourClass is complecated,
|
687
|
+
then the random generator self.arbitrary turns to be complicated
|
688
|
+
also.
|
689
|
+
|
690
|
+
In next sections, I will introduce several generators in gen.rb.
|
691
|
+
They may be useful to create your own random genrator. See also rdoc
|
692
|
+
of Gen.
|
693
|
+
|
694
|
+
h3. Appendix: expensive candy.
|
695
|
+
|
696
|
+
Using Gen.create to generate random instance, if we gives another
|
697
|
+
guard such as
|
698
|
+
<pre>
|
699
|
+
RushCheck::guard { price >= 100000 } # very expensive candy!
|
700
|
+
</pre>
|
701
|
+
then it consumes much time to generate random instance because the
|
702
|
+
guard fails so many times. When RushCheck creates random instances,
|
703
|
+
it starts smallest as possible, then the size becomes larger in
|
704
|
+
repeating tests. Therefore, if the guard instance seems failed so
|
705
|
+
often, then we need another seeds of generators. Here is another
|
706
|
+
generators for expensive candy instance.
|
707
|
+
|
708
|
+
<pre>
|
709
|
+
lo = 100000
|
710
|
+
g = RushCheck::Gen.sized { |n| RushCheck::Gen.choose(lo, n + lo)}
|
711
|
+
xs = [String.arbitrary, g]
|
712
|
+
</pre>
|
713
|
+
See gen.rb and the following sections in details for how to get
|
714
|
+
another generator.
|
715
|
+
|
716
|
+
h2. <a name="Another staffs in Gen class">Another staffs in Gen class</a>
|
717
|
+
|
718
|
+
To help defining random objects in your class, there are several
|
719
|
+
functions in Gen class.
|
720
|
+
|
721
|
+
h3. <a name="Gen.choose">Gen.choose</a>
|
722
|
+
|
723
|
+
Gen.choose(lo, hi) returns a Gen object which generates a random
|
724
|
+
value in the bound.
|
725
|
+
|
726
|
+
example.
|
727
|
+
<pre>
|
728
|
+
Gen.choose(0, 10) # a generator of Integer in (0..10)
|
729
|
+
</pre>
|
730
|
+
|
731
|
+
h3. <a name="Gen.frequency">Gen.frequency</a>
|
732
|
+
|
733
|
+
Gen.frequency requires an array of pair of Integer and Gen objects,
|
734
|
+
and returns a Gen object. Gen.frequency is used to define the
|
735
|
+
distribution of randomness.
|
736
|
+
|
737
|
+
example.
|
738
|
+
<pre>
|
739
|
+
Gen.frequency([[3, Integer.arbitrary], [7, String.arbitrary]])
|
740
|
+
# return a random integer or a random string (by choosing
|
741
|
+
# randomly) Integer:30% String: 70%
|
742
|
+
</pre>
|
743
|
+
|
744
|
+
See also SpecialString.
|
745
|
+
|
746
|
+
h3. <a name="Gen.lift_array">Gen.lift_array</a>
|
747
|
+
|
748
|
+
Gen.lift_array takes an array and a block which has a variable.
|
749
|
+
The block should return a Gen object. lift_array returns a Gen
|
750
|
+
object which generates an array of the result of given block for
|
751
|
+
applying each member of given array.
|
752
|
+
|
753
|
+
example.
|
754
|
+
|
755
|
+
<pre>
|
756
|
+
class Candy
|
757
|
+
extend RushCheck::Arbitrary
|
758
|
+
|
759
|
+
def self.arbitrary
|
760
|
+
RushCheck::Gen.lift_array([Integer, String]) do |c|
|
761
|
+
c.arbitrary
|
762
|
+
end.bind do |args|
|
763
|
+
new(*args)
|
764
|
+
end
|
765
|
+
end
|
766
|
+
end
|
767
|
+
</pre>
|
768
|
+
|
769
|
+
h3. <a name="Gen.oneof">Gen.oneof</a>
|
770
|
+
|
771
|
+
Gen.oneof requires an array of Gen objects returns a Gen object.
|
772
|
+
|
773
|
+
example.
|
774
|
+
<pre>
|
775
|
+
Gen.oneof([Integer.arbitrary, String.arbitrary])
|
776
|
+
# return a random integer or a random string (by choosing
|
777
|
+
# randomly)
|
778
|
+
</pre>
|
779
|
+
|
780
|
+
h3. <a name="Gen.promote">Gen.promote</a>
|
781
|
+
|
782
|
+
Gen.promote is used to generate a random Proc object.
|
783
|
+
Next section I will describe how to define the random Proc object.
|
784
|
+
See also proc.rb in the example directory of RushCheck.
|
785
|
+
|
786
|
+
h3. <a name="Gen.rand">Gen.rand</a>
|
787
|
+
|
788
|
+
Gen.rand is a random number generator.
|
789
|
+
|
790
|
+
h3. <a name="Gen.sized">Gen.sized</a>
|
791
|
+
|
792
|
+
Gen.sized is used to change the size of random object.
|
793
|
+
See also some implementation in RushCheck (grep the source!)
|
794
|
+
|
795
|
+
h3. <a name="Gen.unit">Gen.unit</a>
|
796
|
+
|
797
|
+
return Gen object.
|
798
|
+
|
799
|
+
h3. <a name="Gen.vector">Gen.vector</a>
|
800
|
+
|
801
|
+
Get a vector of Gen.
|
802
|
+
|
803
|
+
example.
|
804
|
+
<pre>
|
805
|
+
Gen.vector(Integer, 3) # => Gen [Integer, Integer, Integer]
|
806
|
+
</pre>
|
807
|
+
|
808
|
+
h2. <a name="how to write random Proc which returns objects in YourClass">how to write random Proc which returns objects in YourClass</a>
|
809
|
+
|
810
|
+
It is complecated, and see some examples.
|
811
|
+
* rushcheck/bool.rb
|
812
|
+
* rushcheck/integer.rb
|
813
|
+
* rushcheck/string.rb
|
814
|
+
|
815
|
+
so on, grep 'coarbitrary'
|
816
|
+
|
817
|
+
FIXME: how to write coarbitrary
|
818
|
+
|
819
|
+
h1. <a name="Further information">Further information</a>
|
820
|
+
|
821
|
+
Webpage should have another useful information:
|
822
|
+
* "RushCheck Homepage http://rushcheck.rubyforge.org/":http://rushcheck.rubyforge.org/
|
823
|
+
|
824
|
+
The project page has a bug tracker and webboard.
|
825
|
+
* "RushCheck at Rubyforge http://rubyforge.org/projects/rushcheck/":http://rubyforge.org/projects/rushcheck/
|
826
|
+
|
827
|
+
There is no mailing list for RushCheck (now at 2006-08-08),
|
828
|
+
but don't hesitate to contact to the author!
|
829
|
+
|
830
|
+
Happy hacking and testing!
|
831
|
+
|
832
|
+
|