queencheck 0.1.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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