fix 1.0.0.beta11 → 1.0.0.beta12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|