rantly 0.3.1 → 0.3.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.
- checksums.yaml +7 -0
- data/.travis.yml +8 -0
- data/Gemfile +5 -2
- data/README.textile +89 -16
- data/Rakefile +4 -19
- data/VERSION.yml +3 -3
- data/lib/rantly/generator.rb +9 -13
- data/lib/rantly/minitest.rb +1 -0
- data/lib/rantly/minitest_extensions.rb +14 -0
- data/lib/rantly/property.rb +51 -29
- data/lib/rantly/rspec.rb +1 -0
- data/lib/rantly/rspec_extensions.rb +8 -0
- data/lib/rantly/shrinks.rb +77 -0
- data/lib/rantly/silly.rb +2 -4
- data/lib/rantly/testunit_extensions.rb +8 -0
- data/rantly.gemspec +47 -32
- data/test/rantly_test.rb +53 -48
- data/test/shrinks_test.rb +108 -0
- data/test/test_helper.rb +11 -4
- metadata +65 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8db5bd7182d7f9e17c430588587617eaa712dd6d
|
4
|
+
data.tar.gz: 5812264178d1640909ba3ea004b777ecea8e78e6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 36ffb950c9e4f23e5a7e02183bf7a4e7de2c35eac5431ffb4adb96266289097133c44ee7de1dd56db18a6553f45e36b580de1f4c91b9f1ad413adfae6b9a3744
|
7
|
+
data.tar.gz: b04342e87f28f5ef185ee6798bb8e7a119444c27d4b1fb0146cccd3e43ca13654fba3925ecc7914501b3336ead47055fa147d74f83874fb26b236a2522474f14
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.textile
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
!https://travis-ci.org/hayeah/rantly.png?branch=master!:https://travis-ci.org/hayeah/rantly
|
2
|
+
|
3
|
+
h1. Repository move (Beginning 2015-07-07)
|
4
|
+
|
5
|
+
The official _rantly_ repository has moved from "hayeah/rantly":https://github.com/hayeah/rantly to "abargnesi/rantly":https://github.com/abargnesi/rantly. The creator of _rantly_ is "Howard Yeh":https://github.com/hayeah. "Anthony Bargnesi":https://github.com/abargnesi is the current maintainer.
|
6
|
+
|
7
|
+
New development will occur in "abargnesi/rantly":https://github.com/abargnesi/rantly.
|
8
|
+
|
9
|
+
The transition plan is as follows:
|
10
|
+
|
11
|
+
* [x] Investigate and move open issues from "hayeah/rantly":https://github.com/hayeah/rantly to "abargnesi/rantly":https://github.com/abargnesi/rantly.
|
12
|
+
* [x] Evaluate and likely merge pull requests into hayeah/rantly. Push these changes to "abargnesi/rantly":https://github.com/abargnesi/rantly.
|
13
|
+
* [x] Move over any closed issues that have relevant discourse.
|
14
|
+
* [ ] Fix open issues.
|
15
|
+
* [x] Push new gem version after testing functionality.
|
16
|
+
* [ ] Continue new development; Changes will be pushed back upstream to "hayeah/rantly":https://github.com/hayeah/rantly over the course of the next month.
|
17
|
+
* [x] Added CHANGELOG markdown file. Includes what was added between 0.3.1 (2011-12-15) and 0.3.2 (2015-09-16).
|
18
|
+
|
1
19
|
h1. Imperative Random Data Generator and Quickcheck
|
2
20
|
|
3
21
|
You can use Rant to generate random test data, and use its Test::Unit extension for property-based testing.
|
@@ -19,7 +37,7 @@ $ irb -rrantly
|
|
19
37
|
> Rantly { [integer,float]}
|
20
38
|
=> [-376856492, 0.452245765751706]
|
21
39
|
> Rantly(5) { integer } # same as Rantly.map(5) { integer }
|
22
|
-
=> [-1843396915550491870, -1683855015308353854, -2291347782549033959, -951461511269053584, 483265231542292652]
|
40
|
+
=> [-1843396915550491870, -1683855015308353854, -2291347782549033959, -951461511269053584, 483265231542292652]
|
23
41
|
</code></pre>
|
24
42
|
|
25
43
|
h1. Data Generation
|
@@ -91,7 +109,7 @@ Rantly#range(lo,hi)
|
|
91
109
|
random integer between lo and hi.
|
92
110
|
Rantly#float
|
93
111
|
random float
|
94
|
-
Rantly#
|
112
|
+
Rantly#boolean
|
95
113
|
true or false
|
96
114
|
Rantly#literal(value)
|
97
115
|
No-op. returns value.
|
@@ -252,41 +270,96 @@ Rantly::TooManyTries: Exceed gen limit 60: 60 failed guards)
|
|
252
270
|
|
253
271
|
h1. Property Testing
|
254
272
|
|
255
|
-
Rantly extends Test::Unit for property testing. The
|
273
|
+
Rantly extends Test::Unit and MiniTest::Test (5.0)/MiniTest::Unit::TestCase (< 5.0) for property testing. The extensions are in their own modules. So you need to require them explicitly:
|
256
274
|
|
257
275
|
<pre><code>
|
258
|
-
require '
|
276
|
+
require 'rantly/testunit_extensions' # for 'test/unit'
|
277
|
+
require 'rantly/minitest_extensions' # for 'minitest'
|
278
|
+
require 'rantly/rspec_extensions' # for RSpec
|
259
279
|
</code></pre>
|
260
280
|
|
261
|
-
|
281
|
+
They define:
|
262
282
|
|
263
283
|
<pre><code>
|
264
284
|
Test::Unit::Assertions#property_of(&block)
|
265
285
|
The block is used to generate random data with a generator. The method returns a Rantly::Property instance, that has the method 'check'.
|
266
286
|
</code></pre>
|
267
287
|
|
268
|
-
|
288
|
+
Property assertions within Test::Unit could be done like this,
|
289
|
+
|
290
|
+
<pre><code>
|
291
|
+
# checks that integer only generates fixnum.
|
292
|
+
property_of {
|
293
|
+
integer
|
294
|
+
}.check { |i|
|
295
|
+
assert(i.is_a?(Integer), "integer property did not return Integer type")
|
296
|
+
}
|
297
|
+
</code></pre>
|
298
|
+
|
299
|
+
Property assertions within Minitest could be done like this,
|
300
|
+
|
301
|
+
<pre><code>
|
302
|
+
# checks that integer only generates fixnum.
|
303
|
+
property_of {
|
304
|
+
integer
|
305
|
+
}.check { |i|
|
306
|
+
assert_kind_of Integer, i, "integer property did not return Integer type"
|
307
|
+
}
|
308
|
+
</code></pre>
|
309
|
+
|
310
|
+
Property assertions within RSpec could be done like this,
|
269
311
|
|
270
312
|
<pre><code>
|
271
313
|
# checks that integer only generates fixnum.
|
272
|
-
|
273
|
-
property_of
|
314
|
+
it "integer property only returns Integer type" do
|
315
|
+
property_of {
|
316
|
+
integer
|
317
|
+
}.check { |i|
|
318
|
+
expect(i).to be_a(Integer)
|
319
|
+
}
|
274
320
|
end
|
275
321
|
</code></pre>
|
276
322
|
|
277
323
|
The check block takes the generated data as its argument. One idiom I find useful is to include a parameter of the random data for the check argument. For example, if I want to check that Rantly#array generates the right sized array, I could say,
|
278
324
|
|
279
325
|
<pre><code>
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
326
|
+
property_of {
|
327
|
+
len = integer
|
328
|
+
[len,array(len){integer}]
|
329
|
+
}.check { |(len,arr)|
|
330
|
+
assert_equal len, arr.length
|
331
|
+
}
|
332
|
+
</code></pre>
|
333
|
+
|
334
|
+
If you wish to have quiet output from Rantly, set environmental variable:
|
335
|
+
<pre><code>
|
336
|
+
RANTLY_VERBOSE=0 # silent
|
337
|
+
RANTLY_VERBOSE=1 # verbose and default if env is not set
|
338
|
+
</code></pre>
|
339
|
+
This will silence the puts, print, and pretty_print statements in property.rb.
|
340
|
+
|
341
|
+
h1. Shrinking
|
342
|
+
|
343
|
+
Shrinking reduces the value of common types to some terminal lower bound. These functions are added to the Ruby types <code>Integer</code>, <code>String</code>, <code>Array</code>, and <code>Hash</code>.
|
344
|
+
|
345
|
+
For example a <code>String</code> is shrinkable until it is empty (e.g. <code>""</code>),
|
346
|
+
|
347
|
+
<pre><code>
|
348
|
+
"foo".shrink # => "fo"
|
349
|
+
"foo".shrink.shrink # => "f"
|
350
|
+
"foo".shrink.shrink.shrink # => ""
|
351
|
+
"".shrinkable? # => false
|
352
|
+
</code></pre>
|
353
|
+
|
354
|
+
Shrinking allows <code>Property#check</code> to find the minimum value that still fails the condition.
|
355
|
+
|
356
|
+
Enable shrinking with
|
357
|
+
|
358
|
+
<pre><code>
|
359
|
+
require 'rantly/shrinks'
|
288
360
|
</code></pre>
|
289
361
|
|
362
|
+
|
290
363
|
That's about it. Enjoy :)
|
291
364
|
|
292
365
|
|
data/Rakefile
CHANGED
@@ -6,9 +6,9 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "rantly"
|
8
8
|
gem.summary = %Q{Ruby Imperative Random Data Generator and Quickcheck}
|
9
|
-
gem.email = "hayeah@gmail.com"
|
10
|
-
gem.homepage = "
|
11
|
-
gem.authors = ["Howard Yeh"]
|
9
|
+
gem.email = ["hayeah@gmail.com", "abargnesi@gmail.com"]
|
10
|
+
gem.homepage = "https://github.com/abargnesi/rantly"
|
11
|
+
gem.authors = ["Howard Yeh", "Anthony Bargnesi"]
|
12
12
|
|
13
13
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
14
|
end
|
@@ -23,23 +23,9 @@ Rake::TestTask.new(:test) do |test|
|
|
23
23
|
test.verbose = true
|
24
24
|
end
|
25
25
|
|
26
|
-
begin
|
27
|
-
require 'rcov/rcovtask'
|
28
|
-
Rcov::RcovTask.new do |test|
|
29
|
-
test.libs << 'test'
|
30
|
-
test.pattern = 'test/**/*_test.rb'
|
31
|
-
test.verbose = true
|
32
|
-
end
|
33
|
-
rescue LoadError
|
34
|
-
task :rcov do
|
35
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
26
|
task :default => :test
|
41
27
|
|
42
|
-
require '
|
28
|
+
require 'rdoc/task'
|
43
29
|
Rake::RDocTask.new do |rdoc|
|
44
30
|
require 'yaml'
|
45
31
|
if File.exist?('VERSION.yml')
|
@@ -54,4 +40,3 @@ Rake::RDocTask.new do |rdoc|
|
|
54
40
|
rdoc.rdoc_files.include('README*')
|
55
41
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
42
|
end
|
57
|
-
|
data/VERSION.yml
CHANGED
data/lib/rantly/generator.rb
CHANGED
@@ -22,7 +22,7 @@ class Rantly
|
|
22
22
|
def value(limit=10,&block)
|
23
23
|
gen.value(limit,&block)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def gen
|
27
27
|
self.singleton
|
28
28
|
end
|
@@ -32,7 +32,6 @@ class Rantly
|
|
32
32
|
end
|
33
33
|
|
34
34
|
class TooManyTries < RuntimeError
|
35
|
-
|
36
35
|
def initialize(limit,nfailed)
|
37
36
|
@limit = limit
|
38
37
|
@nfailed = nfailed
|
@@ -84,7 +83,7 @@ class Rantly
|
|
84
83
|
handler.call(val) if handler
|
85
84
|
end
|
86
85
|
end
|
87
|
-
|
86
|
+
|
88
87
|
attr_accessor :classifiers
|
89
88
|
|
90
89
|
def initialize
|
@@ -111,7 +110,7 @@ class Rantly
|
|
111
110
|
def size
|
112
111
|
@size || Rantly.default_size
|
113
112
|
end
|
114
|
-
|
113
|
+
|
115
114
|
def sized(n,&block)
|
116
115
|
raise "size needs to be greater than zero" if n < 0
|
117
116
|
old_size = @size
|
@@ -222,18 +221,15 @@ class Rantly
|
|
222
221
|
end
|
223
222
|
|
224
223
|
module Chars
|
225
|
-
|
224
|
+
|
226
225
|
class << self
|
227
|
-
ASCII = ""
|
228
|
-
(0..127).to_a.each do |i|
|
229
|
-
ASCII << i
|
230
|
-
end
|
226
|
+
ASCII = (0..127).to_a.each_with_object("") { |i, obj| obj << i }
|
231
227
|
|
232
228
|
def of(regexp)
|
233
229
|
ASCII.scan(regexp).to_a.map! { |char| char[0].ord }
|
234
230
|
end
|
235
231
|
end
|
236
|
-
|
232
|
+
|
237
233
|
ALNUM = Chars.of /[[:alnum:]]/
|
238
234
|
ALPHA = Chars.of /[[:alpha:]]/
|
239
235
|
BLANK = Chars.of /[[:blank:]]/
|
@@ -247,8 +243,8 @@ class Rantly
|
|
247
243
|
UPPER = Chars.of /[[:upper:]]/
|
248
244
|
XDIGIT = Chars.of /[[:xdigit:]]/
|
249
245
|
ASCII = Chars.of /./
|
250
|
-
|
251
|
-
|
246
|
+
|
247
|
+
|
252
248
|
CLASSES = {
|
253
249
|
:alnum => ALNUM,
|
254
250
|
:alpha => ALPHA,
|
@@ -264,7 +260,7 @@ class Rantly
|
|
264
260
|
:xdigit => XDIGIT,
|
265
261
|
:ascii => ASCII,
|
266
262
|
}
|
267
|
-
|
263
|
+
|
268
264
|
end
|
269
265
|
|
270
266
|
def string(char_class=:print)
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'rantly/minitest_extensions'
|
data/lib/rantly/property.rb
CHANGED
@@ -1,13 +1,28 @@
|
|
1
1
|
require 'rantly'
|
2
|
-
require 'test/unit'
|
3
2
|
require 'pp'
|
3
|
+
require 'stringio'
|
4
4
|
|
5
5
|
class Rantly::Property
|
6
|
+
attr_reader :failed_data, :shrunk_failed_data, :io
|
7
|
+
|
8
|
+
VERBOSITY = ENV.fetch('RANTLY_VERBOSE'){ 1 }.to_i
|
9
|
+
|
10
|
+
def io
|
11
|
+
@io ||= if VERBOSITY >= 1
|
12
|
+
STDOUT
|
13
|
+
else
|
14
|
+
StringIO.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def pretty_print(object)
|
19
|
+
PP.pp(object, io)
|
20
|
+
end
|
6
21
|
|
7
22
|
def initialize(property)
|
8
23
|
@property = property
|
9
24
|
end
|
10
|
-
|
25
|
+
|
11
26
|
def check(n=100,limit=10,&assertion)
|
12
27
|
i = 0
|
13
28
|
test_data = nil
|
@@ -15,24 +30,48 @@ class Rantly::Property
|
|
15
30
|
Rantly.singleton.generate(n,limit,@property) do |val|
|
16
31
|
test_data = val
|
17
32
|
assertion.call(val) if assertion
|
18
|
-
puts "" if i % 100 == 0
|
19
|
-
print "." if i % 10 == 0
|
33
|
+
io.puts "" if i % 100 == 0
|
34
|
+
io.print "." if i % 10 == 0
|
20
35
|
i += 1
|
21
36
|
end
|
22
|
-
puts
|
23
|
-
puts "success: #{i} tests"
|
37
|
+
io.puts
|
38
|
+
io.puts "success: #{i} tests"
|
24
39
|
rescue Rantly::TooManyTries => e
|
25
|
-
puts
|
26
|
-
puts "too many tries: #{e.tries}"
|
40
|
+
io.puts
|
41
|
+
io.puts "too many tries: #{e.tries}"
|
27
42
|
raise e
|
28
|
-
rescue => boom
|
29
|
-
puts
|
30
|
-
puts "failure: #{i} tests, on:"
|
31
|
-
|
43
|
+
rescue Exception => boom
|
44
|
+
io.puts
|
45
|
+
io.puts "failure: #{i} tests, on:"
|
46
|
+
pretty_print test_data
|
47
|
+
@failed_data = test_data
|
48
|
+
if @failed_data.respond_to?(:shrink)
|
49
|
+
@shrunk_failed_data = shrinkify(assertion, @failed_data)
|
50
|
+
io.puts "minimal failed data is:"
|
51
|
+
pretty_print @shrunk_failed_data
|
52
|
+
end
|
32
53
|
raise boom
|
33
54
|
end
|
34
55
|
end
|
35
56
|
|
57
|
+
# return the first success case
|
58
|
+
def shrinkify(assertion, data)
|
59
|
+
# We assume that data.shrink is non-destructive
|
60
|
+
return data if !data.shrinkable?
|
61
|
+
val = data.shrink
|
62
|
+
begin
|
63
|
+
assertion.call(val)
|
64
|
+
io.puts "found a reduced success:"
|
65
|
+
pretty_print val
|
66
|
+
return data
|
67
|
+
rescue Exception
|
68
|
+
io.puts "found a reduced failure case:"
|
69
|
+
pretty_print val
|
70
|
+
# recursively shrink failure case
|
71
|
+
return shrinkify(assertion,val)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
36
75
|
def report
|
37
76
|
distribs = self.classifiers.sort { |a,b| b[1] <=> a[1] }
|
38
77
|
total = distribs.inject(0) { |sum,pair| sum + pair[1]}
|
@@ -41,20 +80,3 @@ class Rantly::Property
|
|
41
80
|
end
|
42
81
|
end
|
43
82
|
end
|
44
|
-
|
45
|
-
module Test::Unit::Assertions
|
46
|
-
def property_of(&block)
|
47
|
-
Rantly::Property.new(block)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
begin
|
52
|
-
require 'rspec'
|
53
|
-
class RSpec::Core::ExampleGroup
|
54
|
-
def property_of(&block)
|
55
|
-
Rantly::Property.new(block)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
rescue LoadError
|
59
|
-
"No RSpec loaded. Oh, well."
|
60
|
-
end
|
data/lib/rantly/rspec.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rantly/rspec_extensions'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class Integer
|
2
|
+
def shrink
|
3
|
+
if self < 0 then (self / 2).floor + 1
|
4
|
+
elsif self <= 10 && self > 0 then self - 1
|
5
|
+
elsif self > 0 then ((self + 1) / 2).ceil - 1
|
6
|
+
else
|
7
|
+
return 0
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def shrinkable?
|
12
|
+
self != 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class String
|
17
|
+
def shrink
|
18
|
+
if self.size > 0
|
19
|
+
idx = Random::rand(self.size)
|
20
|
+
shrunk = self.dup
|
21
|
+
shrunk[idx] = ""
|
22
|
+
return shrunk
|
23
|
+
else
|
24
|
+
return ""
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def shrinkable?
|
29
|
+
self != ""
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Array
|
34
|
+
def shrink
|
35
|
+
idx = find_index{|e| e.respond_to?(:shrinkable?) && e.shrinkable?}
|
36
|
+
if idx != nil
|
37
|
+
clone = self.dup
|
38
|
+
clone[idx] = clone[idx].shrink
|
39
|
+
return clone
|
40
|
+
elsif !self.empty?
|
41
|
+
i = Random::rand(self.length)
|
42
|
+
a2 = self.dup
|
43
|
+
a2.delete_at(i)
|
44
|
+
return a2
|
45
|
+
else
|
46
|
+
return self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def shrinkable?
|
51
|
+
self.any?{|e| e.respond_to?(:shrinkable?) && e.shrinkable? } ||
|
52
|
+
!self.empty?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Hash
|
57
|
+
def shrink
|
58
|
+
if self.any?{|_,v| v.respond_to?(:shrinkable?) && v.shrinkable? }
|
59
|
+
key,_ = self.detect{|_,v| v.respond_to?(:shrinkable?) && v.shrinkable? }
|
60
|
+
clone = self.dup
|
61
|
+
clone[key] = clone[key].shrink
|
62
|
+
return clone
|
63
|
+
elsif !self.empty?
|
64
|
+
key = self.keys.first
|
65
|
+
h2 = self.dup
|
66
|
+
h2.delete(key)
|
67
|
+
return h2
|
68
|
+
else
|
69
|
+
return self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def shrinkable?
|
74
|
+
self.any?{|_,v| v.respond_to?(:shrinkable?) && v.shrinkable? } ||
|
75
|
+
!self.empty?
|
76
|
+
end
|
77
|
+
end
|
data/lib/rantly/silly.rb
CHANGED
@@ -21,7 +21,7 @@ module Rantly::Silly::Love
|
|
21
21
|
#{post_script}
|
22
22
|
EOS
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def address
|
26
26
|
"my #{extremifier} #{pedestal_label}"
|
27
27
|
end
|
@@ -60,9 +60,8 @@ EOS
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def caused_by
|
63
|
-
|
64
63
|
end
|
65
|
-
|
64
|
+
|
66
65
|
def whoami
|
67
66
|
"#{extremifier} #{humbleizer} #{groveler}"
|
68
67
|
end
|
@@ -113,4 +112,3 @@ EOS
|
|
113
112
|
choose "once in a while","night","day","hour","minute"
|
114
113
|
end
|
115
114
|
end
|
116
|
-
|
data/rantly.gemspec
CHANGED
@@ -1,55 +1,70 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: rantly 0.3.2 ruby lib
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
|
-
s.name =
|
8
|
-
s.version = "0.3.
|
8
|
+
s.name = "rantly"
|
9
|
+
s.version = "0.3.2"
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.authors = ["Howard Yeh", "Anthony Bargnesi"]
|
14
|
+
s.date = "2015-09-16"
|
15
|
+
s.email = ["hayeah@gmail.com", "abargnesi@gmail.com"]
|
14
16
|
s.extra_rdoc_files = [
|
15
17
|
"LICENSE",
|
16
|
-
|
18
|
+
"README.textile"
|
17
19
|
]
|
18
20
|
s.files = [
|
19
21
|
".document",
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
s.summary = %q{Ruby Imperative Random Data Generator and Quickcheck}
|
40
|
-
s.test_files = [
|
22
|
+
".travis.yml",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE",
|
25
|
+
"README.textile",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION.yml",
|
28
|
+
"lib/rantly.rb",
|
29
|
+
"lib/rantly/data.rb",
|
30
|
+
"lib/rantly/generator.rb",
|
31
|
+
"lib/rantly/minitest.rb",
|
32
|
+
"lib/rantly/minitest_extensions.rb",
|
33
|
+
"lib/rantly/property.rb",
|
34
|
+
"lib/rantly/rspec.rb",
|
35
|
+
"lib/rantly/rspec_extensions.rb",
|
36
|
+
"lib/rantly/shrinks.rb",
|
37
|
+
"lib/rantly/silly.rb",
|
38
|
+
"lib/rantly/spec.rb",
|
39
|
+
"lib/rantly/testunit_extensions.rb",
|
40
|
+
"rantly.gemspec",
|
41
41
|
"test/rantly_test.rb",
|
42
|
-
|
42
|
+
"test/shrinks_test.rb",
|
43
|
+
"test/test_helper.rb"
|
43
44
|
]
|
45
|
+
s.homepage = "https://github.com/abargnesi/rantly"
|
46
|
+
s.rubygems_version = "2.4.5.1"
|
47
|
+
s.summary = "Ruby Imperative Random Data Generator and Quickcheck"
|
44
48
|
|
45
49
|
if s.respond_to? :specification_version then
|
46
|
-
|
47
|
-
s.specification_version = 3
|
50
|
+
s.specification_version = 4
|
48
51
|
|
49
|
-
if Gem::Version.new(Gem::
|
52
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
53
|
+
s.add_development_dependency(%q<minitest>, ["~> 5.7.0"])
|
54
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
56
|
+
s.add_development_dependency(%q<coveralls>, [">= 0"])
|
50
57
|
else
|
58
|
+
s.add_dependency(%q<minitest>, ["~> 5.7.0"])
|
59
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
60
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
61
|
+
s.add_dependency(%q<coveralls>, [">= 0"])
|
51
62
|
end
|
52
63
|
else
|
64
|
+
s.add_dependency(%q<minitest>, ["~> 5.7.0"])
|
65
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
66
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
67
|
+
s.add_dependency(%q<coveralls>, [">= 0"])
|
53
68
|
end
|
54
69
|
end
|
55
70
|
|
data/test/rantly_test.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
|
-
require '
|
2
|
-
require 'rantly/
|
1
|
+
require 'test_helper'
|
2
|
+
require 'rantly/minitest_extensions'
|
3
3
|
|
4
4
|
module RantlyTest
|
5
5
|
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def setup
|
7
|
+
describe Rantly::Property do
|
8
|
+
|
9
|
+
before do
|
11
10
|
Rantly.gen.reset
|
12
11
|
end
|
13
|
-
|
14
|
-
|
12
|
+
|
13
|
+
it "fail test generation" do
|
15
14
|
assert_raises(Rantly::TooManyTries) {
|
16
15
|
property_of { guard range(0,1) < 0 }.check
|
17
16
|
}
|
18
17
|
end
|
19
18
|
|
20
|
-
|
19
|
+
it "generate literal value by returning itself" do
|
21
20
|
property_of {
|
22
21
|
i = integer
|
23
22
|
[i,literal(i)]
|
@@ -26,7 +25,7 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
26
25
|
}
|
27
26
|
end
|
28
27
|
|
29
|
-
|
28
|
+
it "generate integer in range" do
|
30
29
|
property_of {
|
31
30
|
i = integer
|
32
31
|
[i,range(i,i)]
|
@@ -37,15 +36,15 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
37
36
|
lo, hi = [integer(100),integer(100)].sort
|
38
37
|
[lo,hi,range(lo,hi)]
|
39
38
|
}.check { |(lo,hi,int)|
|
40
|
-
assert((lo..hi).include?(int))
|
39
|
+
assert((lo..hi).include?(int))
|
41
40
|
}
|
42
41
|
end
|
43
42
|
|
44
|
-
|
43
|
+
it "generate Fixnum only" do
|
45
44
|
property_of { integer }.check { |i| assert i.is_a?(Integer) }
|
46
45
|
end
|
47
46
|
|
48
|
-
|
47
|
+
it "generate integer less than abs(n)" do
|
49
48
|
property_of {
|
50
49
|
n = range(0,10)
|
51
50
|
[n,integer(n)]
|
@@ -54,17 +53,17 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
54
53
|
}
|
55
54
|
end
|
56
55
|
|
57
|
-
|
56
|
+
it "generate Float" do
|
58
57
|
property_of { float }.check { |f| assert f.is_a?(Float)}
|
59
58
|
end
|
60
59
|
|
61
|
-
|
60
|
+
it "generate Boolean" do
|
62
61
|
property_of { boolean }.check { |t|
|
63
62
|
assert t == true || t == false
|
64
63
|
}
|
65
64
|
end
|
66
65
|
|
67
|
-
|
66
|
+
it "generate empty strings" do
|
68
67
|
property_of {
|
69
68
|
sized(0) { string }
|
70
69
|
}.check { |s|
|
@@ -72,7 +71,7 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
72
71
|
}
|
73
72
|
end
|
74
73
|
|
75
|
-
|
74
|
+
it "generate strings with the right regexp char classes" do
|
76
75
|
char_classes = Rantly::Chars::CLASSES.keys
|
77
76
|
property_of {
|
78
77
|
char_class = choose(*char_classes)
|
@@ -92,7 +91,7 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
92
91
|
}
|
93
92
|
end
|
94
93
|
|
95
|
-
|
94
|
+
it "generate strings matching regexp" do
|
96
95
|
property_of {
|
97
96
|
sized(10) { string(/[abcd]/) }
|
98
97
|
}.check { |s|
|
@@ -102,11 +101,11 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
102
101
|
|
103
102
|
# call
|
104
103
|
|
105
|
-
|
104
|
+
it "call Symbol as method call (no arg)" do
|
106
105
|
property_of {call(:integer)}.check { |i| i.is_a?(Integer)}
|
107
106
|
end
|
108
107
|
|
109
|
-
|
108
|
+
it "call Symbol as method call (with arg)" do
|
110
109
|
property_of {
|
111
110
|
n = range(0,100)
|
112
111
|
[n,call(:integer,n)]
|
@@ -115,8 +114,8 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
115
114
|
}
|
116
115
|
end
|
117
116
|
|
118
|
-
|
119
|
-
|
117
|
+
it "call Array by calling first element as method, the rest as args" do
|
118
|
+
assert_raises(RuntimeError) {
|
120
119
|
Rantly.gen.value {
|
121
120
|
call []
|
122
121
|
}
|
@@ -128,8 +127,8 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
128
127
|
assert_equal a, b
|
129
128
|
}
|
130
129
|
end
|
131
|
-
|
132
|
-
|
130
|
+
|
131
|
+
it "call Proc with generator.instance_eval" do
|
133
132
|
property_of {
|
134
133
|
call Proc.new { true }
|
135
134
|
}.check { |o|
|
@@ -147,16 +146,16 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
147
146
|
assert i1 > i0
|
148
147
|
}
|
149
148
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
149
|
+
|
150
|
+
it "raise if calling on any other value" do
|
151
|
+
assert_raises(RuntimeError) {
|
153
152
|
Rantly.gen.call 0
|
154
153
|
}
|
155
154
|
end
|
156
155
|
|
157
156
|
# branch
|
158
157
|
|
159
|
-
|
158
|
+
it "branch by Rantly#calling one of the args" do
|
160
159
|
property_of {
|
161
160
|
branch :integer, :integer, :integer
|
162
161
|
}.check { |o|
|
@@ -169,10 +168,9 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
169
168
|
}
|
170
169
|
end
|
171
170
|
|
172
|
-
|
173
171
|
# choose
|
174
|
-
|
175
|
-
|
172
|
+
|
173
|
+
it "choose a value from args " do
|
176
174
|
property_of {
|
177
175
|
choose
|
178
176
|
}.check {|o|
|
@@ -190,7 +188,7 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
190
188
|
}
|
191
189
|
property_of {
|
192
190
|
arr = sized(10) { array { integer } }
|
193
|
-
choose(*arr)
|
191
|
+
choose(*arr)
|
194
192
|
}.check { |o|
|
195
193
|
assert o.is_a?(Fixnum)
|
196
194
|
}
|
@@ -207,7 +205,7 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
207
205
|
|
208
206
|
# freq
|
209
207
|
|
210
|
-
|
208
|
+
it "not pick an element with 0 frequency" do
|
211
209
|
property_of {
|
212
210
|
sized(10) {
|
213
211
|
array { freq([0,:string],[1,:integer]) }
|
@@ -217,8 +215,8 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
217
215
|
}
|
218
216
|
end
|
219
217
|
|
220
|
-
|
221
|
-
|
218
|
+
it "handle degenerate freq pairs" do
|
219
|
+
assert_raises(RuntimeError) {
|
222
220
|
Rantly.gen.value {
|
223
221
|
freq
|
224
222
|
}
|
@@ -233,15 +231,15 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
233
231
|
|
234
232
|
# array
|
235
233
|
|
236
|
-
|
234
|
+
it "generate empty array" do
|
237
235
|
property_of {
|
238
236
|
sized(0) { array { integer }}
|
239
237
|
}.check { |o|
|
240
238
|
assert o.empty?
|
241
239
|
}
|
242
240
|
end
|
243
|
-
|
244
|
-
|
241
|
+
|
242
|
+
it "generate the right sized nested arrays" do
|
245
243
|
property_of {
|
246
244
|
size1 = range(5,10)
|
247
245
|
size2 = range(0,size1-1)
|
@@ -252,8 +250,8 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
252
250
|
assert outter_array.all? { |inner_array| inner_array.size < size1 }
|
253
251
|
}
|
254
252
|
end
|
255
|
-
|
256
|
-
|
253
|
+
|
254
|
+
it "generate array with right types" do
|
257
255
|
property_of {
|
258
256
|
sized(10) { array { freq(:integer,:string,:float)} }
|
259
257
|
}.check { |arr|
|
@@ -268,17 +266,24 @@ class RantlyTest::Generator < Test::Unit::TestCase
|
|
268
266
|
}
|
269
267
|
end
|
270
268
|
|
271
|
-
#
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
269
|
+
# it "raise if generating an array without size" do
|
270
|
+
# assert_raises(RuntimeError) {
|
271
|
+
# Rantly.gen.value { array(:integer) }
|
272
|
+
# }
|
273
|
+
# end
|
276
274
|
|
277
275
|
end
|
278
|
-
|
279
276
|
|
277
|
+
# TODO: Determine type of tests required here.
|
278
|
+
|
279
|
+
# check we generate the right kind of data.
|
280
|
+
## doesn't check for distribution
|
281
|
+
class RantlyTest::Generator < Minitest::Test
|
282
|
+
def setup
|
283
|
+
Rantly.gen.reset
|
284
|
+
end
|
285
|
+
end
|
280
286
|
|
281
287
|
# TODO: check that distributions of different methods look roughly correct.
|
282
|
-
class RantlyTest::Distribution
|
283
|
-
|
288
|
+
class RantlyTest::Distribution < Minitest::Test
|
284
289
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'rantly/shrinks'
|
3
|
+
require 'rantly/minitest_extensions'
|
4
|
+
|
5
|
+
module RantlyTest
|
6
|
+
end
|
7
|
+
|
8
|
+
module RantlyTest::Shrinkers
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Integer do
|
12
|
+
|
13
|
+
it "not be able to shrink 0 integer" do
|
14
|
+
assert !0.shrinkable?
|
15
|
+
end
|
16
|
+
|
17
|
+
it "shrink positive integers to something less than itself" do
|
18
|
+
assert(3.shrink < 3)
|
19
|
+
assert(2.shrink < 2)
|
20
|
+
assert_equal(0,1.shrink)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "shrink negative integers to something larger than itself" do
|
24
|
+
assert(-3.shrink > -3)
|
25
|
+
assert(-2.shrink > -2)
|
26
|
+
assert_equal(0,-1.shrink)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "shrink 0 to itself" do
|
30
|
+
# hmm. should this be undefined?
|
31
|
+
assert_equal 0.shrink, 0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe String do
|
36
|
+
|
37
|
+
it "not be able to shrink empty string" do
|
38
|
+
assert !"".shrinkable?
|
39
|
+
end
|
40
|
+
|
41
|
+
it "shrink a string one char shorter" do
|
42
|
+
property_of {
|
43
|
+
sized(10) { string }
|
44
|
+
}.check { |str|
|
45
|
+
assert_equal 9, str.shrink.length
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe Array do
|
51
|
+
|
52
|
+
it "not be able to shrink empty array" do
|
53
|
+
assert ![].shrinkable?
|
54
|
+
end
|
55
|
+
|
56
|
+
it "shrink array by trying to shrink the first shrinkable element available" do
|
57
|
+
assert_equal [0,1], [1,1].shrink
|
58
|
+
assert_equal [0,0,1], [0,1,1].shrink
|
59
|
+
end
|
60
|
+
|
61
|
+
it "shrink array by 1 if none of the element in it is shrinkable" do
|
62
|
+
property_of {
|
63
|
+
n = integer(1..10)
|
64
|
+
a = Array.new(n,0)
|
65
|
+
[n,a]
|
66
|
+
}.check { |n,a|
|
67
|
+
assert_equal n-1, a.shrink.length
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe Hash do
|
73
|
+
|
74
|
+
it "not be able to shrink empty hash" do
|
75
|
+
assert !{}.shrinkable?
|
76
|
+
end
|
77
|
+
|
78
|
+
it "shrink a value if one of the values is shrinkable" do
|
79
|
+
assert_equal({foo: 0, bar: 0}, {foo: 1, bar: 0}.shrink)
|
80
|
+
assert_equal({foo: 0, bar: 0}, {foo: 0, bar: 1}.shrink)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "shrink by deleting an element in it if none of the values is shrinkable" do
|
84
|
+
assert_equal({},{foo: 0}.shrink)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "Shrinker Test" do
|
89
|
+
|
90
|
+
it "shrink data to smallest value that fails assertion" do
|
91
|
+
# We try to generate an array of 10 elements, filled with ones.
|
92
|
+
# The property we try to test is that non of the element is
|
93
|
+
# larger than 1, and the array's length is less than 4.
|
94
|
+
test = property_of {
|
95
|
+
a = Array.new(10,1)
|
96
|
+
i = Random::rand(a.length)
|
97
|
+
a[i] = 1
|
98
|
+
a
|
99
|
+
}
|
100
|
+
assert_raises MiniTest::Assertion do
|
101
|
+
test.check { |a|
|
102
|
+
assert(!a.any? { |e| e > 0 } && a.length < 4,"contains 1")
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
assert_equal [0,0,0,0], test.shrunk_failed_data
|
107
|
+
end
|
108
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
3
|
-
require 'shoulda'
|
2
|
+
require 'minitest/autorun'
|
4
3
|
|
5
4
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
5
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
6
|
|
8
|
-
require '
|
7
|
+
require 'simplecov'
|
8
|
+
SimpleCov.start
|
9
9
|
|
10
|
-
|
10
|
+
begin
|
11
|
+
# Coveralls is marked as an _optional_ dependency, so don't
|
12
|
+
# throw a fit if it's not there.
|
13
|
+
require 'coveralls'
|
14
|
+
Coveralls.wear!
|
15
|
+
rescue LoadError
|
11
16
|
end
|
17
|
+
|
18
|
+
require 'rantly'
|
metadata
CHANGED
@@ -1,47 +1,84 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rantly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Howard Yeh
|
8
|
+
- Anthony Bargnesi
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 5.7.0
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 5.7.0
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: jeweler
|
16
|
-
requirement:
|
17
|
-
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: simplecov
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
18
45
|
requirements:
|
19
|
-
- -
|
46
|
+
- - ">="
|
20
47
|
- !ruby/object:Gem::Version
|
21
48
|
version: '0'
|
22
49
|
type: :development
|
23
50
|
prerelease: false
|
24
|
-
version_requirements:
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
25
56
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement:
|
28
|
-
none: false
|
57
|
+
name: coveralls
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
29
59
|
requirements:
|
30
|
-
- -
|
60
|
+
- - ">="
|
31
61
|
- !ruby/object:Gem::Version
|
32
62
|
version: '0'
|
33
63
|
type: :development
|
34
64
|
prerelease: false
|
35
|
-
version_requirements:
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
36
70
|
description:
|
37
|
-
email:
|
71
|
+
email:
|
72
|
+
- hayeah@gmail.com
|
73
|
+
- abargnesi@gmail.com
|
38
74
|
executables: []
|
39
75
|
extensions: []
|
40
76
|
extra_rdoc_files:
|
41
77
|
- LICENSE
|
42
78
|
- README.textile
|
43
79
|
files:
|
44
|
-
- .document
|
80
|
+
- ".document"
|
81
|
+
- ".travis.yml"
|
45
82
|
- Gemfile
|
46
83
|
- LICENSE
|
47
84
|
- README.textile
|
@@ -50,34 +87,41 @@ files:
|
|
50
87
|
- lib/rantly.rb
|
51
88
|
- lib/rantly/data.rb
|
52
89
|
- lib/rantly/generator.rb
|
90
|
+
- lib/rantly/minitest.rb
|
91
|
+
- lib/rantly/minitest_extensions.rb
|
53
92
|
- lib/rantly/property.rb
|
93
|
+
- lib/rantly/rspec.rb
|
94
|
+
- lib/rantly/rspec_extensions.rb
|
95
|
+
- lib/rantly/shrinks.rb
|
54
96
|
- lib/rantly/silly.rb
|
55
97
|
- lib/rantly/spec.rb
|
98
|
+
- lib/rantly/testunit_extensions.rb
|
56
99
|
- rantly.gemspec
|
57
100
|
- test/rantly_test.rb
|
101
|
+
- test/shrinks_test.rb
|
58
102
|
- test/test_helper.rb
|
59
|
-
homepage:
|
103
|
+
homepage: https://github.com/abargnesi/rantly
|
60
104
|
licenses: []
|
105
|
+
metadata: {}
|
61
106
|
post_install_message:
|
62
107
|
rdoc_options: []
|
63
108
|
require_paths:
|
64
109
|
- lib
|
65
110
|
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
111
|
requirements:
|
68
|
-
- -
|
112
|
+
- - ">="
|
69
113
|
- !ruby/object:Gem::Version
|
70
114
|
version: '0'
|
71
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
-
none: false
|
73
116
|
requirements:
|
74
|
-
- -
|
117
|
+
- - ">="
|
75
118
|
- !ruby/object:Gem::Version
|
76
119
|
version: '0'
|
77
120
|
requirements: []
|
78
121
|
rubyforge_project:
|
79
|
-
rubygems_version:
|
122
|
+
rubygems_version: 2.4.5.1
|
80
123
|
signing_key:
|
81
|
-
specification_version:
|
124
|
+
specification_version: 4
|
82
125
|
summary: Ruby Imperative Random Data Generator and Quickcheck
|
83
126
|
test_files: []
|
127
|
+
has_rdoc:
|