must 0.2.2 → 0.2.3
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/README +17 -4
- data/lib/must/rule.rb +27 -1
- data/lib/must/version.rb +3 -0
- data/lib/must.rb +3 -1
- data/must.gemspec +22 -0
- data/test/coerced_test.rb +39 -0
- data/test/duck_test.rb +83 -0
- data/test/match_test.rb +15 -0
- data/test/must_test.rb +0 -50
- metadata +13 -8
- data/tasks/expectation_tasks.rake +0 -4
data/README
CHANGED
|
@@ -10,9 +10,14 @@ add Object#must method to constrain its origin and conversions
|
|
|
10
10
|
num = params[:num].to_i
|
|
11
11
|
num = 10 unless (1..300) === num
|
|
12
12
|
|
|
13
|
+
and has duck features
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
1.must.duck?(:to_s) # => true
|
|
16
|
+
io.must.duck(:write) { io.extend Writable }
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Asking Methods
|
|
20
|
+
==============
|
|
16
21
|
|
|
17
22
|
be : check whether object equals to the argument
|
|
18
23
|
kind_of : check whether object is a kind of the arguments
|
|
@@ -36,6 +41,15 @@ an : return self
|
|
|
36
41
|
These effect nothing but exist only for English grammar.
|
|
37
42
|
|
|
38
43
|
|
|
44
|
+
Duck Methods
|
|
45
|
+
============
|
|
46
|
+
duck("foo") : check whether object responds to "foo" method.
|
|
47
|
+
duck(:foo) : same above
|
|
48
|
+
duck(".foo") : same above
|
|
49
|
+
duck("#foo") : check whether object has "foo" instance method. (tested only in class/module)
|
|
50
|
+
duck?(...) : acts same as "duck", but this returns a just boolean
|
|
51
|
+
|
|
52
|
+
|
|
39
53
|
Basic Examples
|
|
40
54
|
==============
|
|
41
55
|
|
|
@@ -114,8 +128,7 @@ Actual Examples
|
|
|
114
128
|
Install
|
|
115
129
|
=======
|
|
116
130
|
|
|
117
|
-
gem install
|
|
118
|
-
# add source http://gems.github.com
|
|
131
|
+
gem install must
|
|
119
132
|
|
|
120
133
|
% irb -r rubygems -r must
|
|
121
134
|
irb(main):001:0> 1.must.be 1
|
data/lib/must/rule.rb
CHANGED
|
@@ -48,6 +48,7 @@ module Must
|
|
|
48
48
|
def one_of(target, &block)
|
|
49
49
|
valid?(target === @object, &block)
|
|
50
50
|
end
|
|
51
|
+
alias :match :one_of
|
|
51
52
|
|
|
52
53
|
def valid?(condition, &block)
|
|
53
54
|
if condition ^ @not
|
|
@@ -81,6 +82,31 @@ module Must
|
|
|
81
82
|
retry
|
|
82
83
|
end
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
def duck(method_name, &block)
|
|
86
|
+
valid?(duck?(method_name), &block)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def duck?(method_name)
|
|
90
|
+
case method_name.to_s
|
|
91
|
+
when /^\./ then method_defined?($')
|
|
92
|
+
when /^#/ then instance_method_defined?($')
|
|
93
|
+
else ; method_defined?(method_name)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
def instance?
|
|
99
|
+
@object.class.to_s !~ /\A(Class|Module)\Z/o
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def instance_method_defined?(method_name)
|
|
103
|
+
return false if instance?
|
|
104
|
+
!! @object.instance_methods.find { |m| m.to_s == method_name.to_s}
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def method_defined?(method_name)
|
|
108
|
+
@object.respond_to?(method_name)
|
|
109
|
+
end
|
|
110
|
+
|
|
85
111
|
end
|
|
86
112
|
end
|
data/lib/must/version.rb
ADDED
data/lib/must.rb
CHANGED
data/must.gemspec
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "must/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "must"
|
|
7
|
+
s.version = Must::VERSION
|
|
8
|
+
s.authors = ["maiha"]
|
|
9
|
+
s.email = ["maiha@wota.jp"]
|
|
10
|
+
s.homepage = "http://github.com/maiha/must"
|
|
11
|
+
s.summary = %q{a runtime specification tool}
|
|
12
|
+
s.description = %q{add Object#must method to constrain its origin and conversions}
|
|
13
|
+
|
|
14
|
+
s.files = `git ls-files`.split("\n")
|
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
17
|
+
s.require_paths = ["lib"]
|
|
18
|
+
|
|
19
|
+
# specify any dependencies here; for example:
|
|
20
|
+
# s.add_development_dependency "rspec"
|
|
21
|
+
# s.add_runtime_dependency "rest-client"
|
|
22
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require File.join(File.dirname(__FILE__), '../init')
|
|
4
|
+
|
|
5
|
+
class CoercedTest < Test::Unit::TestCase
|
|
6
|
+
def test_is_a_feature
|
|
7
|
+
assert_equal 1, 1.must.be.coerced(Integer)
|
|
8
|
+
assert_equal 1, 1.must.be.coerced(Integer, String)
|
|
9
|
+
assert_equal 1, 1.must.be.coerced(String, Numeric)
|
|
10
|
+
|
|
11
|
+
assert_raises(Invalid) { "1".must.be.coerced(Integer) }
|
|
12
|
+
assert_raises(Invalid) { "1".must.be.coerced(Integer, Range) }
|
|
13
|
+
assert_raises(NotImplementedError) { "1".must.be.coerced(Integer){raise NotImplementedError} }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_coecing_succeeded
|
|
17
|
+
assert_equal 1, 1.must.be.coerced(Integer, String=>proc{|i|i.to_i})
|
|
18
|
+
assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i})
|
|
19
|
+
assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
|
20
|
+
assert_equal 1, "1".must.be.coerced(Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
|
21
|
+
assert_equal 1, "1".must.be.coerced(File, Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_coecing_failed
|
|
25
|
+
assert_raises(Invalid) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) }
|
|
26
|
+
assert_raises(NotImplementedError) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}){raise NotImplementedError} }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_cascaded_coecing_succeeded
|
|
30
|
+
assert_equal 1, 1.must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
|
31
|
+
assert_equal 1, "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
|
32
|
+
assert_equal 1, :"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_detect_livelock
|
|
36
|
+
assert_raises(Invalid){ "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
|
|
37
|
+
assert_raises(Invalid){:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
|
|
38
|
+
end
|
|
39
|
+
end
|
data/test/duck_test.rb
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require File.join(File.dirname(__FILE__), '../init')
|
|
4
|
+
|
|
5
|
+
class DuckTest < Test::Unit::TestCase
|
|
6
|
+
class ClassFoo
|
|
7
|
+
def foo; 1; end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ModuleFoo
|
|
11
|
+
def foo; 1; end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_itself_duck_type
|
|
15
|
+
# succeeded
|
|
16
|
+
assert_equal 1, 1.must.duck(:to_s)
|
|
17
|
+
assert_equal 1, 1.must.duck("to_s")
|
|
18
|
+
assert_equal 1, 1.must.duck(".to_s")
|
|
19
|
+
assert_equal ClassFoo, ClassFoo.must.duck(:to_s)
|
|
20
|
+
assert_equal ClassFoo, ClassFoo.must.duck("to_s")
|
|
21
|
+
assert_equal ClassFoo, ClassFoo.must.duck(".to_s")
|
|
22
|
+
assert_equal ModuleFoo, ModuleFoo.must.duck(:to_s)
|
|
23
|
+
assert_equal ModuleFoo, ModuleFoo.must.duck("to_s")
|
|
24
|
+
assert_equal ModuleFoo, ModuleFoo.must.duck(".to_s")
|
|
25
|
+
|
|
26
|
+
# failed
|
|
27
|
+
assert_raises(Invalid) { 1.must.duck(:foo) }
|
|
28
|
+
assert_raises(Invalid) { 1.must.duck("foo") }
|
|
29
|
+
assert_raises(Invalid) { 1.must.duck(".foo") }
|
|
30
|
+
assert_raises(Invalid) { ClassFoo.must.duck(:foo) }
|
|
31
|
+
assert_raises(Invalid) { ClassFoo.must.duck("foo") }
|
|
32
|
+
assert_raises(Invalid) { ClassFoo.must.duck(".foo") }
|
|
33
|
+
assert_raises(Invalid) { ModuleFoo.must.duck(:foo) }
|
|
34
|
+
assert_raises(Invalid) { ModuleFoo.must.duck("foo") }
|
|
35
|
+
assert_raises(Invalid) { ModuleFoo.must.duck(".foo") }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_instance_duck_type
|
|
39
|
+
# succeeded
|
|
40
|
+
assert_equal ClassFoo, ClassFoo.must.duck("#foo")
|
|
41
|
+
assert_equal ModuleFoo, ModuleFoo.must.duck("#foo")
|
|
42
|
+
|
|
43
|
+
# failed
|
|
44
|
+
assert_raises(Invalid) { 1.must.duck("#bar") } # instance object
|
|
45
|
+
assert_raises(Invalid) { ClassFoo.must.duck("#bar") }
|
|
46
|
+
assert_raises(Invalid) { ModuleFoo.must.duck("#bar") }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_itself_duck_test
|
|
50
|
+
# succeeded
|
|
51
|
+
assert_equal true, 1.must.duck?(:to_s)
|
|
52
|
+
assert_equal true, 1.must.duck?("to_s")
|
|
53
|
+
assert_equal true, 1.must.duck?(".to_s")
|
|
54
|
+
assert_equal true, ClassFoo.must.duck?(:to_s)
|
|
55
|
+
assert_equal true, ClassFoo.must.duck?("to_s")
|
|
56
|
+
assert_equal true, ClassFoo.must.duck?(".to_s")
|
|
57
|
+
assert_equal true, ModuleFoo.must.duck?(:to_s)
|
|
58
|
+
assert_equal true, ModuleFoo.must.duck?("to_s")
|
|
59
|
+
assert_equal true, ModuleFoo.must.duck?(".to_s")
|
|
60
|
+
|
|
61
|
+
# failed
|
|
62
|
+
assert_equal false, 1.must.duck?(:foo)
|
|
63
|
+
assert_equal false, 1.must.duck?("foo")
|
|
64
|
+
assert_equal false, 1.must.duck?(".foo")
|
|
65
|
+
assert_equal false, ClassFoo.must.duck?(:foo)
|
|
66
|
+
assert_equal false, ClassFoo.must.duck?("foo")
|
|
67
|
+
assert_equal false, ClassFoo.must.duck?(".foo")
|
|
68
|
+
assert_equal false, ModuleFoo.must.duck?(:foo)
|
|
69
|
+
assert_equal false, ModuleFoo.must.duck?("foo")
|
|
70
|
+
assert_equal false, ModuleFoo.must.duck?(".foo")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_instance_duck_test
|
|
74
|
+
# succeeded
|
|
75
|
+
assert_equal true, ClassFoo.must.duck?("#foo")
|
|
76
|
+
assert_equal true, ModuleFoo.must.duck?("#foo")
|
|
77
|
+
|
|
78
|
+
# failed
|
|
79
|
+
assert_equal false, 1.must.duck?("#bar") # instance object
|
|
80
|
+
assert_equal false, ClassFoo.must.duck?("#bar")
|
|
81
|
+
assert_equal false, ModuleFoo.must.duck?("#bar")
|
|
82
|
+
end
|
|
83
|
+
end
|
data/test/match_test.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require File.join(File.dirname(__FILE__), '../init')
|
|
4
|
+
|
|
5
|
+
class MatchTest < Test::Unit::TestCase
|
|
6
|
+
def test_match_range
|
|
7
|
+
# succeeded
|
|
8
|
+
assert_equal 1, 1.must.match(0..3)
|
|
9
|
+
assert_equal 'b', 'b'.must.match('a'..'c')
|
|
10
|
+
|
|
11
|
+
# failed
|
|
12
|
+
assert_raises(Invalid) { 1.must.match(2..3) }
|
|
13
|
+
assert_raises(Invalid) { 'a'.must.match('y'..'z') }
|
|
14
|
+
end
|
|
15
|
+
end
|
data/test/must_test.rb
CHANGED
|
@@ -35,53 +35,3 @@ class MustTest < Test::Unit::TestCase
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
class CoercedTest < Test::Unit::TestCase
|
|
40
|
-
def test_is_a_feature
|
|
41
|
-
assert_equal 1, 1.must.be.coerced(Integer)
|
|
42
|
-
assert_equal 1, 1.must.be.coerced(Integer, String)
|
|
43
|
-
assert_equal 1, 1.must.be.coerced(String, Numeric)
|
|
44
|
-
|
|
45
|
-
assert_raises(Invalid) { "1".must.be.coerced(Integer) }
|
|
46
|
-
assert_raises(Invalid) { "1".must.be.coerced(Integer, Range) }
|
|
47
|
-
assert_raises(NotImplementedError) { "1".must.be.coerced(Integer){raise NotImplementedError} }
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def test_coecing_succeeded
|
|
51
|
-
assert_equal 1, 1.must.be.coerced(Integer, String=>proc{|i|i.to_i})
|
|
52
|
-
assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i})
|
|
53
|
-
assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
|
54
|
-
assert_equal 1, "1".must.be.coerced(Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
|
55
|
-
assert_equal 1, "1".must.be.coerced(File, Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def test_coecing_failed
|
|
59
|
-
assert_raises(Invalid) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) }
|
|
60
|
-
assert_raises(NotImplementedError) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}){raise NotImplementedError} }
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def test_cascaded_coecing_succeeded
|
|
64
|
-
assert_equal 1, 1.must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
|
65
|
-
assert_equal 1, "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
|
66
|
-
assert_equal 1, :"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def test_detect_livelock
|
|
70
|
-
assert_raises(Invalid){ "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
|
|
71
|
-
assert_raises(Invalid){:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class MatchTest < Test::Unit::TestCase
|
|
78
|
-
def test_match_range
|
|
79
|
-
# succeeded
|
|
80
|
-
assert_equal 1, 1.must.match(0..3)
|
|
81
|
-
assert_equal 'b', 'b'.must.match('a'..'c')
|
|
82
|
-
|
|
83
|
-
# failed
|
|
84
|
-
assert_raises(Invalid) { 1.must.match(2..3) }
|
|
85
|
-
assert_raises(Invalid) { 'a'.must.match('y'..'z') }
|
|
86
|
-
end
|
|
87
|
-
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: must
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 17
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 2
|
|
9
|
-
-
|
|
10
|
-
version: 0.2.
|
|
9
|
+
- 3
|
|
10
|
+
version: 0.2.3
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- maiha
|
|
@@ -15,12 +15,13 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2012-01-
|
|
18
|
+
date: 2012-01-26 00:00:00 +09:00
|
|
19
19
|
default_executable:
|
|
20
20
|
dependencies: []
|
|
21
21
|
|
|
22
|
-
description:
|
|
23
|
-
email:
|
|
22
|
+
description: add Object#must method to constrain its origin and conversions
|
|
23
|
+
email:
|
|
24
|
+
- maiha@wota.jp
|
|
24
25
|
executables: []
|
|
25
26
|
|
|
26
27
|
extensions: []
|
|
@@ -34,7 +35,11 @@ files:
|
|
|
34
35
|
- install.rb
|
|
35
36
|
- lib/must.rb
|
|
36
37
|
- lib/must/rule.rb
|
|
37
|
-
-
|
|
38
|
+
- lib/must/version.rb
|
|
39
|
+
- must.gemspec
|
|
40
|
+
- test/coerced_test.rb
|
|
41
|
+
- test/duck_test.rb
|
|
42
|
+
- test/match_test.rb
|
|
38
43
|
- test/must_test.rb
|
|
39
44
|
has_rdoc: true
|
|
40
45
|
homepage: http://github.com/maiha/must
|
|
@@ -69,6 +74,6 @@ rubyforge_project:
|
|
|
69
74
|
rubygems_version: 1.3.7
|
|
70
75
|
signing_key:
|
|
71
76
|
specification_version: 3
|
|
72
|
-
summary:
|
|
77
|
+
summary: a runtime specification tool
|
|
73
78
|
test_files: []
|
|
74
79
|
|