r_spec-clone 1.2.1 → 1.3.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: 90252cd64a48b7b40aa2424c1c09c69227e45e414ac5fd8d14a53697c0b1c180
4
- data.tar.gz: 7eb7211ac34e5dfc2f1f74ae17d354f2704feb41e400d5fada1ccaa764912413
3
+ metadata.gz: c8475d853643279af5a0a255bf7b3fd5b4547f4dd596bc044fa37a5ac2d69ff0
4
+ data.tar.gz: 3d22158ee01cb6f0e4924bd57345225e35d40920b2bffaf0cf862575db4b62ca
5
5
  SHA512:
6
- metadata.gz: a7fc657a588d0efd081ead62736ddd0f2595e09f0e4db6df235550503325d46cb4814110e16a4fb55244c07de645878d1e08eab40e5ddcc0226b3a64e318091d
7
- data.tar.gz: ff205ff80822fea221bbcd27bf8a43925617146be2bf48d0c24d525bbe530921ce6f835530bce0cad53ef6f3e694278b6bd9655dbd4506f3691365cb15ce800a
6
+ metadata.gz: 2f6826b996db0d6b3f727a7bc16b7757f7fc1ae350ca2285cf81aaf4ce8bfb15f0c37a8910bb2413800821524109cd6c655275aa2b800f52ba25aba1c31c9ac7
7
+ data.tar.gz: 53b85ef4eb8b249cdf2f717de35a6c29916c65d28a125e28656e300a5bfb7263d62865fba6d53a2517ae035cf64daa0c2b7b04a82ecaca93903502b0f5c2a59d
data/README.md CHANGED
@@ -6,6 +6,7 @@ A minimalist __RSpec clone__ with all the essentials.
6
6
 
7
7
  ## Status
8
8
 
9
+ [![Home](https://img.shields.io/badge/Home-r--spec.dev-00af8b)](https://r-spec.dev/)
9
10
  [![Version](https://img.shields.io/github/v/tag/cyril/r_spec-clone.rb?label=Version&logo=github)](https://github.com/cyril/r_spec-clone.rb/releases)
10
11
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/cyril/r_spec-clone.rb/main)
11
12
  [![CI](https://github.com/cyril/r_spec-clone.rb/workflows/CI/badge.svg?branch=main)](https://github.com/cyril/r_spec-clone.rb/actions?query=workflow%3Aci+branch%3Amain)
@@ -23,7 +24,7 @@ A minimalist __RSpec clone__ with all the essentials.
23
24
 
24
25
  * There is no option to activate monkey-patching.
25
26
  * It does not rely on [hacks such as `at_exit` hook](https://blog.arkency.com/2013/06/are-we-abusing-at-exit/) to trigger the tests.
26
- * Built-in matchers [do not trust _actual_](https://asciinema.org/a/29172?autoplay=1&speed=2) and do not send it messages.
27
+ * Malicious _actual values_ cannot [hack results](https://asciinema.org/a/423547?autoplay=1&speed=2).
27
28
  * If no `subject` has been explicitly determined, none is defined.
28
29
  * If no described class is set, `described_class` is undefined instead of `nil`.
29
30
  * Expectations cannot be added inside a `before` block.
@@ -95,12 +96,28 @@ For unit tests, it is recommended to follow the conventions for method names:
95
96
 
96
97
  To establish certain contexts — think _empty array_ versus _array with elements_ — the `context` method may be used to communicate this to the reader.
97
98
 
98
- Finally, each block of code can be run in a subprocess to isolate side effects with the equivalent methods:
99
+ To execute unit tests while isolating side effects in a sub-process, declined methods can be used: `describe!`, `context!`, `it!`, `its!`. Here is an example:
99
100
 
100
- * `describe!`
101
- * `context!`
102
- * `it!`
103
- * `its!`
101
+ ```ruby
102
+ app = "foo"
103
+
104
+ RSpec.describe "Side effects per example" do
105
+ it! "runs the example in isolation" do
106
+ expect { app.gsub!("foo", "bar") }.to eq "bar"
107
+ expect(app).to eq "bar"
108
+ end
109
+
110
+ it "runs the example" do
111
+ expect(app).to eq "foo"
112
+ end
113
+ end
114
+
115
+ # Success: expected to eq "bar".
116
+ # Success: expected to eq "bar".
117
+ # Success: expected to eq "foo".
118
+ ```
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).
104
121
 
105
122
  ### Expectations
106
123
 
@@ -132,13 +149,13 @@ expect(actual).to match(expected) # passes if expected.match?(actual)
132
149
  expect { actual }.to raise_exception(expected) # passes if expected exception is raised
133
150
  ```
134
151
 
135
- #### Truth
152
+ #### True
136
153
 
137
154
  ```ruby
138
155
  expect(actual).to be_true # passes if true.equal?(actual)
139
156
  ```
140
157
 
141
- #### Untruth
158
+ #### False
142
159
 
143
160
  ```ruby
144
161
  expect(actual).to be_false # passes if false.equal?(actual)
@@ -157,6 +174,21 @@ expect(actual).to be_instance_of(expected) # passes if expected.equal?(actual
157
174
  expect(actual).to be_an_instance_of(expected) # passes if expected.equal?(actual.class)
158
175
  ```
159
176
 
177
+ #### Change
178
+
179
+ ```ruby
180
+ expect { object.action }.to change(object, :value).from(old).to(new)
181
+ expect { object.action }.to change(object, :value).by(delta)
182
+ expect { object.action }.to change(object, :value).by_at_least(minimum_delta)
183
+ expect { object.action }.to change(object, :value).by_at_most(maximum_delta)
184
+ ```
185
+
186
+ #### Satisfy
187
+
188
+ ```ruby
189
+ expect(actual).to(satisfy { |value| value == expected })
190
+ ```
191
+
160
192
  ### Running specs
161
193
 
162
194
  By convention, specs live in the `spec/` directory of a project. Spec files should end with `_spec.rb` to be recognizable as such.
@@ -217,17 +249,23 @@ bundle exec rake
217
249
 
218
250
  ## Performance
219
251
 
252
+ The benchmarks compare the performance of [`r_spec-clone`](https://rubygems.org/gems/r_spec-clone) with the following frameworks (in alphabetical order):
253
+
254
+ * [`fix`](https://rubygems.org/gems/fix)
255
+ * [`minitest`](https://rubygems.org/gems/minitest)
256
+ * [`rspec`](https://rubygems.org/gems/rspec)
257
+
220
258
  ### Boot time
221
259
 
222
260
  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).
223
261
 
224
- ![Boot time](https://r-spec.dev/benchmark-boot-time.svg)
262
+ ![Boot time benchmark](https://r-spec.dev/benchmark-boot-time.svg)
225
263
 
226
- ### Run time
264
+ ### Runtime
227
265
 
228
266
  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).
229
267
 
230
- ![Run time](https://r-spec.dev/benchmark-run-time.svg)
268
+ ![Runtime benchmark](https://r-spec.dev/benchmark-run-time.svg)
231
269
 
232
270
  ## Test suite
233
271
 
@@ -237,6 +275,7 @@ __RSpec clone__'s specifications are self-described here: [spec/](https://github
237
275
 
238
276
  * Home page: [https://r-spec.dev/](https://r-spec.dev/)
239
277
  * Cheatsheet: [https://r-spec.dev/cheatsheet.html](https://r-spec.dev/cheatsheet.html)
278
+ * Blog post: [https://batman.buzz/introducing-a-new-rspec-850d48c0f901](https://batman.buzz/introducing-a-new-rspec-850d48c0f901)
240
279
  * Source code: [https://github.com/cyril/r_spec-clone.rb](https://github.com/cyril/r_spec-clone.rb)
241
280
  * API Doc: [https://rubydoc.info/gems/r_spec-clone](https://rubydoc.info/gems/r_spec-clone)
242
281
  * Twitter: [https://twitter.com/cyri\_](https://twitter.com/cyri\_)
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"
@@ -201,8 +201,8 @@ module RSpec
201
201
  # @param name [String, nil] The name of the spec.
202
202
  # @param block [Proc] An expectation to evaluate.
203
203
  #
204
- # @raise (see RSpec::ExpectationTarget::Base#result)
205
- # @return (see RSpec::ExpectationTarget::Base#result)
204
+ # @raise (see RSpec::Clone::ExpectationTarget::Base#result)
205
+ # @return (see RSpec::Clone::ExpectationTarget::Base#result)
206
206
  def self.it(name = nil, &block)
207
207
  Clone::Dsl.it(name, &block)
208
208
  end
@@ -329,8 +329,7 @@ module RSpec
329
329
  #
330
330
  # @api public
331
331
  def self.it(_name = nil, &block)
332
- example = ::Class.new(self) { include ExpectationHelper::It }.new
333
- run(example, &block)
332
+ run(example_without_attribute.new, &block)
334
333
  end
335
334
 
336
335
  # :nocov:
@@ -417,15 +416,7 @@ module RSpec
417
416
  #
418
417
  # @api public
419
418
  def self.its(attribute, *args, **kwargs, &block)
420
- example = ::Class.new(self) do
421
- include ExpectationHelper::Its
422
-
423
- define_method(:actual) do
424
- subject.public_send(attribute, *args, **kwargs)
425
- end
426
- end.new
427
-
428
- run(example, &block)
419
+ run(example_with_attribute(attribute, *args, **kwargs).new, &block)
429
420
  end
430
421
 
431
422
  # :nocov:
@@ -495,6 +486,25 @@ module RSpec
495
486
  Console.passed_spec Error::PendingExpectation.result(message)
496
487
  end
497
488
 
489
+ # Example class for concrete test case.
490
+ def self.example_without_attribute
491
+ ::Class.new(self) do
492
+ prepend ExpectationHelper::It
493
+ end
494
+ end
495
+
496
+ # Example class for concrete test case that specifies the actual value of
497
+ # an attribute of the subject.
498
+ def self.example_with_attribute(attribute, *args, **kwargs)
499
+ ::Class.new(self) do
500
+ prepend ExpectationHelper::Its
501
+
502
+ define_method(:actual) do
503
+ subject.public_send(attribute, *args, **kwargs)
504
+ end
505
+ end
506
+ end
507
+
498
508
  # Creates a subprocess and runs the block inside.
499
509
  def self.fork!(&block)
500
510
  pid = fork(&block)
@@ -514,7 +524,7 @@ module RSpec
514
524
  example&.send(AFTER_METHOD)
515
525
  end
516
526
 
517
- private_class_method :fork!, :run
527
+ private_class_method :example_without_attribute, :example_with_attribute, :fork!, :run
518
528
 
519
529
  private
520
530
 
@@ -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
@@ -18,8 +18,8 @@ module RSpec
18
18
  # @return [Block, Value] The wrapped target of an expectation.
19
19
  #
20
20
  # @example
21
- # expect("foo") # => #<RSpec::ExpectationTarget::Value:0x00007fb6b823 @actual="foo">
22
- # expect { Boom } # => #<RSpec::ExpectationTarget::Block:0x00007fb6b826 @callable=#<Proc:0x00007fb6b826>>
21
+ # expect("foo") # => #<RSpec::Clone::ExpectationTarget::Value:0x00007f @actual="foo">
22
+ # expect { Boom } # => #<RSpec::Clone::ExpectationTarget::Block:0x00007f @callable=#<Proc:0x00007f>>
23
23
  #
24
24
  # @api public
25
25
  def expect(value = self.class.superclass, &block)
@@ -31,7 +31,7 @@ module RSpec
31
31
  # @return [Block] The wrapped target of an expectation.
32
32
  #
33
33
  # @example
34
- # is_expected # => #<RSpec::ExpectationTarget::Block:0x00007fb6b8263df8 @callable=#<Proc:0x00007fb6b8263e20>>
34
+ # is_expected # => #<RSpec::Clone::ExpectationTarget::Block:0x00007fb6b8 @callable=#<Proc:0x00007fb6b8>>
35
35
  #
36
36
  # @api public
37
37
  def is_expected
@@ -15,7 +15,7 @@ module RSpec
15
15
  # @return [Block] The wrapped target of an expectation.
16
16
  #
17
17
  # @example
18
- # is_expected # => #<RSpec::ExpectationTarget::Block:0x00007fb6b8263df8 @callable=#<Proc:0x00007fb6b8263e20>>
18
+ # is_expected # => #<RSpec::Clone::ExpectationTarget::Block:0x00007f @callable=#<Proc:0x00007f>>
19
19
  #
20
20
  # @api public
21
21
  def is_expected
@@ -1,83 +1,201 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "matchi/rspec"
4
-
5
- require_relative File.join("..", "error", "pending_expectation")
3
+ require "matchi"
6
4
 
7
5
  module RSpec
8
6
  module Clone
9
7
  module ExpectationHelper
10
8
  # Abstract expectation helper base module.
11
9
  #
12
- # This module defines a number of methods to create expectations, which are
13
- # automatically included into examples.
14
- #
15
- # It also includes a collection of expectation matchers 🤹
16
- #
17
- # @example Equivalence matcher
18
- # matcher = eql("foo") # => Matchi::Matcher::Eql.new("foo")
19
- # matcher.matches? { "foo" } # => true
20
- # matcher.matches? { "bar" } # => false
21
- #
22
- # matcher = eq("foo") # => Matchi::Matcher::Eq.new("foo")
23
- # matcher.matches? { "foo" } # => true
24
- # matcher.matches? { "bar" } # => false
25
- #
26
- # @example Identity matcher
27
- # object = "foo"
28
- #
29
- # matcher = equal(object) # => Matchi::Matcher::Equal.new(object)
30
- # matcher.matches? { object } # => true
31
- # matcher.matches? { "foo" } # => false
32
- #
33
- # matcher = be(object) # => Matchi::Matcher::Be.new(object)
34
- # matcher.matches? { object } # => true
35
- # matcher.matches? { "foo" } # => false
36
- #
37
- # @example Regular expressions matcher
38
- # matcher = match(/^foo$/) # => Matchi::Matcher::Match.new(/^foo$/)
39
- # matcher.matches? { "foo" } # => true
40
- # matcher.matches? { "bar" } # => false
41
- #
42
- # @example Expecting errors matcher
43
- # matcher = raise_exception(NameError) # => Matchi::Matcher::RaiseException.new(NameError)
44
- # matcher.matches? { Boom } # => true
45
- # matcher.matches? { true } # => false
46
- #
47
- # @example Truth matcher
48
- # matcher = be_true # => Matchi::Matcher::BeTrue.new
49
- # matcher.matches? { true } # => true
50
- # matcher.matches? { false } # => false
51
- # matcher.matches? { nil } # => false
52
- # matcher.matches? { 4 } # => false
53
- #
54
- # @example Untruth matcher
55
- # matcher = be_false # => Matchi::Matcher::BeFalse.new
56
- # matcher.matches? { false } # => true
57
- # matcher.matches? { true } # => false
58
- # matcher.matches? { nil } # => false
59
- # matcher.matches? { 4 } # => false
60
- #
61
- # @example Nil matcher
62
- # matcher = be_nil # => Matchi::Matcher::BeNil.new
63
- # matcher.matches? { nil } # => true
64
- # matcher.matches? { false } # => false
65
- # matcher.matches? { true } # => false
66
- # matcher.matches? { 4 } # => false
10
+ # This module defines a number of methods to create expectations, which
11
+ # are automatically included into examples.
67
12
  #
68
- # @example Type/class matcher
69
- # matcher = be_instance_of(String) # => Matchi::Matcher::BeInstanceOf.new(String)
70
- # matcher.matches? { "foo" } # => true
71
- # matcher.matches? { 4 } # => false
72
- #
73
- # matcher = be_an_instance_of(String) # => Matchi::Matcher::BeAnInstanceOf.new(String)
74
- # matcher.matches? { "foo" } # => true
75
- # matcher.matches? { 4 } # => false
13
+ # It also includes a collection of expectation matchers.
76
14
  #
77
15
  # @see https://github.com/fixrb/matchi
78
- # @see https://github.com/fixrb/matchi-rspec
79
16
  module Shared
80
- 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
+ # Regular expressions matcher
55
+ #
56
+ # @example
57
+ # matcher = match(/^foo$/)
58
+ # matcher.matches? { "foo" } # => true
59
+ # matcher.matches? { "bar" } # => false
60
+ #
61
+ # @param expected [#match] A regular expression.
62
+ #
63
+ # @return [#matches?] A regular expression matcher.
64
+ #
65
+ # @api public
66
+ def match(expected)
67
+ ::Matchi::Match.new(expected)
68
+ end
69
+
70
+ # Expecting errors matcher
71
+ #
72
+ # @example
73
+ # matcher = raise_exception(NameError)
74
+ # matcher.matches? { Boom } # => true
75
+ # matcher.matches? { true } # => false
76
+ #
77
+ # @param expected [Exception, #to_s] The expected exception name.
78
+ #
79
+ # @return [#matches?] An error matcher.
80
+ #
81
+ # @api public
82
+ def raise_exception(expected)
83
+ ::Matchi::RaiseException.new(expected)
84
+ end
85
+
86
+ # True matcher
87
+ #
88
+ # @example
89
+ # matcher = be_true
90
+ # matcher.matches? { true } # => true
91
+ # matcher.matches? { false } # => false
92
+ # matcher.matches? { nil } # => false
93
+ # matcher.matches? { 4 } # => false
94
+ #
95
+ # @return [#matches?] A `true` matcher.
96
+ #
97
+ # @api public
98
+ def be_true
99
+ be(true)
100
+ end
101
+
102
+ # False matcher
103
+ #
104
+ # @example
105
+ # matcher = be_false
106
+ # matcher.matches? { false } # => true
107
+ # matcher.matches? { true } # => false
108
+ # matcher.matches? { nil } # => false
109
+ # matcher.matches? { 4 } # => false
110
+ #
111
+ # @return [#matches?] A `false` matcher.
112
+ #
113
+ # @api public
114
+ def be_false
115
+ be(false)
116
+ end
117
+
118
+ # Nil matcher
119
+ #
120
+ # @example
121
+ # matcher = be_nil
122
+ # matcher.matches? { nil } # => true
123
+ # matcher.matches? { false } # => false
124
+ # matcher.matches? { true } # => false
125
+ # matcher.matches? { 4 } # => false
126
+ #
127
+ # @return [#matches?] A `nil` matcher.
128
+ #
129
+ # @api public
130
+ def be_nil
131
+ be(nil)
132
+ end
133
+
134
+ # Type/class matcher
135
+ #
136
+ # @example
137
+ # matcher = be_an_instance_of(String)
138
+ # matcher.matches? { "foo" } # => true
139
+ # matcher.matches? { 4 } # => false
140
+ #
141
+ # @param expected [Class, #to_s] The expected class name.
142
+ #
143
+ # @return [#matches?] A type/class matcher.
144
+ #
145
+ # @api public
146
+ def be_an_instance_of(expected)
147
+ ::Matchi::BeAnInstanceOf.new(expected)
148
+ end
149
+
150
+ # Change matcher
151
+ #
152
+ # @example
153
+ # object = []
154
+ # matcher = change(object, :length).by(1)
155
+ # matcher.matches? { object << 1 } # => true
156
+ #
157
+ # object = []
158
+ # matcher = change(object, :length).by_at_least(1)
159
+ # matcher.matches? { object << 1 } # => true
160
+ #
161
+ # object = []
162
+ # matcher = change(object, :length).by_at_most(1)
163
+ # matcher.matches? { object << 1 } # => true
164
+ #
165
+ # object = "foo"
166
+ # matcher = change(object, :to_s).from("foo").to("FOO")
167
+ # matcher.matches? { object.upcase! } # => true
168
+ #
169
+ # object = "foo"
170
+ # matcher = change(object, :to_s).to("FOO")
171
+ # matcher.matches? { object.upcase! } # => true
172
+ #
173
+ # @param object [#object_id] An object.
174
+ # @param method [Symbol] The name of a method.
175
+ # @param args [Array] A list of arguments.
176
+ # @param kwargs [Hash] A list of keyword arguments.
177
+ #
178
+ # @return [#matches?] A change matcher.
179
+ #
180
+ # @api public
181
+ def change(object, method, *args, **kwargs, &block)
182
+ ::Matchi::Change.new(object, method, *args, **kwargs, &block)
183
+ end
184
+
185
+ # Satisfy matcher
186
+ #
187
+ # @example
188
+ # matcher = satisfy { |value| value == 42 }
189
+ # matcher.matches? { 42 } # => true
190
+ #
191
+ # @param expected [Proc] A block of code.
192
+ #
193
+ # @return [#matches?] A satisfy matcher.
194
+ #
195
+ # @api public
196
+ def satisfy(&expected)
197
+ ::Matchi::Satisfy.new(&expected)
198
+ end
81
199
  end
82
200
  end
83
201
  end
@@ -8,8 +8,8 @@ module RSpec
8
8
  # Wraps the target of an expectation.
9
9
  module ExpectationTarget
10
10
  # @param undefined_value A sentinel value to be able to tell when the user
11
- # did not pass an argument. We can't use `nil` for that because `nil` is a
12
- # valid value to pass.
11
+ # did not pass an argument. We can't use `nil` for that because `nil` is
12
+ # a valid value to pass.
13
13
  # @param value [#object_id, nil] An actual value.
14
14
  # @param block [#call, nil] A code to evaluate.
15
15
  #
@@ -10,14 +10,14 @@ module RSpec
10
10
  module ExpectationTarget
11
11
  # Abstract expectation target base class.
12
12
  #
13
- # @note `RSpec::ExpectationTarget::Base` is not intended to be instantiated
14
- # directly by users. Use `expect` instead.
13
+ # @note `RSpec::Clone::ExpectationTarget::Base` is not intended to be
14
+ # instantiated directly by users. Use `expect` instead.
15
15
  class Base
16
16
  # Instantiate a new expectation target.
17
17
  #
18
- # @param actual [#object_id] The actual value of the code to evaluate.
19
- def initialize(actual)
20
- @actual = actual
18
+ # @param input [#object_id, Proc] The code to evaluate.
19
+ def initialize(input)
20
+ @input = input
21
21
  end
22
22
 
23
23
  # Runs the given expectation, passing if `matcher` returns true.
@@ -52,6 +52,36 @@ module RSpec
52
52
 
53
53
  protected
54
54
 
55
+ # @param test [::TestTube::Base] The state of the experiment.
56
+ # @param matcher [#matches?] The matcher.
57
+ # @param negate [Boolean] The assertion is positive or negative.
58
+ #
59
+ # @return [nil] Write a message to STDOUT.
60
+ #
61
+ # @raise [SystemExit] Terminate execution immediately by calling
62
+ # `Kernel.exit(false)` with a failure message written to STDERR.
63
+ def absolute_requirement(test, matcher:, negate:)
64
+ result(
65
+ passed?(test),
66
+ actual: test.actual,
67
+ error: test.error,
68
+ got: test.got,
69
+ matcher: matcher,
70
+ negate: negate
71
+ )
72
+ end
73
+
74
+ # Code experiment result.
75
+ #
76
+ # @param test [::TestTube::Base] The state of the experiment.
77
+ #
78
+ # @see https://github.com/fixrb/test_tube
79
+ #
80
+ # @return [Boolean] The result of the test (passed or failed).
81
+ def passed?(test)
82
+ test.got.equal?(true)
83
+ end
84
+
55
85
  # @param passed [Boolean] The high expectation passed or failed.
56
86
  # @param actual [#object_id] The actual value.
57
87
  # @param error [Exception, nil] Any raised exception.
@@ -65,13 +95,13 @@ module RSpec
65
95
  # `Kernel.exit(false)` with a failure message written to STDERR.
66
96
  def result(passed, actual:, error:, got:, matcher:, negate:)
67
97
  Console.passed_spec ::Expresenter.call(passed).with(
68
- actual: actual,
69
- error: error,
70
- expected: matcher.expected,
71
- got: got,
72
- negate: negate,
73
- matcher: matcher.class.to_sym,
74
- 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
75
105
  )
76
106
  rescue ::Expresenter::Fail => e
77
107
  Console.failed_spec(e)
@@ -16,31 +16,20 @@ module RSpec
16
16
  # # with `not_to`
17
17
  # expect { actual }.not_to be(4)
18
18
  #
19
- # @note `RSpec::ExpectationTarget::Block` is not intended to be instantiated
20
- # directly by users. Use `expect` instead.
19
+ # @note `RSpec::Clone::ExpectationTarget::Block` is not intended to be
20
+ # instantiated directly by users. Use `expect` instead.
21
21
  class Block < Base
22
22
  protected
23
23
 
24
24
  # @param matcher [#matches?] The matcher.
25
25
  # @param negate [Boolean] The assertion is positive or negative.
26
26
  #
27
- # @return [nil] Write a message to STDOUT.
27
+ # @return (see Base#absolute_requirement)
28
28
  #
29
- # @raise [SystemExit] Terminate execution immediately by calling
30
- # `Kernel.exit(false)` with a failure message written to STDERR.
29
+ # @raise (see Base#absolute_requirement)
31
30
  def absolute_requirement(matcher:, negate:)
32
- experiment = ::TestTube.invoke(
33
- @actual,
34
- isolation: false,
35
- matcher: matcher,
36
- negate: negate
37
- )
38
-
39
- result(
40
- experiment.got.equal?(true),
41
- actual: experiment.actual,
42
- error: experiment.error,
43
- got: experiment.got,
31
+ super(
32
+ ::TestTube.invoke(isolate: false, matcher: matcher, negate: negate, &@input),
44
33
  matcher: matcher,
45
34
  negate: negate
46
35
  )
@@ -16,30 +16,20 @@ module RSpec
16
16
  # # with `not_to`
17
17
  # expect(actual).not_to be(4)
18
18
  #
19
- # @note `RSpec::ExpectationTarget::Value` is not intended to be instantiated
20
- # directly by users. Use `expect` instead.
19
+ # @note `RSpec::Clone::ExpectationTarget::Value` is not intended to be
20
+ # instantiated directly by users. Use `expect` instead.
21
21
  class Value < Base
22
22
  protected
23
23
 
24
24
  # @param matcher [#matches?] The matcher.
25
25
  # @param negate [Boolean] The assertion is positive or negative.
26
26
  #
27
- # @return [nil] Write a message to STDOUT.
27
+ # @return (see Base#absolute_requirement)
28
28
  #
29
- # @raise [SystemExit] Terminate execution immediately by calling
30
- # `Kernel.exit(false)` with a failure message written to STDERR.
29
+ # @raise (see Base#absolute_requirement)
31
30
  def absolute_requirement(matcher:, negate:)
32
- experiment = ::TestTube.pass(
33
- @actual,
34
- matcher: matcher,
35
- negate: negate
36
- )
37
-
38
- result(
39
- experiment.got.equal?(true),
40
- actual: experiment.actual,
41
- error: experiment.error,
42
- got: experiment.got,
31
+ super(
32
+ ::TestTube.pass(@input, matcher: matcher, negate: negate),
43
33
  matcher: matcher,
44
34
  negate: negate
45
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.1
4
+ version: 1.3.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-02 00:00:00.000000000 Z
11
+ date: 2021-07-23 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.1.1
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.1.1
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: 1.1.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: 1.1.0
54
+ version: 2.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement