assay 0.3.0 → 0.4.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/.ruby +46 -41
- data/COPYING.rdoc +38 -0
- data/HISTORY.rdoc +18 -1
- data/QED.rdoc +1100 -0
- data/README.rdoc +139 -16
- data/lib/assay.rb +82 -29
- data/lib/assay.yml +46 -41
- data/lib/assay/{adapters → adapter}/minitest.rb +0 -0
- data/lib/assay/{adapters → adapter}/testunit.rb +0 -0
- data/lib/assay/assertable.rb +174 -0
- data/lib/assay/assertion.rb +98 -124
- data/lib/assay/assertor.rb +187 -0
- data/lib/assay/boolean_assay.rb +15 -0
- data/lib/assay/case_assay.rb +17 -0
- data/lib/assay/compare_assay.rb +38 -0
- data/lib/assay/core_ext/kernel.rb +52 -0
- data/lib/assay/core_ext/na.rb +9 -0
- data/lib/assay/directory_assay.rb +20 -0
- data/lib/assay/empty_assay.rb +17 -0
- data/lib/assay/equal_assay.rb +35 -0
- data/lib/assay/equality_assay.rb +18 -0
- data/lib/assay/execution_assay.rb +59 -0
- data/lib/assay/false_assay.rb +17 -0
- data/lib/assay/file_assay.rb +17 -0
- data/lib/assay/identity_assay.rb +49 -0
- data/lib/assay/include_assay.rb +17 -0
- data/lib/assay/instance_assay.rb +17 -0
- data/lib/assay/kind_assay.rb +18 -0
- data/lib/assay/less_assay.rb +18 -0
- data/lib/assay/less_equal_assay.rb +25 -0
- data/lib/assay/like_assay.rb +17 -0
- data/lib/assay/match_assay.rb +17 -0
- data/lib/assay/more_assay.rb +18 -0
- data/lib/assay/more_equal_assay.rb +25 -0
- data/lib/assay/nil_assay.rb +15 -0
- data/lib/assay/nomatch_assay.rb +17 -0
- data/lib/assay/output_assay.rb +35 -0
- data/lib/assay/path_assay.rb +17 -0
- data/lib/assay/raise_assay.rb +109 -0
- data/lib/assay/rescue_assay.rb +55 -0
- data/lib/assay/respond_assay.rb +17 -0
- data/lib/assay/return_assay.rb +46 -0
- data/lib/assay/silent_assay.rb +59 -0
- data/lib/assay/stderr_assay.rb +30 -0
- data/lib/assay/stdout_assay.rb +30 -0
- data/lib/assay/throw_assay.rb +89 -0
- data/lib/assay/true_assay.rb +20 -0
- data/lib/assay/unequal_assay.rb +37 -0
- data/lib/assay/within_assay.rb +39 -0
- data/test/case_compare_assay.rb +59 -0
- data/test/case_empty_assay.rb +51 -0
- data/test/case_equal_assay.rb +53 -0
- data/test/case_equality_assay.rb +55 -0
- data/test/case_false_assay.rb +48 -0
- data/test/case_identity_assay.rb +51 -0
- data/test/case_include_assay.rb +51 -0
- data/test/case_instance_assay.rb +51 -0
- data/test/case_kind_assay.rb +51 -0
- data/test/case_less_assay.rb +53 -0
- data/test/case_less_equal_assay.rb +53 -0
- data/test/case_like_assay.rb +57 -0
- data/test/case_match_assay.rb +45 -0
- data/test/case_more_assay.rb +53 -0
- data/test/case_more_equal_assay.rb +53 -0
- data/test/case_nil_assay.rb +48 -0
- data/test/case_nomatch_assay.rb +47 -0
- data/test/case_raise_assay.rb +51 -0
- data/test/case_respond_assay.rb +51 -0
- data/test/case_throw_assay.rb +51 -0
- data/test/case_true_assay.rb +48 -0
- data/test/case_unequal_assay.rb +55 -0
- data/test/case_within_assay.rb +61 -0
- data/test/helper.rb +36 -0
- metadata +135 -108
- data/APACHE2.txt +0 -205
- data/NOTICE.rdoc +0 -18
- data/lib/assay/assertions/compare_failure.rb +0 -61
- data/lib/assay/assertions/delta_failure.rb +0 -80
- data/lib/assay/assertions/empty_failure.rb +0 -76
- data/lib/assay/assertions/equality_failure.rb +0 -100
- data/lib/assay/assertions/execution_failure.rb +0 -90
- data/lib/assay/assertions/false_failure.rb +0 -72
- data/lib/assay/assertions/identity_failure.rb +0 -85
- data/lib/assay/assertions/instance_failure.rb +0 -76
- data/lib/assay/assertions/kind_failure.rb +0 -80
- data/lib/assay/assertions/match_failure.rb +0 -85
- data/lib/assay/assertions/nil_failure.rb +0 -75
- data/lib/assay/assertions/raise_failure.rb +0 -134
- data/lib/assay/assertions/response_failure.rb +0 -86
- data/lib/assay/assertions/same_failure.rb +0 -82
- data/lib/assay/assertions/throw_failure.rb +0 -122
- data/lib/assay/assertions/true_failure.rb +0 -79
- data/lib/assay/matcher.rb +0 -48
- data/qed/01_failure_classes.rdoc +0 -75
- data/qed/02_assertives.rdoc +0 -118
- data/qed/03_matchers.rdoc +0 -118
- data/qed/04_lookup.rdoc +0 -10
data/lib/assay/assertion.rb
CHANGED
@@ -1,149 +1,123 @@
|
|
1
|
-
require '
|
2
|
-
require 'assay/matcher'
|
1
|
+
require 'brass'
|
3
2
|
|
4
|
-
|
3
|
+
require_relative 'core_ext/na'
|
4
|
+
require_relative 'core_ext/kernel'
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
require_relative 'assertor'
|
7
|
+
require_relative 'assertable'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
# big for a single line message.
|
12
|
-
SIZE_LIMIT = 13
|
9
|
+
# TODO: Don't care for Proc === subject conditional code, but not
|
10
|
+
# sure how else to deal with lambda subjects.
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
# Base class for all Assay classes. This class defines all the logic
|
13
|
+
# for assertions as exception classes as well as test assertion matchers.
|
14
|
+
#
|
15
|
+
class Assertion < Exception
|
18
16
|
|
19
|
-
|
20
|
-
def self.assertable_method
|
21
|
-
"assert_#{assertion_name}"
|
22
|
-
end
|
17
|
+
extend Assay::Assertable
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
err = new(message, *args, &blk)
|
32
|
-
err.set_backtrace(backtrace)
|
33
|
-
err.assert
|
34
|
-
|
35
|
-
#chk = check(*args, &blk)
|
36
|
-
#msg = fail_message(*args, &blk)
|
37
|
-
#if !chk
|
38
|
-
# msg = opts[:message]
|
39
|
-
# btr = opts[:backtrace] || caller
|
40
|
-
# err = new(msg, *args)
|
41
|
-
# err.set_backtrace(btr)
|
42
|
-
# fail err
|
43
|
-
#end
|
44
|
-
end
|
19
|
+
#
|
20
|
+
# When displaying errors, use this as a rule of thumb
|
21
|
+
# for determining when the inspected object will be too
|
22
|
+
# big for a single line message.
|
23
|
+
#
|
24
|
+
SIZE_LIMIT = 13
|
45
25
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
#end
|
66
|
-
end
|
26
|
+
#
|
27
|
+
# Each new subclass must call the +register+ method. This is not an option!
|
28
|
+
# The method must be called in order to add the class to the Assertion
|
29
|
+
# name and operator indicies, so they might be looked-up efficiently by
|
30
|
+
# other libraries.
|
31
|
+
#
|
32
|
+
def self.register(op, name=nil)
|
33
|
+
case op.to_s
|
34
|
+
when /\W/
|
35
|
+
@operator = op.to_sym
|
36
|
+
@assertive_name = name.to_sym if name
|
37
|
+
else
|
38
|
+
@operator = (op.to_s + '?').to_sym
|
39
|
+
@assertive_name = op.to_sym
|
40
|
+
end
|
41
|
+
|
42
|
+
operator_index[operator] = self
|
43
|
+
name_index[assertive_name] = self
|
44
|
+
end
|
67
45
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
46
|
+
#
|
47
|
+
# When Assertion is inherited, a list of all Assertion subclasses is kept.
|
48
|
+
# This can be used to assertions frameworks with dynamic implementations.
|
49
|
+
#
|
50
|
+
def self.inherited(base)
|
51
|
+
@@by_operator = nil
|
52
|
+
@@by_name = nil
|
53
|
+
subclasses << base
|
54
|
+
end
|
72
55
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
56
|
+
#
|
57
|
+
# List of all subclasses of Assertion.
|
58
|
+
#
|
59
|
+
def self.subclasses
|
60
|
+
@@subclasses ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# If operator is not given, returns a hash table of assertion classes
|
65
|
+
# indexed by operator.
|
66
|
+
#
|
67
|
+
def self.by_operator(operator=nil)
|
68
|
+
return operator_index.dup unless operator
|
69
|
+
operator_index[operator.to_sym]
|
70
|
+
end
|
77
71
|
|
78
|
-
|
79
|
-
|
80
|
-
|
72
|
+
#
|
73
|
+
# If operator is not given, returns a hash table of assertion classes
|
74
|
+
# indexed by assertive name.
|
75
|
+
#
|
76
|
+
def self.by_name(name=nil)
|
77
|
+
return name_index.dup unless name
|
78
|
+
name_index[name.to_sym]
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
@arguments = arguments
|
84
|
-
@block = block
|
81
|
+
private
|
85
82
|
|
86
|
-
|
87
|
-
|
88
|
-
#set_backtrace options[:backtrace] if options[:backtrace]
|
83
|
+
def self.operator_index
|
84
|
+
@@operator_index ||= {}
|
89
85
|
end
|
90
86
|
|
91
|
-
|
92
|
-
|
93
|
-
# This method allows Assay's classes to work in any test framework
|
94
|
-
# that supports this interface.
|
95
|
-
def assertion?
|
96
|
-
true # @assertion = true if @assertion.nil?
|
87
|
+
def self.name_index
|
88
|
+
@@name_index ||= {}
|
97
89
|
end
|
98
90
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
91
|
+
#
|
92
|
+
# Setup new Assertion object.
|
93
|
+
#
|
94
|
+
def initialize(msg=nil) #, *criteria, &block)
|
95
|
+
super(msg)
|
103
96
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
97
|
+
#@criteria = criteria
|
98
|
+
#@block = block
|
99
|
+
#@not = false
|
108
100
|
|
109
|
-
|
110
|
-
def assert
|
111
|
-
#@negative = false
|
112
|
-
raise self unless pass?
|
113
|
-
end
|
101
|
+
@assertion = true
|
114
102
|
|
115
|
-
#
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
end
|
103
|
+
#options = (Hash === criteria.last ? criteria.pop : {})
|
104
|
+
#set_backtrace(options[:backtrace]) if options[:backtrace]
|
105
|
+
#set_negative(options[:negated]) if options[:negated]
|
106
|
+
end
|
120
107
|
|
121
|
-
|
122
|
-
def negative?
|
123
|
-
@negative
|
124
|
-
end
|
108
|
+
end
|
125
109
|
|
126
|
-
# Set whether this failure was the inverse of it's normal meaning.
|
127
|
-
# For example, `!=` rather than `==`.
|
128
|
-
def set_negative(negative)
|
129
|
-
@negative = !!negative
|
130
|
-
end
|
131
110
|
|
132
|
-
|
133
|
-
def set_arguments(arguments)
|
134
|
-
@arguments = arguments
|
135
|
-
#@block = block
|
136
|
-
end
|
111
|
+
=begin
|
137
112
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
113
|
+
#
|
114
|
+
#def to_s
|
115
|
+
# #if @negative
|
116
|
+
# # "NOT " + super()
|
117
|
+
# #else
|
118
|
+
# super()
|
119
|
+
# #end
|
120
|
+
#end
|
146
121
|
|
147
|
-
|
122
|
+
=end
|
148
123
|
|
149
|
-
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
module Assay
|
2
|
+
|
3
|
+
# Assertor delegates to Assay class. It provides an object-oriented
|
4
|
+
# interface to makeing assertions, as opposed to the functional
|
5
|
+
# interface of the Assay classes themselves.
|
6
|
+
#
|
7
|
+
class Assertor
|
8
|
+
|
9
|
+
#
|
10
|
+
#
|
11
|
+
def initialize(assay_class, *criteria, &block)
|
12
|
+
@assay = assay_class
|
13
|
+
@criteria = criteria
|
14
|
+
@block = block
|
15
|
+
@not = false
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# The assay class to which this assertor delegates.
|
20
|
+
#
|
21
|
+
attr :assay
|
22
|
+
|
23
|
+
#
|
24
|
+
# The criteria for applying the assertor.
|
25
|
+
#
|
26
|
+
attr :criteria
|
27
|
+
|
28
|
+
#
|
29
|
+
# Block criterion.
|
30
|
+
#
|
31
|
+
attr :block
|
32
|
+
|
33
|
+
#
|
34
|
+
# Is the assertor negated?
|
35
|
+
#
|
36
|
+
def not?
|
37
|
+
@not
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
#
|
42
|
+
def pass?(subject, &block)
|
43
|
+
arguments, block = complete_criteria(subject, &block)
|
44
|
+
@not ^ @assay.pass?(*arguments, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
#
|
49
|
+
def fail?(subject, &block)
|
50
|
+
arguments, block = complete_criteria(subject, &block)
|
51
|
+
@not ^ @assay.fail?(*arguments, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
#
|
56
|
+
def assert!(subject, &block)
|
57
|
+
# technically this needs to be controlled by the assay class
|
58
|
+
if block.nil? && Proc === subject
|
59
|
+
block = subject
|
60
|
+
subject = NA
|
61
|
+
end
|
62
|
+
|
63
|
+
arguments, block = complete_criteria(subject, &block)
|
64
|
+
|
65
|
+
if @not
|
66
|
+
@assay.refute!(*arguments, &block)
|
67
|
+
else
|
68
|
+
@assay.assert!(*arguments, &block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
#
|
74
|
+
def refute!(subject, &block)
|
75
|
+
# technically this needs to be controlled by the assay class
|
76
|
+
if block.nil? && Proc === subject
|
77
|
+
block = subject
|
78
|
+
subject = NA
|
79
|
+
end
|
80
|
+
|
81
|
+
arguments, block = complete_criteria(subject, &block)
|
82
|
+
|
83
|
+
if @not
|
84
|
+
@assay.assert!(*arguments, &block)
|
85
|
+
else
|
86
|
+
@assay.refute!(*arguments, &block)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
alias_method :==, :pass?
|
91
|
+
alias_method :!=, :fail?
|
92
|
+
|
93
|
+
alias_method :=~, :assert!
|
94
|
+
alias_method :!~, :refute!
|
95
|
+
|
96
|
+
alias_method :===, :assert!
|
97
|
+
|
98
|
+
#
|
99
|
+
# Create a negated form of the matcher.
|
100
|
+
#
|
101
|
+
# @todo Should this be @! method instead?
|
102
|
+
#
|
103
|
+
def !@
|
104
|
+
dup.negate!
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Create a negated form of the matcher.
|
109
|
+
#
|
110
|
+
# @todo Best name for this method?
|
111
|
+
#
|
112
|
+
def not
|
113
|
+
dup.negate!
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Assertion message. This is only used by RSpec compatibility methods.
|
118
|
+
#
|
119
|
+
def assert_message(subject, &block)
|
120
|
+
arguments, block = complete_criteria(subject, &block)
|
121
|
+
@assay.assert_message(*arguments, &block)
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Refutation message. This is only used by RSpec compatibility methods.
|
126
|
+
#
|
127
|
+
def refute_message(subject, &block)
|
128
|
+
arguments, block = complete_criteria(subject, &block)
|
129
|
+
@assay.refute_message(*arguments, &block)
|
130
|
+
end
|
131
|
+
|
132
|
+
# The following methods allow Assay objects to work as RSpec matchers.
|
133
|
+
|
134
|
+
# For RSpec matcher compatability.
|
135
|
+
alias matches? pass?
|
136
|
+
|
137
|
+
# For RSpec matcher compatability.
|
138
|
+
alias does_not_match? fail?
|
139
|
+
|
140
|
+
# For RSpec matcher compatability.
|
141
|
+
alias failure_message_for_should assert_message
|
142
|
+
|
143
|
+
# For RSpec matcher compatability.
|
144
|
+
alias failure_message_for_should_not refute_message
|
145
|
+
|
146
|
+
##
|
147
|
+
## Returns Assay instance.
|
148
|
+
##
|
149
|
+
#def exception(subject, msg=nil)
|
150
|
+
# @assay.new(msg || message, subject, *criteria, &block)
|
151
|
+
# # :negated => options[:negated],
|
152
|
+
# # :backtrace => options[:backtrace] || caller,
|
153
|
+
#end
|
154
|
+
|
155
|
+
protected
|
156
|
+
|
157
|
+
#
|
158
|
+
# Toggle the `@not` flag.
|
159
|
+
#
|
160
|
+
def negate!
|
161
|
+
@not = !@not
|
162
|
+
self
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
#
|
168
|
+
#
|
169
|
+
#
|
170
|
+
def complete_criteria(subject, &block)
|
171
|
+
block = block || @block
|
172
|
+
|
173
|
+
return @criteria, block if subject == NA
|
174
|
+
|
175
|
+
if i = @criteria.index(NA)
|
176
|
+
args = @criteria[0...i] + [subject] + @criteria[i+1..-1]
|
177
|
+
else
|
178
|
+
args = [subject] + @criteria
|
179
|
+
end
|
180
|
+
|
181
|
+
return args, block
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|