queencheck 0.1.2 → 1.0.0

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/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem "colorize", ">= 0.5.8"
4
+
3
5
  group :development, :test do
4
6
  gem "rake", ">= 0.9.2.2"
5
7
  gem "rspec", ">= 2.8.0"
@@ -17,4 +19,6 @@ group :development do
17
19
  gem "guard-yard", ">= 1.0.2"
18
20
  gem "yard", ">= 0.7.4"
19
21
  gem "yard-tomdoc", ">= 0.3.0"
22
+ gem "redcarpet"
23
+ gem "pry"
20
24
  end
data/Guardfile CHANGED
@@ -8,7 +8,7 @@ spork_port = RUBY_VERSION >= '1.9.2' ? 8989 : 8988
8
8
  guard 'spork', :cucumber => false, :bundler => false, :rspec_port => spork_port do
9
9
  end
10
10
 
11
- guard 'rspec', :version => 2, :cli => "--drb --drb-port #{spork_port} --color --format Fuubar" do
11
+ guard 'rspec', :version => 2, :cli => "--drb --drb-port #{spork_port} --color --format doc" do
12
12
  watch(%r{^spec/.+_spec\.rb$})
13
13
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
14
14
  watch('spec/spec_helper.rb') { "spec" }
@@ -16,5 +16,6 @@ end
16
16
 
17
17
  guard 'yard', :plugin => 'yard-tomdoc' do
18
18
  watch(%r{lib/.+\.rb})
19
+ watch(%r{README})
19
20
  end
20
21
 
