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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ca7e0d020bebba8aec767197a6c765fa4c0ded5bb96fb58723e5de8321ba1bf
4
- data.tar.gz: 3e9fd96ec29c5341bb5b8f8a3fb60c9672a816e3dd22e1d80d7593ef78689f74
3
+ metadata.gz: c388fa8f14bc48ea1cd253f46695e15a1f7e96192cc04143d6bc5d363dfa0669
4
+ data.tar.gz: fae27e21e625015f5e3dfaf9ae4f1fc2454632a13f8ed100e8519b080eb61b9d
5
5
  SHA512:
6
- metadata.gz: 7ae195dc7673cdd06068d376763ca3b67904eb1bea7ec502cdaf74424ffacb2d44c685988e7c22db21e7be2295a9d3de3b93d587e1c0d8696739dfdb8f37216d
7
- data.tar.gz: 2b3522c31de373f4b9dc3a5d88a9a8e2ec7443d11205d6f93eae91f43a136bead79774333d3d8bac04b96cd07f89eb8c9792c379af0eb380b644da0931d639b4
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
- #### Truth
158
+ #### True
151
159
 
152
160
  ```ruby
153
161
  expect(actual).to be_true # passes if true.equal?(actual)
154
162
  ```
155
163
 
156
- #### Untruth
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
- ![Boot time](https://r-spec.dev/benchmark-boot-time.svg)
268
+ ![Boot time benchmark](https://r-spec.dev/benchmark-boot-time.svg)
240
269
 
241
- ### Run time
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
- ![Run time](https://r-spec.dev/benchmark-run-time.svg)
274
+ ![Runtime benchmark](https://r-spec.dev/benchmark-run-time.svg)
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 true to be true.
41
- # # Success: expected false to be false.
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: new(message),
16
- error: nil,
17
- expected: self,
18
- got: false,
19
- matcher: :raise_exception,
20
- negate: true,
21
- level: :SHOULD
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/rspec"
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
- include ::Matchi::Helper
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: actual,
99
- error: error,
100
- expected: matcher.expected,
101
- got: got,
102
- negate: negate,
103
- matcher: matcher.class.to_sym,
104
- level: :MUST
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(isolation: false, matcher: matcher, negate: negate, &@input),
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.2.2
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-12 00:00:00.000000000 Z
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.3.0
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.3.0
26
+ version: 1.4.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: matchi-rspec
28
+ name: matchi
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.1.2
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: 1.1.2
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.0.0
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.0.0
54
+ version: 2.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement