r_spec-clone 1.2.2 → 1.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.
- checksums.yaml +4 -4
- data/README.md +34 -5
- data/lib/r_spec.rb +2 -2
- data/lib/r_spec/clone/error/pending_expectation.rb +7 -7
- data/lib/r_spec/clone/expectation_helper/shared.rb +200 -64
- data/lib/r_spec/clone/expectation_target/base.rb +7 -7
- data/lib/r_spec/clone/expectation_target/block.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c388fa8f14bc48ea1cd253f46695e15a1f7e96192cc04143d6bc5d363dfa0669
|
4
|
+
data.tar.gz: fae27e21e625015f5e3dfaf9ae4f1fc2454632a13f8ed100e8519b080eb61b9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 694679d560726f4f0a23c5ee2c5fbbe8fa75744fe8fc480ba907dad64e92036967cfe6ce129a64cb93292025256ba9427cf3723ad7a893dccd430749fd6c0ada
|
7
|
+
data.tar.gz: 0aa55bcf1f8aee5ab72adf4cbaef3fa2a6a9228cbf8b7afbf38f80caca54f84285af99d6aeb8dc6e39629cba090c35657988e1c44f3c2c788dabfc444249e0f2
|
data/README.md
CHANGED
@@ -117,6 +117,8 @@ end
|
|
117
117
|
# Success: expected to eq "foo".
|
118
118
|
```
|
119
119
|
|
120
|
+
Note: if you are wondering what the Ruby code generated by using the DSL might look like, an article presents the correspondence between each method via simple examples, available in [English](https://dev.to/cyri_/what-ruby-code-to-expect-from-a-testing-dsl-4oe1), [Chinese](https://ruby-china.org/topics/41441) and [Japanese](https://qiita.com/cyril/items/17ee758e162bae144a07).
|
121
|
+
|
120
122
|
### Expectations
|
121
123
|
|
122
124
|
Expectations define if the value being tested (_actual_) matches a certain value or specific criteria.
|
@@ -135,6 +137,12 @@ expect(actual).to equal(expected) # passes if expected.equal?(actual)
|
|
135
137
|
expect(actual).to be(expected) # passes if expected.equal?(actual)
|
136
138
|
```
|
137
139
|
|
140
|
+
#### Comparisons
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
expect(actual).to be_within(delta).of(expected) # passes if (expected - actual).abs <= delta
|
144
|
+
```
|
145
|
+
|
138
146
|
#### Regular expressions
|
139
147
|
|
140
148
|
```ruby
|
@@ -147,13 +155,13 @@ expect(actual).to match(expected) # passes if expected.match?(actual)
|
|
147
155
|
expect { actual }.to raise_exception(expected) # passes if expected exception is raised
|
148
156
|
```
|
149
157
|
|
150
|
-
####
|
158
|
+
#### True
|
151
159
|
|
152
160
|
```ruby
|
153
161
|
expect(actual).to be_true # passes if true.equal?(actual)
|
154
162
|
```
|
155
163
|
|
156
|
-
####
|
164
|
+
#### False
|
157
165
|
|
158
166
|
```ruby
|
159
167
|
expect(actual).to be_false # passes if false.equal?(actual)
|
@@ -172,6 +180,21 @@ expect(actual).to be_instance_of(expected) # passes if expected.equal?(actual
|
|
172
180
|
expect(actual).to be_an_instance_of(expected) # passes if expected.equal?(actual.class)
|
173
181
|
```
|
174
182
|
|
183
|
+
#### Change
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
expect { object.action }.to change(object, :value).from(old).to(new)
|
187
|
+
expect { object.action }.to change(object, :value).by(delta)
|
188
|
+
expect { object.action }.to change(object, :value).by_at_least(minimum_delta)
|
189
|
+
expect { object.action }.to change(object, :value).by_at_most(maximum_delta)
|
190
|
+
```
|
191
|
+
|
192
|
+
#### Satisfy
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
expect(actual).to(satisfy { |value| value == expected })
|
196
|
+
```
|
197
|
+
|
175
198
|
### Running specs
|
176
199
|
|
177
200
|
By convention, specs live in the `spec/` directory of a project. Spec files should end with `_spec.rb` to be recognizable as such.
|
@@ -232,17 +255,23 @@ bundle exec rake
|
|
232
255
|
|
233
256
|
## Performance
|
234
257
|
|
258
|
+
The benchmarks compare the performance of [`r_spec-clone`](https://rubygems.org/gems/r_spec-clone) with the following frameworks (in alphabetical order):
|
259
|
+
|
260
|
+
* [`fix`](https://rubygems.org/gems/fix)
|
261
|
+
* [`minitest`](https://rubygems.org/gems/minitest)
|
262
|
+
* [`rspec`](https://rubygems.org/gems/rspec)
|
263
|
+
|
235
264
|
### Boot time
|
236
265
|
|
237
266
|
Benchmark against [100 executions of a file containing 1 expectation](https://github.com/cyril/r_spec-clone.rb/blob/main/benchmark/boot_time/) (lower is better).
|
238
267
|
|
239
|
-

|
268
|
+

|
240
269
|
|
241
|
-
###
|
270
|
+
### Runtime
|
242
271
|
|
243
272
|
Benchmark against [1 execution of a file containing 1,000,000 expectations](https://github.com/cyril/r_spec-clone.rb/blob/main/benchmark/run_time/) (lower is better).
|
244
273
|
|
245
|
-

|
246
275
|
|
247
276
|
## Test suite
|
248
277
|
|
data/lib/r_spec.rb
CHANGED
@@ -37,8 +37,8 @@ require_relative File.join("r_spec", "clone", "dsl")
|
|
37
37
|
#
|
38
38
|
# # Output to the console
|
39
39
|
# # Success: expected to eq 3.
|
40
|
-
# # Success: expected
|
41
|
-
# # Success: expected
|
40
|
+
# # Success: expected to be true.
|
41
|
+
# # Success: expected to be false.
|
42
42
|
#
|
43
43
|
# @example An inherited definition of let
|
44
44
|
# require "r_spec"
|
@@ -12,13 +12,13 @@ module RSpec
|
|
12
12
|
# @return [nil] Write a pending expectation to STDOUT.
|
13
13
|
def self.result(message)
|
14
14
|
::Expresenter.call(true).with(
|
15
|
-
actual:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
negate:
|
21
|
-
level:
|
15
|
+
actual: new(message),
|
16
|
+
definition: "raise exception #{self}",
|
17
|
+
error: nil,
|
18
|
+
expected: self,
|
19
|
+
got: false,
|
20
|
+
negate: true,
|
21
|
+
level: :SHOULD
|
22
22
|
)
|
23
23
|
end
|
24
24
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "matchi
|
3
|
+
require "matchi"
|
4
4
|
|
5
5
|
module RSpec
|
6
6
|
module Clone
|
@@ -10,72 +10,208 @@ module RSpec
|
|
10
10
|
# This module defines a number of methods to create expectations, which
|
11
11
|
# are automatically included into examples.
|
12
12
|
#
|
13
|
-
# It also includes a collection of expectation matchers
|
14
|
-
#
|
15
|
-
# @example Equivalence matcher
|
16
|
-
# matcher = eql("foo") # => Matchi::Matcher::Eql.new("foo")
|
17
|
-
# matcher.matches? { "foo" } # => true
|
18
|
-
# matcher.matches? { "bar" } # => false
|
19
|
-
#
|
20
|
-
# matcher = eq("foo") # => Matchi::Matcher::Eq.new("foo")
|
21
|
-
# matcher.matches? { "foo" } # => true
|
22
|
-
# matcher.matches? { "bar" } # => false
|
23
|
-
#
|
24
|
-
# @example Identity matcher
|
25
|
-
# object = "foo"
|
26
|
-
#
|
27
|
-
# matcher = equal(object) # => Matchi::Matcher::Equal.new(object)
|
28
|
-
# matcher.matches? { object } # => true
|
29
|
-
# matcher.matches? { "foo" } # => false
|
30
|
-
#
|
31
|
-
# matcher = be(object) # => Matchi::Matcher::Be.new(object)
|
32
|
-
# matcher.matches? { object } # => true
|
33
|
-
# matcher.matches? { "foo" } # => false
|
34
|
-
#
|
35
|
-
# @example Regular expressions matcher
|
36
|
-
# matcher = match(/^foo$/) # => Matchi::Matcher::Match.new(/^foo$/)
|
37
|
-
# matcher.matches? { "foo" } # => true
|
38
|
-
# matcher.matches? { "bar" } # => false
|
39
|
-
#
|
40
|
-
# @example Expecting errors matcher
|
41
|
-
# matcher = raise_exception(NameError) # => Matchi::Matcher::RaiseException.new(NameError)
|
42
|
-
# matcher.matches? { Boom } # => true
|
43
|
-
# matcher.matches? { true } # => false
|
44
|
-
#
|
45
|
-
# @example Truth matcher
|
46
|
-
# matcher = be_true # => Matchi::Matcher::BeTrue.new
|
47
|
-
# matcher.matches? { true } # => true
|
48
|
-
# matcher.matches? { false } # => false
|
49
|
-
# matcher.matches? { nil } # => false
|
50
|
-
# matcher.matches? { 4 } # => false
|
51
|
-
#
|
52
|
-
# @example Untruth matcher
|
53
|
-
# matcher = be_false # => Matchi::Matcher::BeFalse.new
|
54
|
-
# matcher.matches? { false } # => true
|
55
|
-
# matcher.matches? { true } # => false
|
56
|
-
# matcher.matches? { nil } # => false
|
57
|
-
# matcher.matches? { 4 } # => false
|
58
|
-
#
|
59
|
-
# @example Nil matcher
|
60
|
-
# matcher = be_nil # => Matchi::Matcher::BeNil.new
|
61
|
-
# matcher.matches? { nil } # => true
|
62
|
-
# matcher.matches? { false } # => false
|
63
|
-
# matcher.matches? { true } # => false
|
64
|
-
# matcher.matches? { 4 } # => false
|
65
|
-
#
|
66
|
-
# @example Type/class matcher
|
67
|
-
# matcher = be_instance_of(String) # => Matchi::Matcher::BeInstanceOf.new(String)
|
68
|
-
# matcher.matches? { "foo" } # => true
|
69
|
-
# matcher.matches? { 4 } # => false
|
70
|
-
#
|
71
|
-
# matcher = be_an_instance_of(String) # => Matchi::Matcher::BeAnInstanceOf.new(String)
|
72
|
-
# matcher.matches? { "foo" } # => true
|
73
|
-
# matcher.matches? { 4 } # => false
|
13
|
+
# It also includes a collection of expectation matchers.
|
74
14
|
#
|
75
15
|
# @see https://github.com/fixrb/matchi
|
76
|
-
# @see https://github.com/fixrb/matchi-rspec
|
77
16
|
module Shared
|
78
|
-
|
17
|
+
# Equivalence matcher
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# matcher = eq("foo")
|
21
|
+
# matcher.matches? { "foo" } # => true
|
22
|
+
# matcher.matches? { "bar" } # => false
|
23
|
+
#
|
24
|
+
# @param expected [#eql?] An expected equivalent object.
|
25
|
+
#
|
26
|
+
# @return [#matches?] An equivalence matcher.
|
27
|
+
#
|
28
|
+
# @api public
|
29
|
+
def eq(expected)
|
30
|
+
::Matchi::Eq.new(expected)
|
31
|
+
end
|
32
|
+
|
33
|
+
alias eql eq
|
34
|
+
|
35
|
+
# Identity matcher
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# object = "foo"
|
39
|
+
# matcher = be(object)
|
40
|
+
# matcher.matches? { object } # => true
|
41
|
+
# matcher.matches? { "foo" } # => false
|
42
|
+
#
|
43
|
+
# @param expected [#equal?] The expected identical object.
|
44
|
+
#
|
45
|
+
# @return [#matches?] An identity matcher.
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
def be(expected)
|
49
|
+
::Matchi::Be.new(expected)
|
50
|
+
end
|
51
|
+
|
52
|
+
alias equal be
|
53
|
+
|
54
|
+
# Comparisons matcher
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# matcher = be_within(1).of(41)
|
58
|
+
# matcher.matches? { 42 } # => true
|
59
|
+
# matcher.matches? { 43 } # => false
|
60
|
+
#
|
61
|
+
# @param delta [Numeric] A numeric value.
|
62
|
+
#
|
63
|
+
# @return [#matches?] A comparison matcher.
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
def be_within(delta)
|
67
|
+
::Matchi::BeWithin.new(delta)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Regular expressions matcher
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# matcher = match(/^foo$/)
|
74
|
+
# matcher.matches? { "foo" } # => true
|
75
|
+
# matcher.matches? { "bar" } # => false
|
76
|
+
#
|
77
|
+
# @param expected [#match] A regular expression.
|
78
|
+
#
|
79
|
+
# @return [#matches?] A regular expression matcher.
|
80
|
+
#
|
81
|
+
# @api public
|
82
|
+
def match(expected)
|
83
|
+
::Matchi::Match.new(expected)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Expecting errors matcher
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# matcher = raise_exception(NameError)
|
90
|
+
# matcher.matches? { Boom } # => true
|
91
|
+
# matcher.matches? { true } # => false
|
92
|
+
#
|
93
|
+
# @param expected [Exception, #to_s] The expected exception name.
|
94
|
+
#
|
95
|
+
# @return [#matches?] An error matcher.
|
96
|
+
#
|
97
|
+
# @api public
|
98
|
+
def raise_exception(expected)
|
99
|
+
::Matchi::RaiseException.new(expected)
|
100
|
+
end
|
101
|
+
|
102
|
+
# True matcher
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# matcher = be_true
|
106
|
+
# matcher.matches? { true } # => true
|
107
|
+
# matcher.matches? { false } # => false
|
108
|
+
# matcher.matches? { nil } # => false
|
109
|
+
# matcher.matches? { 4 } # => false
|
110
|
+
#
|
111
|
+
# @return [#matches?] A `true` matcher.
|
112
|
+
#
|
113
|
+
# @api public
|
114
|
+
def be_true
|
115
|
+
be(true)
|
116
|
+
end
|
117
|
+
|
118
|
+
# False matcher
|
119
|
+
#
|
120
|
+
# @example
|
121
|
+
# matcher = be_false
|
122
|
+
# matcher.matches? { false } # => true
|
123
|
+
# matcher.matches? { true } # => false
|
124
|
+
# matcher.matches? { nil } # => false
|
125
|
+
# matcher.matches? { 4 } # => false
|
126
|
+
#
|
127
|
+
# @return [#matches?] A `false` matcher.
|
128
|
+
#
|
129
|
+
# @api public
|
130
|
+
def be_false
|
131
|
+
be(false)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Nil matcher
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# matcher = be_nil
|
138
|
+
# matcher.matches? { nil } # => true
|
139
|
+
# matcher.matches? { false } # => false
|
140
|
+
# matcher.matches? { true } # => false
|
141
|
+
# matcher.matches? { 4 } # => false
|
142
|
+
#
|
143
|
+
# @return [#matches?] A `nil` matcher.
|
144
|
+
#
|
145
|
+
# @api public
|
146
|
+
def be_nil
|
147
|
+
be(nil)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Type/class matcher
|
151
|
+
#
|
152
|
+
# @example
|
153
|
+
# matcher = be_an_instance_of(String)
|
154
|
+
# matcher.matches? { "foo" } # => true
|
155
|
+
# matcher.matches? { 4 } # => false
|
156
|
+
#
|
157
|
+
# @param expected [Class, #to_s] The expected class name.
|
158
|
+
#
|
159
|
+
# @return [#matches?] A type/class matcher.
|
160
|
+
#
|
161
|
+
# @api public
|
162
|
+
def be_an_instance_of(expected)
|
163
|
+
::Matchi::BeAnInstanceOf.new(expected)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Change matcher
|
167
|
+
#
|
168
|
+
# @example
|
169
|
+
# object = []
|
170
|
+
# matcher = change(object, :length).by(1)
|
171
|
+
# matcher.matches? { object << 1 } # => true
|
172
|
+
#
|
173
|
+
# object = []
|
174
|
+
# matcher = change(object, :length).by_at_least(1)
|
175
|
+
# matcher.matches? { object << 1 } # => true
|
176
|
+
#
|
177
|
+
# object = []
|
178
|
+
# matcher = change(object, :length).by_at_most(1)
|
179
|
+
# matcher.matches? { object << 1 } # => true
|
180
|
+
#
|
181
|
+
# object = "foo"
|
182
|
+
# matcher = change(object, :to_s).from("foo").to("FOO")
|
183
|
+
# matcher.matches? { object.upcase! } # => true
|
184
|
+
#
|
185
|
+
# object = "foo"
|
186
|
+
# matcher = change(object, :to_s).to("FOO")
|
187
|
+
# matcher.matches? { object.upcase! } # => true
|
188
|
+
#
|
189
|
+
# @param object [#object_id] An object.
|
190
|
+
# @param method [Symbol] The name of a method.
|
191
|
+
# @param args [Array] A list of arguments.
|
192
|
+
# @param kwargs [Hash] A list of keyword arguments.
|
193
|
+
#
|
194
|
+
# @return [#matches?] A change matcher.
|
195
|
+
#
|
196
|
+
# @api public
|
197
|
+
def change(object, method, *args, **kwargs, &block)
|
198
|
+
::Matchi::Change.new(object, method, *args, **kwargs, &block)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Satisfy matcher
|
202
|
+
#
|
203
|
+
# @example
|
204
|
+
# matcher = satisfy { |value| value == 42 }
|
205
|
+
# matcher.matches? { 42 } # => true
|
206
|
+
#
|
207
|
+
# @param expected [Proc] A block of code.
|
208
|
+
#
|
209
|
+
# @return [#matches?] A satisfy matcher.
|
210
|
+
#
|
211
|
+
# @api public
|
212
|
+
def satisfy(&expected)
|
213
|
+
::Matchi::Satisfy.new(&expected)
|
214
|
+
end
|
79
215
|
end
|
80
216
|
end
|
81
217
|
end
|
@@ -95,13 +95,13 @@ module RSpec
|
|
95
95
|
# `Kernel.exit(false)` with a failure message written to STDERR.
|
96
96
|
def result(passed, actual:, error:, got:, matcher:, negate:)
|
97
97
|
Console.passed_spec ::Expresenter.call(passed).with(
|
98
|
-
actual:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
level:
|
98
|
+
actual: actual,
|
99
|
+
definition: matcher.to_s,
|
100
|
+
error: error,
|
101
|
+
expected: matcher.expected,
|
102
|
+
got: got,
|
103
|
+
negate: negate,
|
104
|
+
level: :MUST
|
105
105
|
)
|
106
106
|
rescue ::Expresenter::Fail => e
|
107
107
|
Console.failed_spec(e)
|
@@ -29,7 +29,7 @@ module RSpec
|
|
29
29
|
# @raise (see Base#absolute_requirement)
|
30
30
|
def absolute_requirement(matcher:, negate:)
|
31
31
|
super(
|
32
|
-
::TestTube.invoke(
|
32
|
+
::TestTube.invoke(isolate: false, matcher: matcher, negate: negate, &@input),
|
33
33
|
matcher: matcher,
|
34
34
|
negate: negate
|
35
35
|
)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: r_spec-clone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-07-
|
11
|
+
date: 2021-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: expresenter
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.4.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.4.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: matchi
|
28
|
+
name: matchi
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 3.2.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 3.2.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: test_tube
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 2.
|
47
|
+
version: 2.1.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 2.
|
54
|
+
version: 2.1.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|