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.
Files changed (97) hide show
  1. data/.ruby +46 -41
  2. data/COPYING.rdoc +38 -0
  3. data/HISTORY.rdoc +18 -1
  4. data/QED.rdoc +1100 -0
  5. data/README.rdoc +139 -16
  6. data/lib/assay.rb +82 -29
  7. data/lib/assay.yml +46 -41
  8. data/lib/assay/{adapters → adapter}/minitest.rb +0 -0
  9. data/lib/assay/{adapters → adapter}/testunit.rb +0 -0
  10. data/lib/assay/assertable.rb +174 -0
  11. data/lib/assay/assertion.rb +98 -124
  12. data/lib/assay/assertor.rb +187 -0
  13. data/lib/assay/boolean_assay.rb +15 -0
  14. data/lib/assay/case_assay.rb +17 -0
  15. data/lib/assay/compare_assay.rb +38 -0
  16. data/lib/assay/core_ext/kernel.rb +52 -0
  17. data/lib/assay/core_ext/na.rb +9 -0
  18. data/lib/assay/directory_assay.rb +20 -0
  19. data/lib/assay/empty_assay.rb +17 -0
  20. data/lib/assay/equal_assay.rb +35 -0
  21. data/lib/assay/equality_assay.rb +18 -0
  22. data/lib/assay/execution_assay.rb +59 -0
  23. data/lib/assay/false_assay.rb +17 -0
  24. data/lib/assay/file_assay.rb +17 -0
  25. data/lib/assay/identity_assay.rb +49 -0
  26. data/lib/assay/include_assay.rb +17 -0
  27. data/lib/assay/instance_assay.rb +17 -0
  28. data/lib/assay/kind_assay.rb +18 -0
  29. data/lib/assay/less_assay.rb +18 -0
  30. data/lib/assay/less_equal_assay.rb +25 -0
  31. data/lib/assay/like_assay.rb +17 -0
  32. data/lib/assay/match_assay.rb +17 -0
  33. data/lib/assay/more_assay.rb +18 -0
  34. data/lib/assay/more_equal_assay.rb +25 -0
  35. data/lib/assay/nil_assay.rb +15 -0
  36. data/lib/assay/nomatch_assay.rb +17 -0
  37. data/lib/assay/output_assay.rb +35 -0
  38. data/lib/assay/path_assay.rb +17 -0
  39. data/lib/assay/raise_assay.rb +109 -0
  40. data/lib/assay/rescue_assay.rb +55 -0
  41. data/lib/assay/respond_assay.rb +17 -0
  42. data/lib/assay/return_assay.rb +46 -0
  43. data/lib/assay/silent_assay.rb +59 -0
  44. data/lib/assay/stderr_assay.rb +30 -0
  45. data/lib/assay/stdout_assay.rb +30 -0
  46. data/lib/assay/throw_assay.rb +89 -0
  47. data/lib/assay/true_assay.rb +20 -0
  48. data/lib/assay/unequal_assay.rb +37 -0
  49. data/lib/assay/within_assay.rb +39 -0
  50. data/test/case_compare_assay.rb +59 -0
  51. data/test/case_empty_assay.rb +51 -0
  52. data/test/case_equal_assay.rb +53 -0
  53. data/test/case_equality_assay.rb +55 -0
  54. data/test/case_false_assay.rb +48 -0
  55. data/test/case_identity_assay.rb +51 -0
  56. data/test/case_include_assay.rb +51 -0
  57. data/test/case_instance_assay.rb +51 -0
  58. data/test/case_kind_assay.rb +51 -0
  59. data/test/case_less_assay.rb +53 -0
  60. data/test/case_less_equal_assay.rb +53 -0
  61. data/test/case_like_assay.rb +57 -0
  62. data/test/case_match_assay.rb +45 -0
  63. data/test/case_more_assay.rb +53 -0
  64. data/test/case_more_equal_assay.rb +53 -0
  65. data/test/case_nil_assay.rb +48 -0
  66. data/test/case_nomatch_assay.rb +47 -0
  67. data/test/case_raise_assay.rb +51 -0
  68. data/test/case_respond_assay.rb +51 -0
  69. data/test/case_throw_assay.rb +51 -0
  70. data/test/case_true_assay.rb +48 -0
  71. data/test/case_unequal_assay.rb +55 -0
  72. data/test/case_within_assay.rb +61 -0
  73. data/test/helper.rb +36 -0
  74. metadata +135 -108
  75. data/APACHE2.txt +0 -205
  76. data/NOTICE.rdoc +0 -18
  77. data/lib/assay/assertions/compare_failure.rb +0 -61
  78. data/lib/assay/assertions/delta_failure.rb +0 -80
  79. data/lib/assay/assertions/empty_failure.rb +0 -76
  80. data/lib/assay/assertions/equality_failure.rb +0 -100
  81. data/lib/assay/assertions/execution_failure.rb +0 -90
  82. data/lib/assay/assertions/false_failure.rb +0 -72
  83. data/lib/assay/assertions/identity_failure.rb +0 -85
  84. data/lib/assay/assertions/instance_failure.rb +0 -76
  85. data/lib/assay/assertions/kind_failure.rb +0 -80
  86. data/lib/assay/assertions/match_failure.rb +0 -85
  87. data/lib/assay/assertions/nil_failure.rb +0 -75
  88. data/lib/assay/assertions/raise_failure.rb +0 -134
  89. data/lib/assay/assertions/response_failure.rb +0 -86
  90. data/lib/assay/assertions/same_failure.rb +0 -82
  91. data/lib/assay/assertions/throw_failure.rb +0 -122
  92. data/lib/assay/assertions/true_failure.rb +0 -79
  93. data/lib/assay/matcher.rb +0 -48
  94. data/qed/01_failure_classes.rdoc +0 -75
  95. data/qed/02_assertives.rdoc +0 -118
  96. data/qed/03_matchers.rdoc +0 -118
  97. data/qed/04_lookup.rdoc +0 -10
@@ -1,149 +1,123 @@
1
- require 'ansi/diff'
2
- require 'assay/matcher'
1
+ require 'brass'
3
2
 
4
- module Assay
3
+ require_relative 'core_ext/na'
4
+ require_relative 'core_ext/kernel'
5
5
 
6
- #
7
- class Assertion < Exception
6
+ require_relative 'assertor'
7
+ require_relative 'assertable'
8
8
 
9
- # When displaying errors, use this as a rule of thumb
10
- # for determining when the inspected object will be too
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
- # Returns Matcher for the failure class.
15
- def self.to_matcher(*args, &blk)
16
- Matcher.new(self, *args, &blk)
17
- end
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
- def self.assert(*args, &blk)
26
- opts = Hash === args.last ? args.pop : {}
27
-
28
- backtrace = opts[:backtrace] || caller
29
- message = opts[:message]
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
- def self.refute(*args, &blk)
48
- opts = Hash === args.last ? args.pop : {}
49
-
50
- backtrace = opts[:backtrace] || caller
51
- message = opts[:message]
52
-
53
- err = new(message, *args, &blk)
54
- err.set_backtrace(backtrace)
55
- err.refute
56
-
57
- #opts = Hash === args.last ? args.pop : {}
58
- #chk = check!(*args, &blk)
59
- ##msg = fail_message!(*args, &blk)
60
- #if !chk
61
- # msg = opts[:message]
62
- # btr = opts[:backtrace] || caller
63
- # err = new(msg, :backtrace=>btr, :arguments=>args)
64
- # fail err
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
- def self.pass?(*args, &blk)
70
- raise NotImplementedError
71
- end
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
- def self.fail?(*args, &blk)
75
- ! pass?(*args, &blk)
76
- end
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
- def initialize(message=nil, *arguments, &block)
80
- message ? super(message % arguments) : super()
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
- @mesg = message # why isn't this in @mesg from super()?
83
- @arguments = arguments
84
- @block = block
81
+ private
85
82
 
86
- #set_arguments options[:arguments] if options[:arguments]
87
- #set_negative options[:negated] if options[:negated]
88
- #set_backtrace options[:backtrace] if options[:backtrace]
83
+ def self.operator_index
84
+ @@operator_index ||= {}
89
85
  end
90
86
 
91
- # Failure is always a type of assertion.
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
- def pass?
101
- self.class.pass?(*@arguments, &@block) #^ @negative
102
- end
91
+ #
92
+ # Setup new Assertion object.
93
+ #
94
+ def initialize(msg=nil) #, *criteria, &block)
95
+ super(msg)
103
96
 
104
- #
105
- def fail?
106
- not pass?
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
- def refute
117
- #@negative = true
118
- raise self unless fail?
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
- # Set arguments used to make assertion.
133
- def set_arguments(arguments)
134
- @arguments = arguments
135
- #@block = block
136
- end
111
+ =begin
137
112
 
138
- #
139
- def to_s
140
- if @negative
141
- "NOT " + super()
142
- else
143
- super()
144
- end
145
- end
113
+ #
114
+ #def to_s
115
+ # #if @negative
116
+ # # "NOT " + super()
117
+ # #else
118
+ # super()
119
+ # #end
120
+ #end
146
121
 
147
- end
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
+
@@ -0,0 +1,15 @@
1
+ require_relative 'assertion'
2
+
3
+ class BooleanAssay < Assertion
4
+
5
+ register :boolean
6
+
7
+ #
8
+ # Check assertion.
9
+ #
10
+ def self.pass?(subject)
11
+ subject.true? || subject.false? # TODO: Kernel#boolean? method
12
+ end
13
+
14
+ end
15
+