fix 1.0.0.beta11 → 1.0.0.beta12

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 (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +62 -1
  3. data/lib/fix/matcher.rb +38 -230
  4. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40461f87067aa8b719fc25a6256772961b8ef4c412cd043ddddc51d8b048d014
4
- data.tar.gz: ad050718de8cd7c7fcede3f8c9644b91c33ec2cef4e877fd28773d576b265292
3
+ metadata.gz: 4d32cb2da3e2823f71175074536af7f55c981cba88f1fc39952f5c91ecc27756
4
+ data.tar.gz: bfbf3da66b20085030ecffadbfe908dfe90ea3fe5620fdfaceeedbb5eaec0e9e
5
5
  SHA512:
6
- metadata.gz: 8d83f640bb5a086f530265eea8fab350a74e4209072aae351107b0fab393e6ebb1f3fcd266550fccc3c21cf5b9885e2444731ab28200861fcc06fff4f3facf83
7
- data.tar.gz: 85a1b557e06c39c82c653e4283c0489a6bfb3aec0dff69e1f42617cf93805fe5fbe8ea9a5feb13a853d1969a63ea741c73ba1872b4b8b1939b924e388e0ec377
6
+ metadata.gz: 1e66633ce3e37380f20f83f3747ef158e9baadc0853898850972c7e119fe7615eadd53c3197c9bfbd8e48f341d38991060f8dfba16070f34953a08208eefa5bf
7
+ data.tar.gz: 798abf5941f2fbac379d6b19622d1dfe8fd278c81a715a8e1f55a0f8c91aa6b0b1febfd2a60241ddb9a12f5320ed112a77a0a39f860d3e26e43985277f4d0e99
data/README.md CHANGED
@@ -14,7 +14,7 @@ Fix is a modern Ruby testing framework that emphasizes clear separation between
14
14
  Add to your Gemfile:
15
15
 
16
16
  ```ruby
17
- gem "fix", ">= 1.0.0.beta11"
17
+ gem "fix", ">= 1.0.0.beta12"
18
18
  ```
19
19
 
20
20
  Then execute:
@@ -226,6 +226,67 @@ Running the test:
226
226
  Fix[:Duck].test { Duck.new }
227
227
  ```
228
228
 
229
+ ## Available Matchers
230
+
231
+ Fix includes a comprehensive set of matchers through its integration with the [Matchi library](https://github.com/fixrb/matchi):
232
+
233
+ ### Basic Comparison Matchers
234
+ - `eq(expected)` - Tests equality using `eql?`
235
+ - `be(expected)` - Tests object identity using `equal?`
236
+
237
+ ### Type Checking Matchers
238
+ - `be_an_instance_of(class)` - Verifies exact class match
239
+ - `be_a_kind_of(class)` - Checks class inheritance and module inclusion
240
+
241
+ ### Change Testing Matchers
242
+ - `change(object, method)` - Base matcher for state changes
243
+ - `.by(n)` - Expects exact change by n
244
+ - `.by_at_least(n)` - Expects minimum change by n
245
+ - `.by_at_most(n)` - Expects maximum change by n
246
+ - `.from(old).to(new)` - Expects change from old to new value
247
+ - `.to(new)` - Expects change to new value
248
+
249
+ ### Numeric Matchers
250
+ - `be_within(delta).of(value)` - Tests if a value is within ±delta of expected value
251
+
252
+ ### Pattern Matchers
253
+ - `match(regex)` - Tests string against regular expression pattern
254
+ - `satisfy { |value| ... }` - Custom matching with block
255
+
256
+ ### State Matchers
257
+ - `be_true` - Tests for true
258
+ - `be_false` - Tests for false
259
+ - `be_nil` - Tests for nil
260
+
261
+ ### Exception Matchers
262
+ - `raise_exception(class)` - Tests if code raises specified exception
263
+
264
+ ### Dynamic Predicate Matchers
265
+ - `be_*` - Dynamically matches `object.*?` methods (e.g., `be_empty` calls `empty?`)
266
+ - `have_*` - Dynamically matches `object.has_*?` methods (e.g., `have_key` calls `has_key?`)
267
+
268
+ Example usage:
269
+
270
+ ```ruby
271
+ Fix :Calculator do
272
+ it MUST be_an_instance_of Calculator
273
+
274
+ on :add, 2, 3 do
275
+ it MUST eq 5
276
+ it MUST be_within(0.001).of(5.0)
277
+ end
278
+
279
+ on :divide, 1, 0 do
280
+ it MUST raise_exception ZeroDivisionError
281
+ end
282
+
283
+ with numbers: [1, 2, 3] do
284
+ it MUST_NOT be_empty
285
+ it MUST satisfy { |result| result.all? { |n| n.positive? } }
286
+ end
287
+ end
288
+ ```
289
+
229
290
  ## Why Choose Fix?
230
291
 
231
292
  Fix brings several unique advantages to Ruby testing that set it apart from traditional testing frameworks:
data/lib/fix/matcher.rb CHANGED
@@ -5,237 +5,45 @@ require "matchi"
5
5
  module Fix
6
6
  # Collection of expectation matchers.
7
7
  #
8
+ # The following matchers are available:
9
+ #
10
+ # Basic Comparison:
11
+ # - eq(expected) # Checks equality using eql?
12
+ # - eql(expected) # Alias for eq
13
+ # - be(expected) # Checks exact object identity using equal?
14
+ # - equal(expected) # Alias for be
15
+ #
16
+ # Type Checking:
17
+ # - be_an_instance_of(class) # Checks exact class match
18
+ # - be_a_kind_of(class) # Checks class inheritance and module inclusion
19
+ #
20
+ # State & Changes:
21
+ # - change(object, method) # Base for checking state changes
22
+ # .by(n) # Exact change by n
23
+ # .by_at_least(n) # Minimum change by n
24
+ # .by_at_most(n) # Maximum change by n
25
+ # .from(old).to(new) # Change from old to new value
26
+ # .to(new) # Change to new value
27
+ #
28
+ # Value Testing:
29
+ # - be_within(delta).of(value) # Checks numeric value within delta
30
+ # - match(regex) # Tests against regular expression
31
+ # - satisfy { |value| ... } # Custom matcher with block
32
+ #
33
+ # Exceptions:
34
+ # - raise_exception(class) # Checks if code raises exception
35
+ #
36
+ # State Testing:
37
+ # - be_true # Tests for true
38
+ # - be_false # Tests for false
39
+ # - be_nil # Tests for nil
40
+ #
41
+ # Predicate Matchers:
42
+ # - be_* # Matches object.*? method
43
+ # - have_* # Matches object.has_*? method
44
+ #
8
45
  # @api private
9
46
  module Matcher
10
- # Equivalence matcher
11
- #
12
- # @example
13
- # matcher = eq("foo")
14
- # matcher.match? { "foo" } # => true
15
- # matcher.match? { "bar" } # => false
16
- #
17
- # @param expected [#eql?] An expected equivalent object.
18
- #
19
- # @return [#match?] An equivalence matcher.
20
- #
21
- # @api public
22
- def eq(expected)
23
- ::Matchi::Eq.new(expected)
24
- end
25
-
26
- alias eql eq
27
-
28
- # Identity matcher
29
- #
30
- # @example
31
- # object = "foo"
32
- # matcher = be(object)
33
- # matcher.match? { object } # => true
34
- # matcher.match? { "foo" } # => false
35
- #
36
- # @param expected [#equal?] The expected identical object.
37
- #
38
- # @return [#match?] An identity matcher.
39
- #
40
- # @api public
41
- def be(expected)
42
- ::Matchi::Be.new(expected)
43
- end
44
-
45
- alias equal be
46
-
47
- # Comparisons matcher
48
- #
49
- # @example
50
- # matcher = be_within(1).of(41)
51
- # matcher.match? { 42 } # => true
52
- # matcher.match? { 43 } # => false
53
- #
54
- # @param delta [Numeric] A numeric value.
55
- #
56
- # @return [#match?] A comparison matcher.
57
- #
58
- # @api public
59
- def be_within(delta)
60
- ::Matchi::BeWithin.new(delta)
61
- end
62
-
63
- # Regular expressions matcher
64
- #
65
- # @example
66
- # matcher = match(/^foo$/)
67
- # matcher.match? { "foo" } # => true
68
- # matcher.match? { "bar" } # => false
69
- #
70
- # @param expected [#match] A regular expression.
71
- #
72
- # @return [#match?] A regular expression matcher.
73
- #
74
- # @api public
75
- def match(expected)
76
- ::Matchi::Match.new(expected)
77
- end
78
-
79
- # Expecting errors matcher
80
- #
81
- # @example
82
- # matcher = raise_exception(NameError)
83
- # matcher.match? { Boom } # => true
84
- # matcher.match? { true } # => false
85
- #
86
- # @param expected [Exception, #to_s] The expected exception name.
87
- #
88
- # @return [#match?] An error matcher.
89
- #
90
- # @api public
91
- def raise_exception(expected)
92
- ::Matchi::RaiseException.new(expected)
93
- end
94
-
95
- # True matcher
96
- #
97
- # @example
98
- # matcher = be_true
99
- # matcher.match? { true } # => true
100
- # matcher.match? { false } # => false
101
- # matcher.match? { nil } # => false
102
- # matcher.match? { 4 } # => false
103
- #
104
- # @return [#match?] A `true` matcher.
105
- #
106
- # @api public
107
- def be_true
108
- be(true)
109
- end
110
-
111
- # False matcher
112
- #
113
- # @example
114
- # matcher = be_false
115
- # matcher.match? { false } # => true
116
- # matcher.match? { true } # => false
117
- # matcher.match? { nil } # => false
118
- # matcher.match? { 4 } # => false
119
- #
120
- # @return [#match?] A `false` matcher.
121
- #
122
- # @api public
123
- def be_false
124
- be(false)
125
- end
126
-
127
- # Nil matcher
128
- #
129
- # @example
130
- # matcher = be_nil
131
- # matcher.match? { nil } # => true
132
- # matcher.match? { false } # => false
133
- # matcher.match? { true } # => false
134
- # matcher.match? { 4 } # => false
135
- #
136
- # @return [#match?] A `nil` matcher.
137
- #
138
- # @api public
139
- def be_nil
140
- be(nil)
141
- end
142
-
143
- # Type/class matcher
144
- #
145
- # @example
146
- # matcher = be_an_instance_of(String)
147
- # matcher.match? { "foo" } # => true
148
- # matcher.match? { 4 } # => false
149
- #
150
- # @param expected [Class, #to_s] The expected class name.
151
- #
152
- # @return [#match?] A type/class matcher.
153
- #
154
- # @api public
155
- def be_an_instance_of(expected)
156
- ::Matchi::BeAnInstanceOf.new(expected)
157
- end
158
-
159
- # Change matcher
160
- #
161
- # @example
162
- # object = []
163
- # matcher = change(object, :length).by(1)
164
- # matcher.match? { object << 1 } # => true
165
- #
166
- # object = []
167
- # matcher = change(object, :length).by_at_least(1)
168
- # matcher.match? { object << 1 } # => true
169
- #
170
- # object = []
171
- # matcher = change(object, :length).by_at_most(1)
172
- # matcher.match? { object << 1 } # => true
173
- #
174
- # object = "foo"
175
- # matcher = change(object, :to_s).from("foo").to("FOO")
176
- # matcher.match? { object.upcase! } # => true
177
- #
178
- # object = "foo"
179
- # matcher = change(object, :to_s).to("FOO")
180
- # matcher.match? { object.upcase! } # => true
181
- #
182
- # @param object [#object_id] An object.
183
- # @param method [Symbol] The name of a method.
184
- #
185
- # @return [#match?] A change matcher.
186
- #
187
- # @api public
188
- def change(object, method, ...)
189
- ::Matchi::Change.new(object, method, ...)
190
- end
191
-
192
- # Satisfy matcher
193
- #
194
- # @example
195
- # matcher = satisfy { |value| value == 42 }
196
- # matcher.match? { 42 } # => true
197
- #
198
- # @yield [value] A block that defines the satisfaction criteria
199
- # @yieldparam value The value to test
200
- # @yieldreturn [Boolean] true if the value satisfies the criteria
201
- #
202
- # @return [#match?] A satisfy matcher.
203
- #
204
- # @api public
205
- def satisfy(&)
206
- ::Matchi::Satisfy.new(&)
207
- end
208
-
209
- private
210
-
211
- # Predicate matcher, or default method missing behavior.
212
- #
213
- # @example Empty predicate matcher
214
- # matcher = be_empty
215
- # matcher.match? { [] } # => true
216
- # matcher.match? { [4] } # => false
217
- def method_missing(name, ...)
218
- return super unless predicate_matcher_name?(name)
219
-
220
- ::Matchi::Predicate.new(name, ...)
221
- end
222
-
223
- # :nocov:
224
-
225
- # Hook method to return whether the obj can respond to id method or not.
226
- def respond_to_missing?(name, include_private = false)
227
- predicate_matcher_name?(name) || super
228
- end
229
-
230
- # :nocov:
231
-
232
- # Predicate matcher name detector.
233
- #
234
- # @param name [Array, Symbol] The name of a potential predicate matcher.
235
- #
236
- # @return [Boolean] Indicates if it is a predicate matcher name or not.
237
- def predicate_matcher_name?(name)
238
- name.start_with?("be_", "have_") && !name.end_with?("!", "?")
239
- end
47
+ include Matchi
240
48
  end
241
49
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta11
4
+ version: 1.0.0.beta12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-12-30 00:00:00.000000000 Z
10
+ date: 2024-12-31 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: defi
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 4.0.0
32
+ version: 4.1.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 4.0.0
39
+ version: 4.1.0
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: spectus
42
42
  requirement: !ruby/object:Gem::Requirement