rushcheck 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +515 -0
- data/INSTALL +14 -0
- data/LICENSE +5 -0
- data/README +49 -0
- data/Rakefile +39 -0
- data/copying.txt +23 -0
- data/data/rushcheck/doc/policy.txt +520 -0
- data/data/rushcheck/doc/rushcheck.txt +612 -0
- data/data/rushcheck/examples/printf.rb +22 -0
- data/data/rushcheck/examples/proc.rb +33 -0
- data/data/rushcheck/examples/roguetile.rb +153 -0
- data/data/rushcheck/examples/sample.rb +52 -0
- data/data/rushcheck/rdoc/classes/Arbitrary.html +148 -0
- data/data/rushcheck/rdoc/classes/Arbitrary.src/M000075.html +18 -0
- data/data/rushcheck/rdoc/classes/Assertion.html +183 -0
- data/data/rushcheck/rdoc/classes/Assertion.src/M000015.html +20 -0
- data/data/rushcheck/rdoc/classes/Assertion.src/M000016.html +45 -0
- data/data/rushcheck/rdoc/classes/Coarbitrary.html +135 -0
- data/data/rushcheck/rdoc/classes/Coarbitrary.src/M000095.html +18 -0
- data/data/rushcheck/rdoc/classes/FalseClass.html +177 -0
- data/data/rushcheck/rdoc/classes/FalseClass.src/M000018.html +18 -0
- data/data/rushcheck/rdoc/classes/FalseClass.src/M000019.html +18 -0
- data/data/rushcheck/rdoc/classes/FalseClass.src/M000020.html +18 -0
- data/data/rushcheck/rdoc/classes/Float.html +191 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000047.html +21 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000048.html +18 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000049.html +22 -0
- data/data/rushcheck/rdoc/classes/Float.src/M000050.html +20 -0
- data/data/rushcheck/rdoc/classes/Gen.html +515 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000026.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000027.html +20 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000028.html +28 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000029.html +24 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000030.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000031.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000032.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000033.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000034.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000035.html +24 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000036.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000037.html +21 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000038.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000039.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000040.html +23 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000041.html +19 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000042.html +18 -0
- data/data/rushcheck/rdoc/classes/Gen.src/M000043.html +24 -0
- data/data/rushcheck/rdoc/classes/Guard.html +159 -0
- data/data/rushcheck/rdoc/classes/Guard.src/M000024.html +27 -0
- data/data/rushcheck/rdoc/classes/Guard.src/M000025.html +18 -0
- data/data/rushcheck/rdoc/classes/HsRandom.html +201 -0
- data/data/rushcheck/rdoc/classes/HsRandom.src/M000081.html +22 -0
- data/data/rushcheck/rdoc/classes/HsRandom.src/M000082.html +32 -0
- data/data/rushcheck/rdoc/classes/HsRandom.src/M000083.html +18 -0
- data/data/rushcheck/rdoc/classes/Integer.html +212 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000006.html +18 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000007.html +18 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000008.html +21 -0
- data/data/rushcheck/rdoc/classes/Integer.src/M000009.html +19 -0
- data/data/rushcheck/rdoc/classes/NilClass.html +177 -0
- data/data/rushcheck/rdoc/classes/NilClass.src/M000059.html +18 -0
- data/data/rushcheck/rdoc/classes/NilClass.src/M000060.html +18 -0
- data/data/rushcheck/rdoc/classes/NilClass.src/M000061.html +18 -0
- data/data/rushcheck/rdoc/classes/Property.html +174 -0
- data/data/rushcheck/rdoc/classes/Property.src/M000070.html +26 -0
- data/data/rushcheck/rdoc/classes/Property.src/M000071.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomArray.html +184 -0
- data/data/rushcheck/rdoc/classes/RandomArray.src/M000021.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomArray.src/M000022.html +35 -0
- data/data/rushcheck/rdoc/classes/RandomArray.src/M000023.html +22 -0
- data/data/rushcheck/rdoc/classes/RandomBool.html +146 -0
- data/data/rushcheck/rdoc/classes/RandomBool.src/M000079.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomBool.src/M000080.html +19 -0
- data/data/rushcheck/rdoc/classes/RandomGen.html +196 -0
- data/data/rushcheck/rdoc/classes/RandomGen.src/M000076.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomGen.src/M000077.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomGen.src/M000078.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomHash.html +197 -0
- data/data/rushcheck/rdoc/classes/RandomHash.src/M000044.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomHash.src/M000045.html +26 -0
- data/data/rushcheck/rdoc/classes/RandomHash.src/M000046.html +22 -0
- data/data/rushcheck/rdoc/classes/RandomProc.html +192 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000055.html +18 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000056.html +30 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000057.html +26 -0
- data/data/rushcheck/rdoc/classes/RandomProc.src/M000058.html +20 -0
- data/data/rushcheck/rdoc/classes/Result.html +214 -0
- data/data/rushcheck/rdoc/classes/Result.src/M000051.html +18 -0
- data/data/rushcheck/rdoc/classes/Result.src/M000052.html +18 -0
- data/data/rushcheck/rdoc/classes/Result.src/M000053.html +18 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.html +240 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000001.html +23 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000002.html +22 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000003.html +18 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000004.html +38 -0
- data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000005.html +55 -0
- data/data/rushcheck/rdoc/classes/RushCheckGuard.html +118 -0
- data/data/rushcheck/rdoc/classes/SpecialString.html +151 -0
- data/data/rushcheck/rdoc/classes/SpecialString.src/M000017.html +37 -0
- data/data/rushcheck/rdoc/classes/StdGen.html +252 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000010.html +23 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000011.html +21 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000012.html +21 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000013.html +18 -0
- data/data/rushcheck/rdoc/classes/StdGen.src/M000014.html +18 -0
- data/data/rushcheck/rdoc/classes/String.html +191 -0
- data/data/rushcheck/rdoc/classes/String.src/M000066.html +24 -0
- data/data/rushcheck/rdoc/classes/String.src/M000067.html +18 -0
- data/data/rushcheck/rdoc/classes/String.src/M000068.html +25 -0
- data/data/rushcheck/rdoc/classes/String.src/M000069.html +22 -0
- data/data/rushcheck/rdoc/classes/Testable.html +281 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000084.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000085.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000088.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000089.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000090.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000092.html +18 -0
- data/data/rushcheck/rdoc/classes/Testable.src/M000094.html +18 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.html +200 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000062.html +18 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000063.html +20 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000064.html +21 -0
- data/data/rushcheck/rdoc/classes/TheStdGen.src/M000065.html +18 -0
- data/data/rushcheck/rdoc/classes/TrueClass.html +177 -0
- data/data/rushcheck/rdoc/classes/TrueClass.src/M000072.html +18 -0
- data/data/rushcheck/rdoc/classes/TrueClass.src/M000073.html +18 -0
- data/data/rushcheck/rdoc/classes/TrueClass.src/M000074.html +18 -0
- data/data/rushcheck/rdoc/created.rid +1 -0
- data/data/rushcheck/rdoc/files/rushcheck/arbitrary_rb.html +114 -0
- data/data/rushcheck/rdoc/files/rushcheck/array_rb.html +117 -0
- data/data/rushcheck/rdoc/files/rushcheck/assertion_rb.html +120 -0
- data/data/rushcheck/rdoc/files/rushcheck/bool_rb.html +120 -0
- data/data/rushcheck/rdoc/files/rushcheck/config_rb.html +109 -0
- data/data/rushcheck/rdoc/files/rushcheck/float_rb.html +118 -0
- data/data/rushcheck/rdoc/files/rushcheck/gen_rb.html +111 -0
- data/data/rushcheck/rdoc/files/rushcheck/guard_rb.html +108 -0
- data/data/rushcheck/rdoc/files/rushcheck/hash_rb.html +117 -0
- data/data/rushcheck/rdoc/files/rushcheck/integer_rb.html +118 -0
- data/data/rushcheck/rdoc/files/rushcheck/proc_rb.html +118 -0
- data/data/rushcheck/rdoc/files/rushcheck/property_rb.html +119 -0
- data/data/rushcheck/rdoc/files/rushcheck/random_rb.html +126 -0
- data/data/rushcheck/rdoc/files/rushcheck/result_rb.html +118 -0
- data/data/rushcheck/rdoc/files/rushcheck/rushcheck_rb.html +123 -0
- data/data/rushcheck/rdoc/files/rushcheck/string_rb.html +121 -0
- data/data/rushcheck/rdoc/files/rushcheck/testable_rb.html +117 -0
- data/data/rushcheck/rdoc/fr_class_index.html +51 -0
- data/data/rushcheck/rdoc/fr_file_index.html +43 -0
- data/data/rushcheck/rdoc/fr_method_index.html +121 -0
- data/data/rushcheck/rdoc/index.html +24 -0
- data/data/rushcheck/rdoc/rdoc-style.css +208 -0
- data/lib/rushcheck/arbitrary.rb +28 -0
- data/lib/rushcheck/array.rb +49 -0
- data/lib/rushcheck/assertion.rb +67 -0
- data/lib/rushcheck/bool.rb +90 -0
- data/lib/rushcheck/config.rb +98 -0
- data/lib/rushcheck/float.rb +43 -0
- data/lib/rushcheck/gen.rb +189 -0
- data/lib/rushcheck/guard.rb +27 -0
- data/lib/rushcheck/hash.rb +45 -0
- data/lib/rushcheck/integer.rb +43 -0
- data/lib/rushcheck/proc.rb +53 -0
- data/lib/rushcheck/property.rb +29 -0
- data/lib/rushcheck/random.rb +215 -0
- data/lib/rushcheck/result.rb +26 -0
- data/lib/rushcheck/rushcheck.rb +17 -0
- data/lib/rushcheck/string.rb +100 -0
- data/lib/rushcheck/testable.rb +41 -0
- metadata +238 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
2006-07-26 start Daisuke IKEGAMI <ikegami@madscientist.jp>
|
|
2
|
+
2006-08-09 add
|
|
3
|
+
|
|
4
|
+
porting policy
|
|
5
|
+
--------------
|
|
6
|
+
|
|
7
|
+
In this document, I compare between the original Haskell
|
|
8
|
+
implementation in ghc and RushCheck.
|
|
9
|
+
|
|
10
|
+
1. Haskell98 System.Random
|
|
11
|
+
|
|
12
|
+
1.1 type, type classes and functions in System.Random
|
|
13
|
+
|
|
14
|
+
class RandomGen g where
|
|
15
|
+
next :: g -> (Int, g)
|
|
16
|
+
split :: g -> (g, g)
|
|
17
|
+
genRange :: g -> (Int, Int)
|
|
18
|
+
|
|
19
|
+
data StdGen = StdGen Int Int
|
|
20
|
+
instance RandomGen StdGen
|
|
21
|
+
instance Show StdGen
|
|
22
|
+
instance Read StdGen
|
|
23
|
+
|
|
24
|
+
mkStdGen :: Int -> StdGen
|
|
25
|
+
|
|
26
|
+
class Random a where
|
|
27
|
+
random :: RandomGen g => g -> (a, g)
|
|
28
|
+
randomR :: RandomGen g => (a, a) -> g -> (a, g)
|
|
29
|
+
randoms :: RandomGen g => g -> [a]
|
|
30
|
+
randomRs :: RandomGen g => (a, a) -> g -> [a]
|
|
31
|
+
randomIO :: IO a
|
|
32
|
+
randomRIO :: (a, a) -> IO a
|
|
33
|
+
instance Random Int
|
|
34
|
+
instance Random Char
|
|
35
|
+
instance Random Bool
|
|
36
|
+
instance Random Integer
|
|
37
|
+
instance Random Double
|
|
38
|
+
instance Random Float
|
|
39
|
+
|
|
40
|
+
getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
|
|
41
|
+
getStdGen :: IO StdGen
|
|
42
|
+
setStdGen :: StdGen -> IO ()
|
|
43
|
+
newStdGen :: IO StdGen
|
|
44
|
+
|
|
45
|
+
1.2 porting policy for System.Random in Haskell to Ruby
|
|
46
|
+
|
|
47
|
+
Haskell ruby
|
|
48
|
+
System.Random ---> rushcheck/random.rb
|
|
49
|
+
|
|
50
|
+
Haskell ruby
|
|
51
|
+
class RandomGen ---> module RandomGen
|
|
52
|
+
for instance methods
|
|
53
|
+
|
|
54
|
+
'method RandomGen' is assumed to be included for making instance
|
|
55
|
+
methods.
|
|
56
|
+
|
|
57
|
+
Haskell
|
|
58
|
+
next :: g -> (Int, g)
|
|
59
|
+
split :: g -> (g, g)
|
|
60
|
+
genRange :: g -> (Int, Int)
|
|
61
|
+
--->
|
|
62
|
+
Ruby
|
|
63
|
+
RandomGen#gen_next :: [Fixnum, SELF]
|
|
64
|
+
RandomGen#split :: [SELF, SELF]
|
|
65
|
+
RandomGen#gen_range :: [Fixnum, Int]
|
|
66
|
+
|
|
67
|
+
- because 'next' is a reserved word of ruby, change it to 'gen_next'.
|
|
68
|
+
- SELF is the class which includes the module RandomGen.
|
|
69
|
+
- Haskell's Int is similar to Ruby's Fixnum
|
|
70
|
+
|
|
71
|
+
Haskell
|
|
72
|
+
data StdGen = StdGen Int Int
|
|
73
|
+
instance RandomGen StdGen
|
|
74
|
+
instance Show StdGen
|
|
75
|
+
instance Read StdGen
|
|
76
|
+
mkStdGen :: Int -> StdGen
|
|
77
|
+
--->
|
|
78
|
+
Ruby
|
|
79
|
+
class StdGen
|
|
80
|
+
StdGen#initialize(left::Fixnum=nil, right::Fixnum = nil)
|
|
81
|
+
StdGen includes module RandomGen
|
|
82
|
+
StdGen#to_s
|
|
83
|
+
|
|
84
|
+
- read is not implemented yet (maybe unnecessary?)
|
|
85
|
+
- StdGen requires two integers in default, but we can also create
|
|
86
|
+
StdGen with only one integer by mkStdGen. Therefore,
|
|
87
|
+
StdGen#initialize takes one/two integers. In addition, we can make
|
|
88
|
+
StdGen without any integers but they are generated randomly.
|
|
89
|
+
|
|
90
|
+
Haskell
|
|
91
|
+
class Random a where
|
|
92
|
+
random :: RandomGen g => g -> (a, g)
|
|
93
|
+
randomR :: RandomGen g => (a, a) -> g -> (a, g)
|
|
94
|
+
randoms :: RandomGen g => g -> [a]
|
|
95
|
+
randomRs :: RandomGen g => (a, a) -> g -> [a]
|
|
96
|
+
randomIO :: IO a
|
|
97
|
+
randomRIO :: (a, a) -> IO a
|
|
98
|
+
--->
|
|
99
|
+
Ruby
|
|
100
|
+
module HsRandom
|
|
101
|
+
HsRandom#random
|
|
102
|
+
(gen::RandomGen, lo::HsRandom=nil, hi::HsRandom=nil)
|
|
103
|
+
:: [HsRandom, RandomGen]
|
|
104
|
+
HsRandom#random_array
|
|
105
|
+
(gen::RandomGen, len::Integer=nil,
|
|
106
|
+
lo::HsRandom=nil, hi::HsRandom=nil)
|
|
107
|
+
:: [HsRandom, RandomGen]
|
|
108
|
+
HsRandom#random_std(lo::HsRandom=nil, hi::HsRandom=nil)
|
|
109
|
+
private
|
|
110
|
+
HsRandom#random_range
|
|
111
|
+
(gen::RandomGen, lo::HsRandom=nil, hi::HsRandom=nil)
|
|
112
|
+
:: [HsRandom, RandomGen]
|
|
113
|
+
|
|
114
|
+
Haskell
|
|
115
|
+
instance Random Int
|
|
116
|
+
instance Random Integer
|
|
117
|
+
--->
|
|
118
|
+
Ruby
|
|
119
|
+
class Integer includes the module HsRandom
|
|
120
|
+
why not Fixnum and Bignum?
|
|
121
|
+
|
|
122
|
+
Haskell
|
|
123
|
+
instance Random Char
|
|
124
|
+
-->
|
|
125
|
+
Ruby
|
|
126
|
+
class String includes the module HsRandom
|
|
127
|
+
|
|
128
|
+
Haskell
|
|
129
|
+
instance Random Double
|
|
130
|
+
instance Random Float
|
|
131
|
+
-->
|
|
132
|
+
Ruby
|
|
133
|
+
class Float includes the module HsRandom
|
|
134
|
+
|
|
135
|
+
Haskell
|
|
136
|
+
instance Random Bool
|
|
137
|
+
-->
|
|
138
|
+
Ruby
|
|
139
|
+
nop
|
|
140
|
+
why not TrueClass and FalseClass?
|
|
141
|
+
but what is the randomness of TrueClass?
|
|
142
|
+
|
|
143
|
+
Haskell
|
|
144
|
+
getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
|
|
145
|
+
-->
|
|
146
|
+
Ruby
|
|
147
|
+
nop
|
|
148
|
+
|
|
149
|
+
Haskell
|
|
150
|
+
newStdGen :: IO StdGen
|
|
151
|
+
setStdGen :: StdGen -> IO ()
|
|
152
|
+
getStdGen :: IO StdGen
|
|
153
|
+
-->
|
|
154
|
+
Ruby
|
|
155
|
+
class TheStdGen (singleton class)
|
|
156
|
+
|
|
157
|
+
2.1 Test.QuickCheck
|
|
158
|
+
|
|
159
|
+
quickCheck :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
160
|
+
verboseCheck :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
161
|
+
test :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
162
|
+
|
|
163
|
+
Config(..) -- :: *
|
|
164
|
+
data Config = Config
|
|
165
|
+
{ configMaxTest :: Int
|
|
166
|
+
, configMaxFail :: Int
|
|
167
|
+
, configSize :: Int -> Int
|
|
168
|
+
, configEvery :: Int -> [String] -> String
|
|
169
|
+
}
|
|
170
|
+
defaultConfig :: Config
|
|
171
|
+
check :: Testable a => Config -> a -> IO ()
|
|
172
|
+
-- :: Config -> prop -> IO ()
|
|
173
|
+
|
|
174
|
+
-- property combinators
|
|
175
|
+
forAll :: (Show a, Testable b) => Gen a -> (a -> b) ->
|
|
176
|
+
Property
|
|
177
|
+
-- :: Gen a -> (a -> prop) -> prop
|
|
178
|
+
(==>) :: Testable a => Bool -> a -> Property
|
|
179
|
+
-- :: Bool -> prop -> prop
|
|
180
|
+
|
|
181
|
+
-- gathering test-case information
|
|
182
|
+
label :: Testable a => String -> a -> Property
|
|
183
|
+
-- :: String -> prop -> prop
|
|
184
|
+
collect :: (Show a, Testable b) => a -> b -> Property
|
|
185
|
+
-- :: Show a => a -> prop -> prop
|
|
186
|
+
classify :: Testable a => Bool -> String -> a -> Property
|
|
187
|
+
-- :: Bool -> String -> prop -> prop
|
|
188
|
+
trivial :: Testable a => Bool -> a -> Property
|
|
189
|
+
-- :: Bool -> prop -> prop
|
|
190
|
+
|
|
191
|
+
-- generator combinators
|
|
192
|
+
Gen -- :: * -> * ; Functor, Monad
|
|
193
|
+
newtype Gen a
|
|
194
|
+
= Gen (Int -> StdGen -> a)
|
|
195
|
+
|
|
196
|
+
elements :: [a] -> Gen a
|
|
197
|
+
two :: Gen a -> Gen (a,a)
|
|
198
|
+
three :: Gen a -> Gen (a,a,a)
|
|
199
|
+
four :: Gen a -> Gen (a,a,a,a)
|
|
200
|
+
|
|
201
|
+
sized :: (Int -> Gen a) -> Gen a
|
|
202
|
+
resize :: Int -> Gen a -> Gen a
|
|
203
|
+
choose :: Random a => (a, a) -> Gen a
|
|
204
|
+
oneof :: [Gen a] -> Gen a
|
|
205
|
+
frequency :: [(Int, Gen a)] -> Gen a
|
|
206
|
+
|
|
207
|
+
vector :: Arbitrary a => Int -> Gen [a]
|
|
208
|
+
|
|
209
|
+
-- default generators
|
|
210
|
+
Arbitrary(..) -- :: class
|
|
211
|
+
class Arbitrary a where
|
|
212
|
+
arbitrary :: Gen a
|
|
213
|
+
coarbitrary :: a -> Gen b -> Gen b
|
|
214
|
+
rand :: Gen StdGen
|
|
215
|
+
promote :: (a -> Gen b) -> Gen (a -> b)
|
|
216
|
+
variant :: Int -> Gen a -> Gen a
|
|
217
|
+
|
|
218
|
+
-- testable
|
|
219
|
+
Testable(..) -- :: class
|
|
220
|
+
class Testable a where
|
|
221
|
+
property :: a -> Property
|
|
222
|
+
Property -- :: *
|
|
223
|
+
newtype Property
|
|
224
|
+
= Prop (Gen Result)
|
|
225
|
+
|
|
226
|
+
-- For writing your own driver
|
|
227
|
+
Result(..) -- :: data
|
|
228
|
+
data Result
|
|
229
|
+
= Result { ok :: Maybe Bool,
|
|
230
|
+
stamp :: [String],
|
|
231
|
+
arguments :: [String] }
|
|
232
|
+
generate :: Int -> StdGen -> Gen a -> a
|
|
233
|
+
evaluate :: Testable a => a -> Gen Result
|
|
234
|
+
|
|
235
|
+
2.2 porting policy for QuickCheck in Haskell to Ruby
|
|
236
|
+
|
|
237
|
+
Because Test.QuickCheck is not small, I decide to divide
|
|
238
|
+
implementation into several files.
|
|
239
|
+
|
|
240
|
+
= testable.rb
|
|
241
|
+
quickCheck :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
242
|
+
verboseCheck :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
243
|
+
test :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
244
|
+
check :: Testable a => Config -> a -> IO ()
|
|
245
|
+
-- :: Config -> prop -> IO ()
|
|
246
|
+
(==>) :: Testable a => Bool -> a -> Property
|
|
247
|
+
-- :: Bool -> prop -> prop
|
|
248
|
+
-- gathering test-case information
|
|
249
|
+
label :: Testable a => String -> a -> Property
|
|
250
|
+
-- :: String -> prop -> prop
|
|
251
|
+
collect :: (Show a, Testable b) => a -> b -> Property
|
|
252
|
+
-- :: Show a => a -> prop -> prop
|
|
253
|
+
classify :: Testable a => Bool -> String -> a -> Property
|
|
254
|
+
-- :: Bool -> String -> prop -> prop
|
|
255
|
+
trivial :: Testable a => Bool -> a -> Property
|
|
256
|
+
-- :: Bool -> prop -> prop
|
|
257
|
+
-- testable
|
|
258
|
+
Testable(..) -- :: class
|
|
259
|
+
class Testable a where
|
|
260
|
+
property :: a -> Property
|
|
261
|
+
|
|
262
|
+
evaluate :: Testable a => a -> Gen Result
|
|
263
|
+
|
|
264
|
+
= config.rb
|
|
265
|
+
Config(..) -- :: *
|
|
266
|
+
data Config = Config
|
|
267
|
+
{ configMaxTest :: Int
|
|
268
|
+
, configMaxFail :: Int
|
|
269
|
+
, configSize :: Int -> Int
|
|
270
|
+
, configEvery :: Int -> [String] -> String
|
|
271
|
+
}
|
|
272
|
+
defaultConfig :: Config
|
|
273
|
+
|
|
274
|
+
= gen.rb
|
|
275
|
+
-- property combinators
|
|
276
|
+
forAll :: (Show a, Testable b) => Gen a -> (a -> b) ->
|
|
277
|
+
Property
|
|
278
|
+
-- :: Gen a -> (a -> prop) -> prop
|
|
279
|
+
-- generator combinators
|
|
280
|
+
Gen -- :: * -> * ; Functor, Monad
|
|
281
|
+
newtype Gen a
|
|
282
|
+
= Gen (Int -> StdGen -> a)
|
|
283
|
+
elements :: [a] -> Gen a
|
|
284
|
+
two :: Gen a -> Gen (a,a)
|
|
285
|
+
three :: Gen a -> Gen (a,a,a)
|
|
286
|
+
four :: Gen a -> Gen (a,a,a,a)
|
|
287
|
+
|
|
288
|
+
sized :: (Int -> Gen a) -> Gen a
|
|
289
|
+
resize :: Int -> Gen a -> Gen a
|
|
290
|
+
choose :: Random a => (a, a) -> Gen a
|
|
291
|
+
oneof :: [Gen a] -> Gen a
|
|
292
|
+
frequency :: [(Int, Gen a)] -> Gen a
|
|
293
|
+
|
|
294
|
+
vector :: Arbitrary a => Int -> Gen [a]
|
|
295
|
+
|
|
296
|
+
rand :: Gen StdGen
|
|
297
|
+
promote :: (a -> Gen b) -> Gen (a -> b)
|
|
298
|
+
variant :: Int -> Gen a -> Gen a
|
|
299
|
+
|
|
300
|
+
generate :: Int -> StdGen -> Gen a -> a
|
|
301
|
+
|
|
302
|
+
= arbitrary.rb
|
|
303
|
+
Arbitrary(..) -- :: class
|
|
304
|
+
class Arbitrary a where
|
|
305
|
+
arbitrary :: Gen a
|
|
306
|
+
coarbitrary :: a -> Gen b -> Gen b
|
|
307
|
+
|
|
308
|
+
= property.rb
|
|
309
|
+
Property -- :: *
|
|
310
|
+
newtype Property
|
|
311
|
+
= Prop (Gen Result)
|
|
312
|
+
|
|
313
|
+
= result.rb
|
|
314
|
+
Result(..) -- :: data
|
|
315
|
+
data Result
|
|
316
|
+
= Result { ok :: Maybe Bool,
|
|
317
|
+
stamp :: [String],
|
|
318
|
+
arguments :: [String] }
|
|
319
|
+
|
|
320
|
+
2.2.1 testable.rb
|
|
321
|
+
|
|
322
|
+
-- testable
|
|
323
|
+
Testable(..) -- :: class
|
|
324
|
+
class Testable a where
|
|
325
|
+
property :: a -> Property
|
|
326
|
+
type class Testable is translated into a module Testable.
|
|
327
|
+
|
|
328
|
+
Haskell
|
|
329
|
+
quickCheck :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
330
|
+
verboseCheck :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
331
|
+
test :: Testable a => a -> IO () -- :: prop -> IO ()
|
|
332
|
+
check :: Testable a => Config -> a -> IO ()
|
|
333
|
+
-- :: Config -> prop -> IO ()
|
|
334
|
+
--->
|
|
335
|
+
Ruby
|
|
336
|
+
Testable#quick_check :: [nil, [TrueClass, FalseClass]]
|
|
337
|
+
Testable#verbose_check :: [nil, [TrueClass, FalseClass]]
|
|
338
|
+
Testable#test :: [nil, [TrueClass, FalseClass]]
|
|
339
|
+
Testable#check :: [Config, [TrueClass, FalseClass]]
|
|
340
|
+
|
|
341
|
+
For using checking functions with unit testing framework, they
|
|
342
|
+
should return the result as a boolean value.
|
|
343
|
+
|
|
344
|
+
Haskell
|
|
345
|
+
(==>) :: Testable a => Bool -> a -> Property
|
|
346
|
+
-- :: Bool -> prop -> prop
|
|
347
|
+
--->
|
|
348
|
+
Ruby
|
|
349
|
+
Testable#imply :: []
|
|
350
|
+
method imply takes a block for the boolean property.
|
|
351
|
+
|
|
352
|
+
Haskell
|
|
353
|
+
-- gathering test-case information
|
|
354
|
+
label :: Testable a => String -> a -> Property
|
|
355
|
+
-- :: String -> prop -> prop
|
|
356
|
+
collect :: (Show a, Testable b) => a -> b -> Property
|
|
357
|
+
-- :: Show a => a -> prop -> prop
|
|
358
|
+
classify :: Testable a => Bool -> String -> a -> Property
|
|
359
|
+
-- :: Bool -> String -> prop -> prop
|
|
360
|
+
trivial :: Testable a => Bool -> a -> Property
|
|
361
|
+
-- :: Bool -> prop -> prop
|
|
362
|
+
--->
|
|
363
|
+
Ruby
|
|
364
|
+
Testable#label :: [Object, Property]
|
|
365
|
+
alias Testable#collect
|
|
366
|
+
Testable#classify :: [Object, Property] # Object -> String
|
|
367
|
+
Testable#trivial :: [nil, Property]
|
|
368
|
+
|
|
369
|
+
In ruby, label and collect can be regarded as same with 'to_s'.
|
|
370
|
+
classify and trivial take a block for boolean condition.
|
|
371
|
+
classify calls label internally.
|
|
372
|
+
|
|
373
|
+
Haskell
|
|
374
|
+
evaluate :: Testable a => a -> Gen Result
|
|
375
|
+
where property :: Testable a => a -> Property
|
|
376
|
+
Property = Prop (Gen Result)
|
|
377
|
+
--->
|
|
378
|
+
Ruby
|
|
379
|
+
nop
|
|
380
|
+
Because the name evaluate is similar to eval in Ruby, I decide to
|
|
381
|
+
not implement evaluate. evaluate is almost same to property.
|
|
382
|
+
|
|
383
|
+
2.2.2 config.rb
|
|
384
|
+
|
|
385
|
+
Haskell
|
|
386
|
+
Config(..) -- :: *
|
|
387
|
+
data Config = Config
|
|
388
|
+
{ configMaxTest :: Int
|
|
389
|
+
, configMaxFail :: Int
|
|
390
|
+
, configSize :: Int -> Int
|
|
391
|
+
, configEvery :: Int -> [String] -> String
|
|
392
|
+
}
|
|
393
|
+
defaultConfig :: Config
|
|
394
|
+
--->
|
|
395
|
+
Ruby
|
|
396
|
+
class Config
|
|
397
|
+
Config#initialize :: [[Integer, Integer, Proc, Proc], ...]
|
|
398
|
+
|
|
399
|
+
There is two ways to implement a method with functions.
|
|
400
|
+
Because the initialize takes two functions, I choose to implement
|
|
401
|
+
them as Proc objects and as not block (it is confused to use both
|
|
402
|
+
Proc and block)
|
|
403
|
+
|
|
404
|
+
2.2.3 gen.rb
|
|
405
|
+
|
|
406
|
+
gen.rb is not a small file to implement almost all of features in
|
|
407
|
+
QuickCheck.
|
|
408
|
+
|
|
409
|
+
Haskell
|
|
410
|
+
-- generator combinators
|
|
411
|
+
Gen -- :: * -> * ; Functor, Monad
|
|
412
|
+
newtype Gen a
|
|
413
|
+
= Gen (Int -> StdGen -> a)
|
|
414
|
+
--->
|
|
415
|
+
Ruby
|
|
416
|
+
class Gen
|
|
417
|
+
Gen#initialize [nil, ...]
|
|
418
|
+
initialize takes a block {|n, r| } where n is an integer and r is a
|
|
419
|
+
random generator.
|
|
420
|
+
|
|
421
|
+
Haskell
|
|
422
|
+
-- property combinators
|
|
423
|
+
forAll :: (Show a, Testable b) => Gen a -> (a -> b) ->
|
|
424
|
+
Property
|
|
425
|
+
-- :: Gen a -> (a -> prop) -> prop
|
|
426
|
+
--->
|
|
427
|
+
Ruby
|
|
428
|
+
Gen#forall :: [nil, Property]
|
|
429
|
+
forall takes a block.
|
|
430
|
+
|
|
431
|
+
Haskell
|
|
432
|
+
elements :: [a] -> Gen a
|
|
433
|
+
--->
|
|
434
|
+
Ruby
|
|
435
|
+
Gen.elements :: [[Object], Gen]
|
|
436
|
+
|
|
437
|
+
Haskell
|
|
438
|
+
two :: Gen a -> Gen (a,a)
|
|
439
|
+
three :: Gen a -> Gen (a,a,a)
|
|
440
|
+
four :: Gen a -> Gen (a,a,a,a)
|
|
441
|
+
--->
|
|
442
|
+
Ruby
|
|
443
|
+
nop
|
|
444
|
+
Because Ruby does not have tuple (but has Array). I wonder whether
|
|
445
|
+
the monadic functions two, three and four in Ruby. So I deferred to
|
|
446
|
+
implement them until I need them.
|
|
447
|
+
|
|
448
|
+
Haskell
|
|
449
|
+
sized :: (Int -> Gen a) -> Gen a
|
|
450
|
+
resize :: Int -> Gen a -> Gen a
|
|
451
|
+
choose :: Random a => (a, a) -> Gen a
|
|
452
|
+
oneof :: [Gen a] -> Gen a
|
|
453
|
+
frequency :: [(Int, Gen a)] -> Gen a
|
|
454
|
+
vector :: Arbitrary a => Int -> Gen [a]
|
|
455
|
+
rand :: Gen StdGen
|
|
456
|
+
promote :: (a -> Gen b) -> Gen (a -> b)
|
|
457
|
+
variant :: Int -> Gen a -> Gen a
|
|
458
|
+
generate :: Int -> StdGen -> Gen a -> a
|
|
459
|
+
--->
|
|
460
|
+
Ruby
|
|
461
|
+
Gen#sized :: [nil, Gen], takes a block
|
|
462
|
+
Gen#resize :: [Integer, Gen]
|
|
463
|
+
|
|
464
|
+
Gen.choose :: [[lo::?, hi::?], Gen]
|
|
465
|
+
where lo and hi belongs Random
|
|
466
|
+
Gen.oneof :: [[Gen], Gen]
|
|
467
|
+
Gen.frequency :: [[Integer, Gen], Gen]
|
|
468
|
+
Gen.vector :: [Integer, Gen]
|
|
469
|
+
Gen.rand :: [nil, Gen]
|
|
470
|
+
Gen.promote :: [nil, Gen], takes a block
|
|
471
|
+
|
|
472
|
+
Gen#variant :: [Integer, Gen]
|
|
473
|
+
Gen#generate :: [[Integer, StdGen], ?]
|
|
474
|
+
|
|
475
|
+
2.2.3 arbitrary.rb
|
|
476
|
+
|
|
477
|
+
Haskell
|
|
478
|
+
Arbitrary(..) -- :: class
|
|
479
|
+
class Arbitrary a where
|
|
480
|
+
arbitrary :: Gen a
|
|
481
|
+
coarbitrary :: a -> Gen b -> Gen b
|
|
482
|
+
--->
|
|
483
|
+
Ruby
|
|
484
|
+
module Arbitrary
|
|
485
|
+
module Coarbitrary
|
|
486
|
+
|
|
487
|
+
Because arbitrary should be implemented as a class method, while
|
|
488
|
+
coarbitrary as a instance method, they are included in different
|
|
489
|
+
modules.
|
|
490
|
+
|
|
491
|
+
2.2.4 property.rb
|
|
492
|
+
|
|
493
|
+
Haskell
|
|
494
|
+
Property -- :: *
|
|
495
|
+
newtype Property
|
|
496
|
+
= Prop (Gen Result)
|
|
497
|
+
--->
|
|
498
|
+
Ruby
|
|
499
|
+
class Property
|
|
500
|
+
|
|
501
|
+
There are several ways to implement Property in Ruby:
|
|
502
|
+
- as a class independently <-- I choose
|
|
503
|
+
- as a subclass of Gen
|
|
504
|
+
|
|
505
|
+
At first implementation (experimentally), I tried to write Property
|
|
506
|
+
as a subclass of Gen. However, initialization is different and debug
|
|
507
|
+
is imprecated.
|
|
508
|
+
|
|
509
|
+
2.2.5 result.rb
|
|
510
|
+
|
|
511
|
+
Haskell
|
|
512
|
+
Result(..) -- :: data
|
|
513
|
+
data Result
|
|
514
|
+
= Result { ok :: Maybe Bool,
|
|
515
|
+
stamp :: [String],
|
|
516
|
+
arguments :: [String] }
|
|
517
|
+
--->
|
|
518
|
+
Ruby
|
|
519
|
+
class Result
|
|
520
|
+
attr_reader :ok, :stamp, :arguments
|