covenant 0.6.0 → 0.7.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.
Files changed (3) hide show
  1. data/lib/covenant/version.rb +1 -1
  2. data/lib/covenant.rb +48 -130
  3. metadata +15 -4
@@ -1,3 +1,3 @@
1
1
  module Covenant
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
data/lib/covenant.rb CHANGED
@@ -1,15 +1,27 @@
1
+ require 'sourcify'
2
+
1
3
  module Covenant
2
4
  # Adds the Covenant DSL to base.
3
5
  #
4
6
  # @api public
5
7
  #
6
8
  # @param base where to add the Covenant DSL
7
- def self.abide(base = Object)
8
- case base
9
- when Class
10
- base.send :include, Covenant::DSL
11
- else
12
- base.extend Covenant::DSL
9
+ def self.abide(base = Object, as = [:assert, :asserting])
10
+ target = Class === base ? base : base.singleton_class
11
+
12
+ target.class_eval do
13
+ include Covenant::DSL
14
+
15
+ case as
16
+ when Array
17
+ as.each do |a|
18
+ alias_method a, :_assert
19
+ end
20
+ when Symbol, String
21
+ alias_method as, :_assert
22
+ else
23
+ raise ArgumentError, "cannot register `#{as.inspect}` as method names"
24
+ end
13
25
  end
14
26
  end
15
27
 
@@ -22,151 +34,57 @@ module Covenant
22
34
  # @param [#to_s] message the message that will be set if the test fails
23
35
  #
24
36
  # @return the wrapper object you can use to test your assertions
25
- def assert(target = self, message = nil)
26
- if block_given?
27
- Covenant::Assertion.new(target, message).test(yield target)
28
- else
29
- Covenant::Assertion.new(target, message)
30
- end
31
- end
32
-
33
- alias_method :asserting, :assert
37
+ def _assert(&block)
38
+ raise ArgumentError, "no block given" unless block_given?
34
39
 
35
- # Ensures that the condition on target evaluates to a false value.
36
- #
37
- # @api public
38
- #
39
- # @param target the target on which to test the condition
40
- # @param message the message that will be set if the test fails
41
- #
42
- # @return the wrapper object you can use to test your assertions
43
- def deny(target = self, message = nil)
44
- if block_given?
45
- Covenant::Denial.new(target, message).test(yield target)
46
- else
47
- Covenant::Denial.new(target, message)
48
- end
40
+ tap { yield self or raise AssertionFailed, ErrorMessage.new(block) }
49
41
  end
50
-
51
- alias_method :denying, :deny
52
42
  end
53
43
 
54
- class AssertionFailed < Exception; end
44
+ class AssertionFailed < StandardError; end
55
45
 
56
- class Statement < BasicObject
57
- def initialize(target, message)
58
- @target = target
59
- @message = message
46
+ class ErrorMessage
47
+ def initialize(block)
48
+ @block = block
60
49
  end
61
50
 
62
- def ==(other)
63
- test(target == other, ErrorMessage.new(target, :==, [other]))
51
+ def to_s
52
+ "block did not return true:\n\n#{source_block}\n\n#{variable_block}"
64
53
  end
65
54
 
66
- def !=(other)
67
- test(target != other, ErrorMessage.new(target, :!=, [other]))
68
- end
55
+ private
69
56
 
70
- def method_missing(name, *args)
71
- if target.respond_to?(name)
72
- return test(target.send(name, *args),
73
- ErrorMessage.new(target, name, args))
74
- end
75
-
76
- query = "#{name}?"
57
+ attr_reader :block
77
58
 
78
- if target.respond_to?(query)
79
- return test(target.send(query, *args),
80
- ErrorMessage.new(target, query, args))
81
- end
82
-
83
- no_is = name.to_s.sub(/^is_/, '')
84
- is_query = "#{no_is}?"
85
-
86
- if target.respond_to?(is_query)
87
- return test(target.send(is_query, *args),
88
- ErrorMessage.new(target, is_query, args))
89
- end
90
-
91
- super
59
+ def indent(str)
60
+ " " + str.gsub(/\n/, "\n ").strip
92
61
  end
93
62
 
94
- protected
95
-
96
- attr_reader :target, :message
97
-
98
- def raise_error(message)
99
- msg = self.message || message
100
-
101
- if msg
102
- ::Kernel.raise AssertionFailed, msg
103
- else
104
- ::Kernel.raise AssertionFailed
105
- end
63
+ def source
64
+ block.to_source
106
65
  end
107
66
 
108
- class NullErrorMessage
109
- def for_assertion; end
110
- def for_denial; end
67
+ def source_block
68
+ "Source:\n\n#{indent(source)}"
111
69
  end
112
70
 
113
- class ErrorMessage
114
- attr_reader :target, :message, :args
115
-
116
- def initialize(target, message, args)
117
- @target = target
118
- @message = message
119
- @args = args
120
- end
121
-
122
- def for_assertion
123
- error_message('should be true')
124
- end
71
+ def variable_block
72
+ b = variables.
73
+ inject("") { |a, (var, val)|
74
+ a << "#{var} = #{val.inspect}\n"
75
+ }
125
76
 
126
- def for_denial
127
- error_message('should be false')
128
- end
129
-
130
- private
131
-
132
- def error_message(expected)
133
- argl = args.map(&:inspect).join(", ")
134
-
135
- "#{target.inspect}.#{message} #{argl} #{expected}"
136
- end
77
+ "Variables:\n\n" + indent(b)
137
78
  end
138
- end
139
79
 
140
- class Assertion < Statement
141
- def test(condition, error_message = NullErrorMessage.new)
142
- if condition
143
- target
144
- else
145
- raise_error error_message.for_assertion
146
- end
147
- end
148
- end
80
+ def variables
81
+ s = source
82
+ b = block.binding
83
+ lv = b.eval('local_variables')
149
84
 
150
- class Denial < Statement
151
- def test(condition, error_message = NullErrorMessage.new)
152
- if ! condition
153
- target
154
- else
155
- raise_error error_message.for_denial
156
- end
85
+ lv.
86
+ select { |v| s =~ /\b#{v}\b/ }.
87
+ map { |v| [v, b.eval(v.to_s)] }
157
88
  end
158
89
  end
159
90
  end
160
-
161
- =begin
162
-
163
- require 'benchmark'
164
-
165
- Covenant.abide self
166
-
167
- Benchmark.bm do |x|
168
- x.report { 1_000_000.times { assert('aaa').start_with 'a' } }
169
- x.report { 1_000_000.times { 'aaa'.start_with? 'a' } }
170
- end
171
-
172
- =end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: covenant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-03 00:00:00.000000000 Z
12
+ date: 2013-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sourcify
16
+ requirement: &84448700 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.6.0.pre
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *84448700
14
25
  - !ruby/object:Gem::Dependency
15
26
  name: rspec
16
- requirement: &86482920 !ruby/object:Gem::Requirement
27
+ requirement: &84448470 !ruby/object:Gem::Requirement
17
28
  none: false
18
29
  requirements:
19
30
  - - ! '>='
@@ -21,7 +32,7 @@ dependencies:
21
32
  version: '2.11'
22
33
  type: :development
23
34
  prerelease: false
24
- version_requirements: *86482920
35
+ version_requirements: *84448470
25
36
  description:
26
37
  email:
27
38
  - gems@mojotech.com