@@ -0,0 +1,119 @@
1
+ # QueenCheck [![Build Status](https://secure.travis-ci.org/rosylilly/QueenCheck.png)](http://travis-ci.org/rosylilly/QueenCheck) [![Gem Status](https://gemnasium.com/rosylilly/QueenCheck.png)](https://gemnasium.com/rosylilly/QueenCheck)
2
+
3
+ QueenCheck is random test library.
4
+
5
+ Inspired by QuickCheck library in Haskell.
6
+
7
+ ## Usage
8
+
9
+ $ gem install queencheck
10
+
11
+ or
12
+
13
+ $ git clone git://github.com/rosylilly/QueenCheck.git QueenCheck
14
+ $ cd QueenCheck
15
+ $ bundle install
16
+ $ bundle exec rake install
17
+
18
+ ## CI Report
19
+
20
+ [See Travis-CI](http://travis-ci.org/#!/rosylilly/QueenCheck)
21
+
22
+ ## Abstract
23
+
24
+ let's start DDT(Data Driven Testing)
25
+
26
+ require 'queencheck'
27
+
28
+ def plus(x, y)
29
+ x + y
30
+ end
31
+
32
+ prop_Plus = QueenCheck::Testable.new(Integer, Integer) do | x, y |
33
+ plus(x, y) == x + y
34
+ end
35
+ puts prop_Plus.check.pretty_report
36
+ # Tests: 100
37
+ # ✓ Successes : 100
38
+ # ✗ Failures : 0
39
+ # ✷ Exceptions : 0
40
+
41
+ with `exception`, `labeling` and `where`
42
+
43
+ def div(x, y)
44
+ x / y # => raise ZeroDividedError if y == 0
45
+ end
46
+
47
+ prop_Div = QueenCheck::Testable.new(Integer, Integer) do | x, y |
48
+ div(x, y) == x / y
49
+ end
50
+ puts prop_Div.check.pretty_report
51
+ # Tests: 100
52
+ # ✓ Successes : 99
53
+ # ✗ Failures : 1
54
+ # ✷ Exceptions : 1
55
+
56
+ puts prop_Div.check_with_label(
57
+ "x > y" => proc{|x,y| x > y },
58
+ "x < y" => proc{|x,y| x < y },
59
+ "x = y" => proc{|x,y| x == y },
60
+ "x is 0" => proc{|x,y| x.zero? },
61
+ "y is 0" => proc{|x,y| y.zero? }
62
+ ).pretty_report
63
+ # Tests: 100
64
+ # ✓ Successes : 99
65
+ # x > y : 43
66
+ # x < y : 56
67
+ # x = y : 0
68
+ # x is 0 : 0
69
+ # y is 0 : 0
70
+ # ✗ Failures : 1
71
+ # x > y : 0
72
+ # x < y : 0
73
+ # x = y : 1
74
+ # x is 0 : 1
75
+ # y is 0 : 1
76
+ # ✷ Exceptions : 1
77
+ # x > y : 0
78
+ # x < y : 0
79
+ # x = y : 1
80
+ # x is 0 : 1
81
+ # y is 0 : 1
82
+
83
+ int_generater = Integer.arbitrary.gen # => QueenCheck::Gen
84
+ nonzero_integer = int_generater.where{|num| !num.zero? }
85
+ prop_DivSuccess = QueenCheck::Testable.new(nonzero_integer, nonzero_integer) do | x, y |
86
+ div(x, y) == x / y
87
+ end
88
+ puts prop_DivSuccess.check_with_label(
89
+ "x > y" => proc{|x,y| x > y },
90
+ "x < y" => proc{|x,y| x < y },
91
+ "x = y" => proc{|x,y| x == y },
92
+ "x is 0" => proc{|x,y| x.zero? },
93
+ "y is 0" => proc{|x,y| y.zero? }
94
+ ).pretty_report
95
+ # Tests: 99
96
+ # ✓ Successes : 99
97
+ # x > y : 55
98
+ # x < y : 44
99
+ # x = y : 0
100
+ # x is 0 : 0
101
+ # y is 0 : 0
102
+ # ✗ Failures : 0
103
+ # x > y : 0
104
+ # x < y : 0
105
+ # x = y : 0
106
+ # x is 0 : 0
107
+ # y is 0 : 0
108
+ # ✷ Exceptions : 0
109
+ # x > y : 0
110
+ # x < y : 0
111
+ # x = y : 0
112
+ # x is 0 : 0
113
+ # y is 0 : 0
114
+
115
+ ## Help me
116
+
117
+ please fork [QueenCheck repository](https://github.com/rosylilly/QueenCheck).
118
+
119
+ __I'm waiting for the code review of you !__
data/Rakefile CHANGED
@@ -28,3 +28,14 @@ begin
28
28
  rescue LoadError
29
29
  puts "YARD not available. Install it with: bundle install"
30
30
  end
31
+
32
+ begin
33
+ require 'pry'
34
+
35
+ task "pry" do
36
+ require './lib/queencheck'
37
+ binding.pry
38
+ end
39
+ rescue LoadError
40
+ puts "Pry not available. Install it with: gem intall pry"
41
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 1.0.0
@@ -1,17 +1,20 @@
1
- require "pathname"
2
- $:.unshift Pathname.new(File.expand_path('../', __FILE__))
1
+ # QueenCheck is Test Utility Library like Quick Check in Haskell.
2
+ #
3
+ # == Examples:
4
+ #
5
+ # QueenCheck(Integer, Integer) do | x, y |
6
+ # x + y == y + x
7
+ # end
8
+ module QueenCheck
9
+ # QueenCheck Version
10
+ VERSION = '1.0.0'
11
+ end
3
12
 
13
+ $: << File.dirname(File.expand_path(__FILE__))
4
14
  require 'queencheck/core'
5
15
  require 'queencheck/arbitrary'
16
+ require 'queencheck/gen'
17
+ require 'queencheck/condition'
18
+ require 'queencheck/exception'
6
19
 
7
- require 'queencheck/integer'
8
- require 'queencheck/float'
9
- require 'queencheck/boolean'
10
- require 'queencheck/array'
11
- require 'queencheck/string'
12
-
13
- module QueenCheck
14
- unless defined? Version
15
- Version = `cat #{Pathname.new(File.expand_path('../../', __FILE__))}/VERSION`.strip
16
- end
17
- end
20
+ require 'queencheck/arbitraries/all'
@@ -0,0 +1,5 @@
1
+ # require all default arbitrary
2
+
3
+ require 'queencheck/arbitraries/boolean'
4
+ require 'queencheck/arbitraries/integer'
5
+ require 'queencheck/arbitraries/string'
@@ -0,0 +1,5 @@
1
+ require 'queencheck/arbitrary'
2
+
3
+ class Boolean
4
+ arbitrary QueenCheck::Gen.elements_of([true, false])
5
+ end
@@ -0,0 +1,17 @@
1
+ require 'queencheck/arbitrary'
2
+
3
+ class Integer
4
+ arbitrary QueenCheck::Gen.quadratic(1<<20).bind { |n|
5
+ QueenCheck::Gen.rand.resize(-(n.ceil), n.ceil)
6
+ }
7
+ end
8
+
9
+ class Fixnum
10
+ arbitrary Integer.arbitrary.gen
11
+ end
12
+
13
+ class Bignum
14
+ arbitrary QueenCheck::Gen.quadratic(1<<20, 1, (1 << (0.size * 8))).bind {|n|
15
+ QueenCheck::Gen.rand.resize(-(n.ceil), n.ceil)
16
+ }
17
+ end
@@ -0,0 +1,39 @@
1
+ require 'queencheck/arbitrary'
2
+
3
+ module QueenCheck
4
+ class ASCIIChar
5
+ arbitrary QueenCheck::Gen.choose(0, 127).bind { | c |
6
+ QueenCheck::Gen.unit(c.chr)
7
+ }
8
+ end
9
+
10
+ class Alphabet
11
+ class LowerCase
12
+ arbitrary QueenCheck::Gen.choose(97, 122).bind { | c |
13
+ QueenCheck::Gen.unit(c.chr)
14
+ }
15
+ end
16
+
17
+ class UpperCase
18
+ arbitrary QueenCheck::Gen.choose(65, 90).bind { | c |
19
+ QueenCheck::Gen.unit(c.chr)
20
+ }
21
+ end
22
+
23
+ arbitrary QueenCheck::Gen.one_of([LowerCase.arbitrary.gen, UpperCase.arbitrary.gen])
24
+ end
25
+ end
26
+
27
+ class String
28
+ arbitrary QueenCheck::Gen.quadratic(20000).bind { | length |
29
+ if length.zero?
30
+ QueenCheck::Gen.unit("")
31
+ else
32
+ QueenCheck::Gen.rand.resize(1, length).fmap { | r |
33
+ str = []
34
+ r.times { str << QueenCheck::ASCIIChar.arbitrary.gen.value(0)[0] }
35
+ str.join()
36
+ }
37
+ end
38
+ }
39
+ end
@@ -1,56 +1,100 @@
1
+ require 'queencheck/gen'
1
2
 
2
3
  module QueenCheck
3
4
  class << self
4
- def Arbitrary(name = nil, &block)
5
- if block.nil? && !name.nil?
6
- return QueenCheck::Arbitrary::Instance.get_by_id(name)
7
- else
8
- return QueenCheck::Arbitrary::Instance.new(name, &block)
9
- end
10
- nil
5
+ # set or get arbitrary
6
+ # @overload Arbitrary(name)
7
+ # @param [#name or #to_s] name arbitrary name
8
+ # @return [QueenCheck::Arbitrary]
9
+ # @overload Arbitrary(name, gen)
10
+ # @param [#name or #to_s] name arbitrary name
11
+ # @param [QueenCheck::Gen or Proc] gen arbitrary generator
12
+ # @return [Symbol or String] stored arbitrary name
13
+ # @overload Arbitrary(name, &block)
14
+ # @param [#name or #to_s] name arbitrary name
15
+ # @param [Proc] block arbitrary generator source
16
+ # @return [Symbol or String] stored arbitrary name
17
+ def Arbitrary(name, gen = nil, &block)
18
+ generator = gen || block
19
+
20
+ generator.nil? ? Arbitrary.from_dic(name) : Arbitrary.new(name, generator)
11
21
  end
12
22
  end
13
- module Arbitrary
14
- class NotQueenCheckArbitrary < StandardError; end
15
23
 
16
- def arbitrary?; true; end
24
+ # QueenCheck Arbitrary class
25
+ # @example
26
+ # QueenCheck::Arbitrary(Integer, QueenCheck::Gen.unit(0))
27
+ class Arbitrary
28
+ @@dictionary = {}
17
29
 
18
- def arbitrary(seed)
19
- raise NotImplementedError
30
+ # new instance of QueenCheck::Arbitrary
31
+ # @overload initialize(name, gen)
32
+ # @param [#name or #to_s] name arbitrary name
33
+ # @param [QueenCheck::Gen or Proc] gen arbitrary generater
34
+ # @overload initialize(name, &block)
35
+ # @param [#name or #to_s] name arbitrary name
36
+ # @param [Proc] block arbitrary generater source
37
+ def initialize(name, gen, &block)
38
+ gen = block || gen
39
+ @gen = gen.instance_of?(QueenCheck::Gen) ? gen : QueenCheck::Gen.new(&gen)
40
+ @name = QueenCheck::Arbitrary.to_dic(name, self)
20
41
  end
21
42
 
22
- def set_arbitrary(&block)
23
- self.module_eval do
24
- sig = class << self; self; end
25
- sig.send(:define_method, :arbitrary, &block)
26
- end
43
+ # @return [Symbol or String] arbitrary name
44
+ attr_reader :name
45
+ # @return [QueenCheck::Gen] arbitrary generater
46
+ attr_reader :gen
47
+
48
+
49
+ # store arbitrary to dictionary
50
+ # @param [#name or #to_s] name arbitrary name
51
+ # @param [QueenCheck::Arbitrary] arb store arbitrary
52
+ # @return [Symbol or String] stored arbitrary name
53
+ def self.to_dic(name, arb)
54
+ name = name.respond_to?(:name) ? name.name : name.to_s
55
+ @@dictionary[name] = arb
56
+ return name
27
57
  end
28
58
 
29
- class Instance
30
- @@collection = {}
31
- def self.get_by_id(name); return @@collection[name.to_s.to_sym]; end
32
- def self.collection=(c); @@collection = c; end
33
- def self.collection; @@collection; end
34
-
35
- def initialize(name = nil, &block)
36
- raise ArgumentError, "require block" if block.nil?
37
- @arbitrary_proc = block
38
- @name = name.to_s.to_sym unless name.nil?
39
- unless @name.nil?
40
- @@collection[@name] = self
41
- end
42
- end
43
- attr_reader :name
44
-
45
- def arbitrary?; true; end
46
-
47
- def arbitrary(seed)
48
- @arbitrary_proc.call(seed)
49
- end
59
+ # get arbitrary from dictionary
60
+ # @param [#name or #to_s] name arbitrary name
61
+ # @return [QueenCheck::Arbitrary or nil] QueenCheck::Arbitrary where hit name dictionary
62
+ def self.from_dic(name)
63
+ name = name.respond_to?(:name) ? name.name : name.to_s
64
+ @@dictionary[name]
50
65
  end
51
66
  end
52
67
  end
53
68
 
54
- class BasicObject
55
- def arbitrary?; false; end
69
+ class Class
70
+ # set arbitrary to class or get arbitrary of class
71
+ # @overload arbitrary
72
+ # get arbitrary of class
73
+ # @return [QueenCheck::Arbitrary] arbitrary of class
74
+ # @overload arbitrary(gen)
75
+ # set arbitrary of class
76
+ # @param [QueenCheck::Gen] gen generater of arbitrary
77
+ # @overload arbitrary(&block)
78
+ # set arbitrary of class
79
+ # @param [Proc] block proc of new QueenCheck::Gen instance
80
+ # @return [QueenCheck::Arbitrary] arbitrary of class
81
+ # @example
82
+ # class Klass
83
+ # arbitrary QueenCheck::Gen.choose(0, 100)
84
+ # #=> QueenCheck::Arbitrary
85
+ # end
86
+ # Klass.arbitrary #=> QueenCheck::Arbitrary
87
+ #
88
+ # # set arbitrary
89
+ # Klass.arbitrary {|p, r| Klass.new }
90
+ # @see QueenCheck.Arbitrary
91
+ def arbitrary(gen = nil, &block)
92
+ QueenCheck::Arbitrary(name, gen || block)
93
+ end
94
+
95
+ # check implemented arbitrary on class
96
+ # @return [Boolean] implemented arbitrary
97
+ def arbitrary?
98
+ !QueenCheck::Arbitrary(name).nil?
99
+ end
56
100
  end
@@ -0,0 +1,112 @@
1
+ module QueenCheck
2
+ # QueenCheck condition class
3
+ # @example
4
+ # QueenCheck::Alphabet::LowerCase.arbitrary.gen.where(:include? => ['a', 'b', 'c'])
5
+ class Condition
6
+ # @yield [value] generated value
7
+ # @yieldreturn [Boolean] matched?
8
+ def initialize(&condition)
9
+ @condition = condition
10
+ end
11
+
12
+ # @param [Object] n any value
13
+ # @return [Boolean] condition matched
14
+ def match?(n)
15
+ @condition.call(n)
16
+ end
17
+
18
+ # @visibility private
19
+ # @macro def_not
20
+ # @method not_$1
21
+ # not $1
22
+ # @param (see QueenCheck::Condition.$1)
23
+ # @scope class
24
+ # @visibility public
25
+ # @return [QueenCheck::Condition]
26
+ # @see QueenCheck::Condition.$1
27
+ def self.def_not(method_name)
28
+ not_proc = proc { | *args |
29
+ cond = self.method(method_name).call(*args)
30
+ class << cond
31
+ def match?(n)
32
+ !@condition.call(n)
33
+ end
34
+ end
35
+
36
+ return cond
37
+ }
38
+
39
+ (class << self; self; end).instance_eval do
40
+ define_method('not_' + method_name.to_s, &not_proc)
41
+ end
42
+ end
43
+
44
+ # check value in ary
45
+ #
46
+ # @param [Array] ary
47
+ # @return [QueenCheck::Condition]
48
+ def self.include?(ary)
49
+ new { |n|
50
+ ary.include?(n)
51
+ }
52
+ end
53
+ def_not :include?
54
+
55
+ # check instance of klass
56
+ # @param [Class] klass
57
+ # @return [QueenCheck::Condition]
58
+ def self.instance_of?(klass)
59
+ new { |n|
60
+ n.instance_of?(klass)
61
+ }
62
+ end
63
+ def_not :instance_of?
64
+
65
+ # check respond to method
66
+ # @param [Symbol, String] method method name
67
+ # @return [QueenCheck::Condition]
68
+ def self.respond_to?(method)
69
+ new { |n|
70
+ n.respond_to?(method)
71
+ }
72
+ end
73
+ def_not :respond_to?
74
+
75
+ # check nil
76
+ # @return [QueenCheck::Condition]
77
+ def self.nil?()
78
+ new { |n|
79
+ n.nil?
80
+ }
81
+ end
82
+ def_not :nil?
83
+
84
+ # check empty
85
+ # @return [QueenCheck::Condition]
86
+ def self.empty?()
87
+ new { |n|
88
+ n.empty?
89
+ }
90
+ end
91
+ def_not :empty?
92
+
93
+ # check equal m
94
+ # @param [Object] m
95
+ # @return [QueenCheck::Condition]
96
+ def self.equal?(m)
97
+ new { |n|
98
+ n == m
99
+ }
100
+ end
101
+ def_not :equal?
102
+
103
+ # check orderd array
104
+ # @return [QueenCheck::Condition]
105
+ def self.orderd?
106
+ new { |n|
107
+ n.sort == n
108
+ }
109
+ end
110
+ def_not :orderd?
111
+ end
112
+ end