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.
- checksums.yaml +4 -4
- data/README.md +62 -1
- data/lib/fix/matcher.rb +38 -230
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d32cb2da3e2823f71175074536af7f55c981cba88f1fc39952f5c91ecc27756
|
4
|
+
data.tar.gz: bfbf3da66b20085030ecffadbfe908dfe90ea3fe5620fdfaceeedbb5eaec0e9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
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.
|
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-
|
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.
|
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.
|
39
|
+
version: 4.1.0
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: spectus
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|