propr 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/NOTES.md +62 -0
- data/README.md +553 -0
- data/Rakefile +83 -0
- data/TODO.md +64 -0
- data/lib/propr.rb +123 -0
- data/lib/propr/dsl.rb +6 -0
- data/lib/propr/dsl/check.rb +49 -0
- data/lib/propr/dsl/property.rb +62 -0
- data/lib/propr/property.rb +23 -0
- data/lib/propr/random.rb +143 -0
- data/lib/propr/random/array.rb +19 -0
- data/lib/propr/random/bigdecimal.rb +43 -0
- data/lib/propr/random/boolean.rb +7 -0
- data/lib/propr/random/complex.rb +0 -0
- data/lib/propr/random/date.rb +17 -0
- data/lib/propr/random/float.rb +60 -0
- data/lib/propr/random/hash.rb +55 -0
- data/lib/propr/random/integer.rb +38 -0
- data/lib/propr/random/maybe.rb +0 -0
- data/lib/propr/random/nil.rb +8 -0
- data/lib/propr/random/range.rb +32 -0
- data/lib/propr/random/rational.rb +0 -0
- data/lib/propr/random/set.rb +22 -0
- data/lib/propr/random/string.rb +41 -0
- data/lib/propr/random/symbol.rb +13 -0
- data/lib/propr/random/time.rb +14 -0
- data/lib/propr/rspec.rb +97 -0
- data/lib/propr/runner.rb +53 -0
- data/lib/propr/shrink/array.rb +16 -0
- data/lib/propr/shrink/bigdecimal.rb +17 -0
- data/lib/propr/shrink/boolean.rb +11 -0
- data/lib/propr/shrink/complex.rb +0 -0
- data/lib/propr/shrink/date.rb +12 -0
- data/lib/propr/shrink/float.rb +17 -0
- data/lib/propr/shrink/hash.rb +18 -0
- data/lib/propr/shrink/integer.rb +10 -0
- data/lib/propr/shrink/maybe.rb +11 -0
- data/lib/propr/shrink/nil.rb +5 -0
- data/lib/propr/shrink/object.rb +5 -0
- data/lib/propr/shrink/range.rb +4 -0
- data/lib/propr/shrink/rational.rb +4 -0
- data/lib/propr/shrink/set.rb +18 -0
- data/lib/propr/shrink/string.rb +19 -0
- data/lib/propr/shrink/symbol.rb +5 -0
- data/lib/propr/shrink/time.rb +9 -0
- data/spec/examples/choose/array.example +12 -0
- data/spec/examples/choose/hash.example +12 -0
- data/spec/examples/choose/range.example +13 -0
- data/spec/examples/choose/set.example +12 -0
- data/spec/examples/guard.example +38 -0
- data/spec/examples/random/array.example +38 -0
- data/spec/examples/random/hash.example +18 -0
- data/spec/examples/random/integer.example +23 -0
- data/spec/examples/random/range.example +43 -0
- data/spec/examples/scale.example +17 -0
- data/spec/examples/shrink/array.example +20 -0
- data/spec/examples/shrink/bigdecimal.example +20 -0
- data/spec/examples/shrink/float.example +20 -0
- data/spec/examples/shrink/hash.example +20 -0
- data/spec/examples/shrink/integer.example +21 -0
- data/spec/examples/shrink/maybe.example +24 -0
- data/spec/examples/shrink/set.example +21 -0
- data/spec/examples/shrink/string.example +17 -0
- data/spec/issues/003.example +9 -0
- data/spec/spec_helper.rb +24 -0
- metadata +143 -0
data/Rakefile
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require "pathname"
|
2
|
+
abspath = Pathname.new(File.dirname(__FILE__)).expand_path
|
3
|
+
relpath = abspath.relative_path_from(Pathname.pwd)
|
4
|
+
|
5
|
+
begin
|
6
|
+
require "rubygems"
|
7
|
+
require "bundler/setup"
|
8
|
+
rescue LoadError
|
9
|
+
warn "couldn't load bundler:"
|
10
|
+
warn " #{$!}"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :console do
|
14
|
+
exec *%w(irb -I lib -r propr)
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
require "rspec/core/rake_task"
|
19
|
+
|
20
|
+
RSpec::Core::RakeTask.new do |t|
|
21
|
+
t.verbose = false
|
22
|
+
t.pattern = "#{relpath}/spec/examples/**/*.example"
|
23
|
+
|
24
|
+
t.rspec_opts = %w(--color)
|
25
|
+
t.rspec_opts << "--profile"
|
26
|
+
t.rspec_opts << "-I#{abspath}/spec"
|
27
|
+
end
|
28
|
+
rescue LoadError
|
29
|
+
task :spec do
|
30
|
+
warn "couldn't load rspec"
|
31
|
+
warn " #{$!}"
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
require "rcov"
|
38
|
+
begin
|
39
|
+
require "rspec/core/rake_task"
|
40
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
41
|
+
t.rcov = true
|
42
|
+
t.rcov_opts = "--exclude spec/,gems/,00401"
|
43
|
+
|
44
|
+
t.verbose = false
|
45
|
+
t.pattern = "#{relpath}/spec/examples/**/*.example"
|
46
|
+
|
47
|
+
t.rspec_opts = %w(--color --format p)
|
48
|
+
t.rspec_opts << "-I#{abspath}/spec"
|
49
|
+
end
|
50
|
+
rescue LoadError
|
51
|
+
task :rcov do
|
52
|
+
warn "couldn't load rspec"
|
53
|
+
warn " #{$!}"
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
rescue LoadError
|
58
|
+
task :rcov do
|
59
|
+
warn "couldn't load rcov:"
|
60
|
+
warn " #{$!}"
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
begin
|
66
|
+
require "yard"
|
67
|
+
|
68
|
+
# Note options are loaded from .yardopts
|
69
|
+
YARD::Rake::YardocTask.new(:yard => :clobber_yard)
|
70
|
+
|
71
|
+
task :clobber_yard do
|
72
|
+
rm_rf "#{relpath}/doc/generated"
|
73
|
+
mkdir_p "#{relpath}/doc/generated/images"
|
74
|
+
end
|
75
|
+
rescue LoadError
|
76
|
+
task :yard do
|
77
|
+
warn "couldn't load yard:"
|
78
|
+
warn " #{$!}"
|
79
|
+
exit 1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
task :default => :spec
|
data/TODO.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
Priorities
|
2
|
+
|
3
|
+
1. Write unit tests
|
4
|
+
2. Write property tests
|
5
|
+
3. Write example properties and subclasses (markup)
|
6
|
+
4. API documentation
|
7
|
+
5. User documentation
|
8
|
+
6. Optimization (drop Ruby 1.8)
|
9
|
+
7. Publish as rubygem
|
10
|
+
8. Update Stupidedi
|
11
|
+
|
12
|
+
Specifics
|
13
|
+
|
14
|
+
* Organization of common properties
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
module ShrinkSpecs
|
18
|
+
def self
|
19
|
+
# must hold for all implementations
|
20
|
+
property("no value is smaller than itself"){|x| not x.shrink.member?(x) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe String, "#shrink" do
|
25
|
+
# property holds for all implementations
|
26
|
+
ShrinkSpecs.self
|
27
|
+
.check { String.random ... }
|
28
|
+
|
29
|
+
# property of the String#shrink implementation
|
30
|
+
property("empty"){|s| s.shrink.member?("") }
|
31
|
+
.check { String.random ... }
|
32
|
+
|
33
|
+
# property of the String#shrink implementation
|
34
|
+
property("shorter"){|s| s.shrink.all?{|x| x.length < s.length }}
|
35
|
+
.check { String.random ... }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe Integer, "#shrink" do
|
39
|
+
# property holds for all implementations
|
40
|
+
ShrinkSpecs.self
|
41
|
+
.check { Integer.random ... }
|
42
|
+
|
43
|
+
# property of the Integer#shrink implementation
|
44
|
+
property("smaller"){|n| n.shrink.all?{|m| m.abs < n.abs }}
|
45
|
+
.check { Integer.random ... }
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
* Stateful random generation
|
50
|
+
* <del>Re-consider sized values (magntitude, center) or range?</del>
|
51
|
+
* <del>Re-implement sized values</del>
|
52
|
+
* Steal `collect` and `classify` from QuickCheck
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
property("foo") { ... }
|
56
|
+
.check{|rand| rand.integer.tap{|n| classify(n < 0, "negative") }
|
57
|
+
.tap{|n| classify(n > 0, "positive") }}
|
58
|
+
|
59
|
+
property("bar") { ... }
|
60
|
+
check{|rand| rand.array.tap{|xs| collect xs.length }}
|
61
|
+
```
|
62
|
+
|
63
|
+
* <del>Shrink input with breadth first</del>
|
64
|
+
* See also: smallcheck, deepcheck
|
data/lib/propr.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Propr
|
2
|
+
autoload :Property, "propr/property"
|
3
|
+
autoload :Dsl, "propr/dsl"
|
4
|
+
autoload :Runner, "propr/runner"
|
5
|
+
autoload :RSpec, "propr/rspec"
|
6
|
+
autoload :RSpecAdapter, "propr/rspec"
|
7
|
+
|
8
|
+
require "fr"
|
9
|
+
require "propr/random"
|
10
|
+
|
11
|
+
def self.wrap(object)
|
12
|
+
if object.nil?
|
13
|
+
[]
|
14
|
+
elsif object.respond_to?(:to_ary)
|
15
|
+
object.to_ary || [object]
|
16
|
+
else
|
17
|
+
[object]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class GuardFailure < StandardError
|
22
|
+
end
|
23
|
+
|
24
|
+
class Falsifiable < StandardError
|
25
|
+
attr_reader :counterex, :shrunken, :passed, :skipped
|
26
|
+
|
27
|
+
def initialize(counterex, shrunken, passed, skipped)
|
28
|
+
@counterex, @shrunken, @passed, @skipped =
|
29
|
+
counterex, shrunken, passed, skipped
|
30
|
+
end
|
31
|
+
|
32
|
+
def counterex
|
33
|
+
Propr.wrap(@counterex)
|
34
|
+
end
|
35
|
+
|
36
|
+
def shrunken
|
37
|
+
Propr.wrap(@shrunken)
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
if @shrunken.nil?
|
42
|
+
["input: #{counterex.map(&:inspect).join(", ")}",
|
43
|
+
"after: #{@passed} passed, #{@skipped} skipped"].join("\n")
|
44
|
+
else
|
45
|
+
["input: #{counterex.map(&:inspect).join(", ")}",
|
46
|
+
"shrunken: #{shrunken.map(&:inspect).join(", ")}",
|
47
|
+
"after: #{@passed} passed, #{@skipped} skipped"].join("\n")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Failure < StandardError
|
53
|
+
attr_reader :counterex, :shrunken, :passed, :skipped
|
54
|
+
|
55
|
+
def initialize(exception, counterex, shrunken, passed, skipped)
|
56
|
+
@exception, @counterex, @shrunken, @passed, @skipped =
|
57
|
+
exception, counterex, shrunken, passed, skipped
|
58
|
+
end
|
59
|
+
|
60
|
+
def counterex
|
61
|
+
Propr.wrap(@counterex)
|
62
|
+
end
|
63
|
+
|
64
|
+
def shrunken
|
65
|
+
Propr.wrap(@shrunken)
|
66
|
+
end
|
67
|
+
|
68
|
+
def class
|
69
|
+
@exception.class
|
70
|
+
end
|
71
|
+
|
72
|
+
def backtrace
|
73
|
+
@exception.backtrace
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s
|
77
|
+
if @shrunken.nil?
|
78
|
+
[@exception.message,
|
79
|
+
"input: #{counterex.map(&:inspect).join(", ")}",
|
80
|
+
"after: #{@passed} passed, #{@skipped} skipped"].join("\n")
|
81
|
+
else
|
82
|
+
[@exception.message,
|
83
|
+
"input: #{counterex.map(&:inspect).join(", ")}",
|
84
|
+
"shrunken: #{shrunken.map(&:inspect).join(", ")}",
|
85
|
+
"after: #{@passed} passed, #{@skipped} skipped"].join("\n")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :message, :to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
class NoMoreTries < StandardError
|
93
|
+
# @return [Integer]
|
94
|
+
attr_reader :tries
|
95
|
+
|
96
|
+
def initialize(tries)
|
97
|
+
@tries = tries
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [String]
|
101
|
+
def to_s
|
102
|
+
"Exceeded #{@tries} failed guards"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.RSpec(checkdsl, propdsl)
|
107
|
+
Module.new.tap do |m|
|
108
|
+
m.send(:define_method, :property) { raise }
|
109
|
+
m.send(:define_singleton_method, :rand) { rand }
|
110
|
+
m.send(:define_singleton_method, :included) do |scope|
|
111
|
+
|
112
|
+
# @todo: raise an error if body isn't given
|
113
|
+
scope.send(:define_singleton_method, :property) do |name, options = {}, &body|
|
114
|
+
q = Dsl::Property.wrap(body)
|
115
|
+
p = Property.new(name, q)
|
116
|
+
RSpecAdapter.new(self, options, p)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
RSpec = RSpec(nil, nil)
|
123
|
+
end
|
data/lib/propr/dsl.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Propr
|
2
|
+
module Dsl
|
3
|
+
|
4
|
+
class Check
|
5
|
+
|
6
|
+
# Generates a monadic action, to be run with Random.eval
|
7
|
+
def self.wrap(block, m = Propr::Random)
|
8
|
+
new(block, m).instance_exec(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(block, m)
|
12
|
+
@context, @m =
|
13
|
+
Kernel.eval("self", block.binding), m
|
14
|
+
end
|
15
|
+
|
16
|
+
def bind(f, &g)
|
17
|
+
@m.bind(f, &g)
|
18
|
+
end
|
19
|
+
|
20
|
+
def unit(value)
|
21
|
+
@m.unit(value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def guard(*conditions)
|
25
|
+
@m.guard(*conditions)
|
26
|
+
end
|
27
|
+
|
28
|
+
def join(value)
|
29
|
+
@m.join(value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def sequence(actions)
|
33
|
+
@m.sequence(actions)
|
34
|
+
end
|
35
|
+
|
36
|
+
def scale(*args)
|
37
|
+
@m.scale(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def method_missing(name, *args, &block)
|
43
|
+
@context.__send__(name, *args, &block)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Propr
|
2
|
+
module Dsl
|
3
|
+
|
4
|
+
class Property
|
5
|
+
|
6
|
+
# Properties shouldn't be monadic, as all random data is generated
|
7
|
+
# elsewhere and passed as arguments to the property. However, this
|
8
|
+
# provides a workaround: m.eval, m.unit, m.bind, etc where `m` is
|
9
|
+
# given as an argument to `wrap`.
|
10
|
+
attr_reader :m
|
11
|
+
|
12
|
+
# Generates a new function, which should return a Boolean
|
13
|
+
def self.wrap(block, m = Propr::Random)
|
14
|
+
case block.arity
|
15
|
+
when 0; lambda{|| new(block, m).instance_exec(&block) }
|
16
|
+
when 1; lambda{|a| new(block, m).instance_exec(a,&block) }
|
17
|
+
when 2; lambda{|a,b| new(block, m).instance_exec(a,b,&block) }
|
18
|
+
when 3; lambda{|a,b,c| new(block, m).instance_exec(a,b,c,&block) }
|
19
|
+
when 4; lambda{|a,b,c,d| new(block, m).instance_exec(a,b,c,d &block) }
|
20
|
+
when 5; lambda{|a,b,c,d,e| new(block, m).instance_exec(a,b,c,d,e,&block) }
|
21
|
+
when 6; lambda{|a,b,c,d,e,f| new(block, m).instance_exec(a,b,c,d,e,f,&block) }
|
22
|
+
when 7; lambda{|a,b,c,d,e,f,g| new(block, m).instance_exec(a,b,c,d,e,f,g,&block) }
|
23
|
+
when 8; lambda{|a,b,c,d,e,f,g,h| new(block, m).instance_exec(a,b,c,d,e,f,g,h,&block) }
|
24
|
+
else lambda{|*args| new(block, m).instance_exec(*args,&block) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(block, m)
|
29
|
+
@context, @m =
|
30
|
+
Kernel.eval("self", block.binding), m
|
31
|
+
end
|
32
|
+
|
33
|
+
def error?(type = Exception)
|
34
|
+
begin
|
35
|
+
yield
|
36
|
+
false
|
37
|
+
rescue => e
|
38
|
+
e.is_a?(type)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def guard(*conditions)
|
43
|
+
if index = conditions.index{|x| not x }
|
44
|
+
raise GuardFailure,
|
45
|
+
"guard condition #{index} was false"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def label(value)
|
50
|
+
# @todo
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def method_missing(name, *args, &block)
|
56
|
+
@context.__send__(name, *args, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Propr
|
2
|
+
class Property
|
3
|
+
# @return [Proc]
|
4
|
+
def self.new(name, body)
|
5
|
+
body.instance_variable_set(:@name, name)
|
6
|
+
|
7
|
+
# @return [String]
|
8
|
+
body.define_singleton_method(:name) { @name }
|
9
|
+
|
10
|
+
# @return [Boolean]
|
11
|
+
body.define_singleton_method(:check) do |*args, &block|
|
12
|
+
if block.nil?
|
13
|
+
true == call(*args)
|
14
|
+
else
|
15
|
+
count = args.first || 100
|
16
|
+
count.times.all? { true == call(*block.call) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/propr/random.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
module Propr
|
2
|
+
|
3
|
+
class Random
|
4
|
+
end
|
5
|
+
|
6
|
+
class << Random
|
7
|
+
include Fr::Monad
|
8
|
+
|
9
|
+
# Evaluators
|
10
|
+
#############################################
|
11
|
+
|
12
|
+
def run(computation, scale = BigDecimal(1))
|
13
|
+
computation.call(bound scale)
|
14
|
+
end
|
15
|
+
|
16
|
+
def eval(computation, scale = BigDecimal(1), retries = 0)
|
17
|
+
skipped = 0
|
18
|
+
scale = bound(scale)
|
19
|
+
|
20
|
+
while true
|
21
|
+
value, _, success = computation.call(scale)
|
22
|
+
|
23
|
+
if success
|
24
|
+
return value
|
25
|
+
elsif (skipped += 1) > retries
|
26
|
+
raise NoMoreTries, retries
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Combinators
|
32
|
+
#############################################
|
33
|
+
|
34
|
+
def unit(value)
|
35
|
+
lambda do |scale|
|
36
|
+
[value, scale, true]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def bind(f, &g)
|
41
|
+
lambda do |scale|
|
42
|
+
value, scale, success = f.call(scale)
|
43
|
+
|
44
|
+
success ?
|
45
|
+
g.call(value).call(scale) :
|
46
|
+
[value, scale, success]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Actions
|
51
|
+
#############################################
|
52
|
+
|
53
|
+
# TODO: Make Random an instance of Functor and use Functor.guard?
|
54
|
+
def guard(*conditions)
|
55
|
+
lambda do |scale|
|
56
|
+
[nil, scale, conditions.all?]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# When given two arguments, scales a numeric value around a
|
61
|
+
# given origin `zero`, using the current scale factor (0..1).
|
62
|
+
#
|
63
|
+
def scale(number, range, zero)
|
64
|
+
if range.zero?
|
65
|
+
# No scaling
|
66
|
+
lambda do |scale|
|
67
|
+
[number, scale, true]
|
68
|
+
end
|
69
|
+
else
|
70
|
+
# Shrink range exponentially, and -1 + scale reduces the
|
71
|
+
# rng_ to 0 when scale = 0, but rng_ = range when scale = 1.
|
72
|
+
lambda do |scale|
|
73
|
+
rng_ = (range ** scale) - 1 + scale
|
74
|
+
pct = (number - zero) / range
|
75
|
+
[zero + rng_ * pct, scale, true]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Generate psuedo-random number normally distributed between
|
81
|
+
# 0 <= x < 1. This distribution is not weighted using `scale`.
|
82
|
+
#
|
83
|
+
def rand(limit = nil)
|
84
|
+
if not limit.nil? and limit <= 0
|
85
|
+
raise InvalidArgument, "limit <= 0"
|
86
|
+
end
|
87
|
+
|
88
|
+
lambda do |scale|
|
89
|
+
[Kernel.rand(limit), scale, true]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def bound(scale)
|
96
|
+
if scale > 1
|
97
|
+
scale.coerce(1)[0]
|
98
|
+
elsif scale < 0
|
99
|
+
scale.coerce(0)[0]
|
100
|
+
else
|
101
|
+
scale
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Instances of Monad Random
|
109
|
+
require "propr/random/array"
|
110
|
+
require "propr/random/bigdecimal"
|
111
|
+
require "propr/random/boolean"
|
112
|
+
require "propr/random/complex"
|
113
|
+
require "propr/random/date"
|
114
|
+
require "propr/random/float"
|
115
|
+
require "propr/random/hash"
|
116
|
+
require "propr/random/integer"
|
117
|
+
require "propr/random/maybe"
|
118
|
+
require "propr/random/nil"
|
119
|
+
require "propr/random/range"
|
120
|
+
require "propr/random/rational"
|
121
|
+
require "propr/random/set"
|
122
|
+
require "propr/random/string"
|
123
|
+
require "propr/random/symbol"
|
124
|
+
require "propr/random/time"
|
125
|
+
|
126
|
+
# Instances of Shrink "typeclass"
|
127
|
+
require "propr/shrink/object"
|
128
|
+
require "propr/shrink/array"
|
129
|
+
require "propr/shrink/bigdecimal"
|
130
|
+
require "propr/shrink/boolean"
|
131
|
+
require "propr/shrink/complex"
|
132
|
+
require "propr/shrink/date"
|
133
|
+
require "propr/shrink/float"
|
134
|
+
require "propr/shrink/hash"
|
135
|
+
require "propr/shrink/integer"
|
136
|
+
require "propr/shrink/maybe"
|
137
|
+
require "propr/shrink/nil"
|
138
|
+
require "propr/shrink/range"
|
139
|
+
require "propr/shrink/rational"
|
140
|
+
require "propr/shrink/set"
|
141
|
+
require "propr/shrink/string"
|
142
|
+
require "propr/shrink/symbol"
|
143
|
+
require "propr/shrink/time"
|