r_spec-clone 1.7.2 → 2.0.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/LICENSE.md +1 -1
- data/README.md +138 -237
- data/lib/r_spec/clone/dsl.rb +165 -189
- data/lib/r_spec/clone/error.rb +14 -6
- data/lib/r_spec/clone/expectation_helper/it.rb +19 -21
- data/lib/r_spec/clone/expectation_helper/matcher.rb +115 -0
- data/lib/r_spec/clone/expectation_helper.rb +3 -2
- data/lib/r_spec/clone/expectation_target.rb +50 -18
- data/lib/r_spec/clone/report.rb +65 -0
- data/lib/r_spec/clone.rb +1 -3
- data/lib/r_spec.rb +37 -109
- metadata +20 -29
- data/lib/r_spec/clone/error/pending_expectation.rb +0 -26
- data/lib/r_spec/clone/error/reserved_method.rb +0 -11
- data/lib/r_spec/clone/error/undefined_described_class.rb +0 -11
- data/lib/r_spec/clone/error/undefined_subject.rb +0 -11
- data/lib/r_spec/clone/expectation_helper/its.rb +0 -27
- data/lib/r_spec/clone/expectation_helper/shared.rb +0 -250
- data/lib/r_spec/clone/expectation_target/base.rb +0 -115
- data/lib/r_spec/clone/expectation_target/block.rb +0 -40
- data/lib/r_spec/clone/expectation_target/value.rb +0 -40
- data/lib/r_spec/clone/logger.rb +0 -42
data/lib/r_spec/clone/dsl.rb
CHANGED
|
@@ -1,91 +1,123 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require "defi"
|
|
4
|
+
|
|
4
5
|
require_relative "error"
|
|
5
6
|
require_relative "expectation_helper"
|
|
7
|
+
require_relative "report"
|
|
6
8
|
|
|
7
9
|
module RSpec
|
|
8
10
|
module Clone
|
|
9
|
-
#
|
|
11
|
+
# The language of a spec. An example group, `describe` or `context`, is
|
|
12
|
+
# a subclass of the enclosing one; `let`, `subject` and `before` define
|
|
13
|
+
# methods on it, which a nested group inherits and may redefine, with
|
|
14
|
+
# `super` at hand; an example is an instance of a class of its own,
|
|
15
|
+
# built when `it` or `its` runs it, in the order of the file.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# require "r_spec"
|
|
19
|
+
#
|
|
20
|
+
# RSpec.describe "Name stories" do
|
|
21
|
+
# let(:name) { "Bob" }
|
|
22
|
+
#
|
|
23
|
+
# it { expect(name).to eq "Bob" }
|
|
24
|
+
#
|
|
25
|
+
# context "with a last name" do
|
|
26
|
+
# let(:name) { "#{super()} Smith" }
|
|
27
|
+
#
|
|
28
|
+
# it { expect(name).to eq "Bob Smith" }
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # spec/name_spec.rb:6: Success: expected "Bob" to eq "Bob"
|
|
33
|
+
# # spec/name_spec.rb:11: Success: expected "Bob Smith" to eq "Bob Smith"
|
|
10
34
|
class Dsl
|
|
11
35
|
BEFORE_METHOD = :initialize
|
|
36
|
+
# The words of an example, which a helper cannot take.
|
|
37
|
+
WORDS = ExpectationHelper::It
|
|
12
38
|
|
|
13
|
-
private_constant :BEFORE_METHOD
|
|
39
|
+
private_constant :BEFORE_METHOD, :WORDS
|
|
14
40
|
|
|
15
|
-
#
|
|
41
|
+
# Runs the block before each example of the group, after the blocks
|
|
42
|
+
# of the enclosing groups and those written before it in the group,
|
|
43
|
+
# in the example itself: an instance variable set here is seen by the
|
|
44
|
+
# example. Each block is the hook of a module of its own, included in
|
|
45
|
+
# the group, so that the blocks chain through `super`.
|
|
16
46
|
#
|
|
17
47
|
# @example
|
|
18
48
|
# require "r_spec"
|
|
19
49
|
#
|
|
20
50
|
# RSpec.describe Integer do
|
|
21
|
-
# before
|
|
22
|
-
# @value = 123
|
|
23
|
-
# end
|
|
51
|
+
# before { @value = 123 }
|
|
24
52
|
#
|
|
25
53
|
# it { expect(@value).to be 123 }
|
|
26
54
|
#
|
|
27
55
|
# describe "nested" do
|
|
28
|
-
# before
|
|
29
|
-
# @value -= 81
|
|
30
|
-
# end
|
|
56
|
+
# before { @value -= 81 }
|
|
31
57
|
#
|
|
32
58
|
# it { expect(@value).to be 42 }
|
|
33
59
|
# end
|
|
34
|
-
#
|
|
35
|
-
# it { expect(@value).to be 123 }
|
|
36
60
|
# end
|
|
37
61
|
#
|
|
38
|
-
# #
|
|
39
|
-
# #
|
|
40
|
-
# # Success: expected to be 42.
|
|
41
|
-
# # Success: expected to be 123.
|
|
62
|
+
# # spec/before_spec.rb:6: Success: expected 123 to be 123
|
|
63
|
+
# # spec/before_spec.rb:11: Success: expected 42 to be 42
|
|
42
64
|
#
|
|
43
|
-
# @
|
|
65
|
+
# @yield the block to run before each example
|
|
66
|
+
# @return [nil]
|
|
67
|
+
# @raise [ArgumentError] without a block
|
|
44
68
|
#
|
|
45
69
|
# @api public
|
|
46
70
|
def self.before(&block)
|
|
47
|
-
|
|
48
|
-
super()
|
|
49
|
-
instance_eval(&block)
|
|
50
|
-
end
|
|
71
|
+
raise ::ArgumentError, "a block must be given" unless block
|
|
51
72
|
|
|
52
|
-
|
|
73
|
+
hook = ::Module.new do
|
|
74
|
+
define_method(BEFORE_METHOD) do
|
|
75
|
+
super()
|
|
76
|
+
instance_eval(&block)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
include hook
|
|
80
|
+
nil
|
|
53
81
|
end
|
|
54
82
|
|
|
55
|
-
#
|
|
83
|
+
# Defines a helper method, called each time it is used: nothing is
|
|
84
|
+
# memoized.
|
|
56
85
|
#
|
|
57
86
|
# @example
|
|
58
87
|
# require "r_spec"
|
|
59
88
|
#
|
|
60
|
-
# RSpec.describe
|
|
61
|
-
# let(:
|
|
89
|
+
# RSpec.describe Integer do
|
|
90
|
+
# let(:answer) { 42 }
|
|
62
91
|
#
|
|
63
|
-
# it { expect(
|
|
92
|
+
# it { expect(answer).to be 42 }
|
|
64
93
|
#
|
|
65
|
-
# context "
|
|
66
|
-
# let(:
|
|
94
|
+
# context "when incremented" do
|
|
95
|
+
# let(:answer) { super().next }
|
|
67
96
|
#
|
|
68
|
-
# it { expect(
|
|
97
|
+
# it { expect(answer).to be 43 }
|
|
69
98
|
# end
|
|
70
99
|
# end
|
|
71
100
|
#
|
|
72
|
-
# #
|
|
73
|
-
# #
|
|
74
|
-
# # Success: expected to eq "Bob Smith".
|
|
101
|
+
# # spec/let_spec.rb:6: Success: expected 42 to be 42
|
|
102
|
+
# # spec/let_spec.rb:11: Success: expected 43 to be 43
|
|
75
103
|
#
|
|
76
|
-
# @param name
|
|
77
|
-
# @
|
|
78
|
-
#
|
|
79
|
-
# @
|
|
104
|
+
# @param name [Symbol, String] the name of the helper
|
|
105
|
+
# @yield the body of the helper, with its parameters
|
|
106
|
+
# @return [Symbol] the name of the helper
|
|
107
|
+
# @raise [Error::ReservedMethod] for the name of the hook, or a word
|
|
108
|
+
# of the example (`expect`, `is_expected`, a matcher), which the
|
|
109
|
+
# helper could not reach
|
|
80
110
|
#
|
|
81
111
|
# @api public
|
|
82
112
|
def self.let(name, ...)
|
|
83
|
-
|
|
113
|
+
name = name.to_sym
|
|
114
|
+
reserved = BEFORE_METHOD.equal?(name) || WORDS.method_defined?(name) || WORDS.private_method_defined?(name)
|
|
115
|
+
raise Error::ReservedMethod, "#{name} is reserved" if reserved
|
|
84
116
|
|
|
85
117
|
private define_method(name, ...)
|
|
86
118
|
end
|
|
87
119
|
|
|
88
|
-
#
|
|
120
|
+
# Defines the subject, a helper named `subject`.
|
|
89
121
|
#
|
|
90
122
|
# @example
|
|
91
123
|
# require "r_spec"
|
|
@@ -93,108 +125,96 @@ module RSpec
|
|
|
93
125
|
# RSpec.describe Array do
|
|
94
126
|
# subject { [1, 2, 3] }
|
|
95
127
|
#
|
|
96
|
-
# it
|
|
97
|
-
# expect(subject).to eq([1, 2, 3])
|
|
98
|
-
# end
|
|
99
|
-
#
|
|
128
|
+
# it { expect(subject).to eq [1, 2, 3] }
|
|
100
129
|
# it { is_expected.to be_an_instance_of described_class }
|
|
101
|
-
#
|
|
102
130
|
# its(:size) { is_expected.to be 3 }
|
|
103
|
-
# its(:downcase) { is_expected.to raise_exception NoMethodError }
|
|
104
131
|
# end
|
|
105
132
|
#
|
|
106
|
-
# #
|
|
107
|
-
# #
|
|
108
|
-
# #
|
|
109
|
-
# # Success: expected to be 3.
|
|
110
|
-
# # Success: undefined method `downcase' for [1, 2, 3]:Array.
|
|
133
|
+
# # spec/subject_spec.rb:6: Success: expected [1, 2, 3] to eq [1, 2, 3]
|
|
134
|
+
# # spec/subject_spec.rb:7: Success: expected [1, 2, 3] to be an instance of Array
|
|
135
|
+
# # spec/subject_spec.rb:8: Success: expected 3 to be 3
|
|
111
136
|
#
|
|
112
|
-
# @
|
|
113
|
-
# @return [Symbol]
|
|
137
|
+
# @yield the body of the subject
|
|
138
|
+
# @return [Symbol] `:subject`
|
|
114
139
|
#
|
|
115
140
|
# @api public
|
|
116
141
|
def self.subject(&)
|
|
117
142
|
let(__method__, &)
|
|
118
143
|
end
|
|
119
144
|
|
|
120
|
-
# Defines an example group that describes a unit to be tested.
|
|
145
|
+
# Defines an example group that describes a unit to be tested. A
|
|
146
|
+
# module given makes `described_class` return it.
|
|
121
147
|
#
|
|
122
148
|
# @example
|
|
123
149
|
# require "r_spec"
|
|
124
150
|
#
|
|
125
151
|
# RSpec.describe String do
|
|
126
|
-
# describe "
|
|
127
|
-
# it("
|
|
152
|
+
# describe "#+" do
|
|
153
|
+
# it("concatenates") { expect("foo" + "bar").to eq "foobar" }
|
|
128
154
|
# end
|
|
129
155
|
# end
|
|
130
156
|
#
|
|
131
|
-
# #
|
|
132
|
-
# # Success: expected to eq "foobar".
|
|
157
|
+
# # spec/string_spec.rb:5: Success: expected "foobar" to eq "foobar"
|
|
133
158
|
#
|
|
134
|
-
# @param const [Module, String]
|
|
135
|
-
# @
|
|
159
|
+
# @param const [Module, String] the module under test, or a description
|
|
160
|
+
# @yield the specs of the group
|
|
161
|
+
# @return [nil]
|
|
162
|
+
# @raise [ArgumentError] without a block
|
|
136
163
|
#
|
|
137
164
|
# @api public
|
|
138
|
-
def self.describe(const, &)
|
|
139
|
-
|
|
140
|
-
desc.let(:described_class) { const } if const.is_a?(::Module)
|
|
141
|
-
desc.instance_eval(&)
|
|
142
|
-
end
|
|
165
|
+
def self.describe(const, &block)
|
|
166
|
+
raise ::ArgumentError, "a block must be given" unless block
|
|
143
167
|
|
|
144
|
-
|
|
168
|
+
group = ::Class.new(self)
|
|
169
|
+
group.let(:described_class) { const } if ::Module === const
|
|
170
|
+
group.instance_eval(&block)
|
|
171
|
+
nil
|
|
172
|
+
end
|
|
145
173
|
|
|
146
|
-
# Defines an example group that establishes a
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
# effects on the Ruby object environment from being propagated outside
|
|
152
|
-
# their context, which could alter the result of the unit test suite.
|
|
174
|
+
# Defines an example group that establishes a context, like _empty
|
|
175
|
+
# array_ versus _array with elements_, and runs it in a child process:
|
|
176
|
+
# what its specs change in the Ruby process, a constant, a global, the
|
|
177
|
+
# subject itself, stays in the child. The parent exits with the status
|
|
178
|
+
# 1 when the child did not succeed.
|
|
153
179
|
#
|
|
154
180
|
# @example
|
|
155
181
|
# require "r_spec"
|
|
156
182
|
#
|
|
157
|
-
# RSpec.describe "web resource" do
|
|
158
|
-
# context "when
|
|
183
|
+
# RSpec.describe "a web resource" do
|
|
184
|
+
# context "when it is not found" do
|
|
159
185
|
# pending "responds with 404"
|
|
160
186
|
# end
|
|
161
187
|
#
|
|
162
|
-
# context "when
|
|
188
|
+
# context "when it is found" do
|
|
163
189
|
# pending "responds with 200"
|
|
164
190
|
# end
|
|
165
191
|
# end
|
|
166
192
|
#
|
|
167
|
-
# #
|
|
168
|
-
# #
|
|
169
|
-
# # Warning: responds with 200.
|
|
193
|
+
# # spec/resource_spec.rb:5: Pending: responds with 404
|
|
194
|
+
# # spec/resource_spec.rb:9: Pending: responds with 200
|
|
170
195
|
#
|
|
171
|
-
# @param _description [String]
|
|
172
|
-
# "when", "with" or "without"
|
|
173
|
-
# @
|
|
196
|
+
# @param _description [String] a description, usually beginning with
|
|
197
|
+
# "when", "with" or "without"
|
|
198
|
+
# @yield the specs of the context
|
|
199
|
+
# @return [nil]
|
|
200
|
+
# @raise [ArgumentError] without a block
|
|
201
|
+
# @raise [NotImplementedError] when this Ruby cannot fork
|
|
202
|
+
# @raise [SystemExit] when a spec of the context did not succeed
|
|
174
203
|
#
|
|
175
204
|
# @api public
|
|
176
205
|
def self.context(_description, &block)
|
|
206
|
+
raise ::ArgumentError, "a block must be given" unless block
|
|
207
|
+
|
|
177
208
|
pid = ::Process.fork { ::Class.new(self).instance_eval(&block) }
|
|
178
|
-
exit
|
|
209
|
+
exit(false) unless ::Process.wait2(pid).last.success?
|
|
210
|
+
nil
|
|
179
211
|
end
|
|
180
212
|
|
|
181
|
-
# :
|
|
182
|
-
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
# The test is performed by the block supplied to `&block`.
|
|
186
|
-
#
|
|
187
|
-
# @example The integer after 41
|
|
188
|
-
# require "r_spec"
|
|
189
|
-
#
|
|
190
|
-
# RSpec.describe Integer do
|
|
191
|
-
# it { expect(41.next).to be 42 }
|
|
192
|
-
# end
|
|
213
|
+
# Defines a concrete test case, and runs it: the block is evaluated
|
|
214
|
+
# in a new example, where `expect`, `is_expected` and the matchers
|
|
215
|
+
# are words.
|
|
193
216
|
#
|
|
194
|
-
#
|
|
195
|
-
# # Success: expected to be 42.
|
|
196
|
-
#
|
|
197
|
-
# @example A division by zero
|
|
217
|
+
# @example
|
|
198
218
|
# require "r_spec"
|
|
199
219
|
#
|
|
200
220
|
# RSpec.describe Integer do
|
|
@@ -202,89 +222,69 @@ module RSpec
|
|
|
202
222
|
#
|
|
203
223
|
# it { is_expected.to be_an_instance_of described_class }
|
|
204
224
|
#
|
|
205
|
-
# it "raises
|
|
225
|
+
# it "raises on a division by zero" do
|
|
206
226
|
# expect { subject / 0 }.to raise_exception ZeroDivisionError
|
|
207
227
|
# end
|
|
208
228
|
# end
|
|
209
229
|
#
|
|
210
|
-
# #
|
|
211
|
-
# #
|
|
212
|
-
# # Success: divided by 0.
|
|
213
|
-
#
|
|
214
|
-
# It can be used inside a {.describe} or {.context} section.
|
|
215
|
-
#
|
|
216
|
-
# @param _name [String, nil] The name of the spec.
|
|
217
|
-
# @param block [Proc] An expectation to evaluate.
|
|
230
|
+
# # spec/integer_spec.rb:6: Success: expected 41 to be an instance of Integer
|
|
231
|
+
# # spec/integer_spec.rb:9: Success: expected #<ZeroDivisionError: divided by 0> to raise exception ZeroDivisionError
|
|
218
232
|
#
|
|
219
|
-
# @
|
|
220
|
-
# @
|
|
233
|
+
# @param _name [String, nil] the name of the example
|
|
234
|
+
# @yield the example, with its expectations
|
|
235
|
+
# @return [nil]
|
|
236
|
+
# @raise [ArgumentError] without a block
|
|
237
|
+
# @raise [SystemExit] when an expectation is not met
|
|
221
238
|
#
|
|
222
239
|
# @api public
|
|
223
240
|
def self.it(_name = nil, &block)
|
|
224
|
-
|
|
225
|
-
example_without_attribute.new.instance_eval(&block)
|
|
226
|
-
end
|
|
241
|
+
raise ::ArgumentError, "a block must be given" unless block
|
|
227
242
|
|
|
228
|
-
|
|
243
|
+
::Class.new(self) { prepend ExpectationHelper::It }.new.instance_eval(&block)
|
|
244
|
+
nil
|
|
245
|
+
end
|
|
229
246
|
|
|
230
|
-
# Defines a
|
|
231
|
-
#
|
|
247
|
+
# Defines a concrete test case about an attribute of the subject, and
|
|
248
|
+
# runs it: `is_expected`, the one word of the example with the
|
|
249
|
+
# matchers, wraps the attribute, sent to the subject with the
|
|
250
|
+
# arguments when the matcher asks for it, so that what it raises can
|
|
251
|
+
# be expected too.
|
|
232
252
|
#
|
|
233
|
-
# @example
|
|
253
|
+
# @example
|
|
234
254
|
# require "r_spec"
|
|
235
255
|
#
|
|
236
256
|
# RSpec.describe Integer do
|
|
237
257
|
# subject { 41 }
|
|
238
258
|
#
|
|
239
259
|
# its(:next) { is_expected.to be 42 }
|
|
240
|
-
# end
|
|
241
|
-
#
|
|
242
|
-
# # Output to the console
|
|
243
|
-
# # Success: expected to be 42.
|
|
244
|
-
#
|
|
245
|
-
# @example A division by zero
|
|
246
|
-
# require "r_spec"
|
|
247
|
-
#
|
|
248
|
-
# RSpec.describe Integer do
|
|
249
|
-
# subject { 41 }
|
|
250
|
-
#
|
|
251
260
|
# its(:/, 0) { is_expected.to raise_exception ZeroDivisionError }
|
|
252
261
|
# end
|
|
253
262
|
#
|
|
254
|
-
# #
|
|
255
|
-
# #
|
|
256
|
-
#
|
|
257
|
-
# @example A spec without subject
|
|
258
|
-
# require "r_spec"
|
|
259
|
-
#
|
|
260
|
-
# RSpec.describe Integer do
|
|
261
|
-
# its(:abs) { is_expected.to raise_exception RSpec::Clone::Error::UndefinedSubject }
|
|
262
|
-
# end
|
|
263
|
-
#
|
|
264
|
-
# # Output to the console
|
|
265
|
-
# # Success: subject not explicitly defined.
|
|
266
|
-
#
|
|
267
|
-
# @param attribute [String, Symbol] The property to call to subject.
|
|
268
|
-
# @param args [Array] An optional list of arguments.
|
|
269
|
-
# @param kwargs [Hash] An optional list of keyword arguments.
|
|
270
|
-
# @param block [Proc] An expectation to evaluate.
|
|
263
|
+
# # spec/its_spec.rb:6: Success: expected 42 to be 42
|
|
264
|
+
# # spec/its_spec.rb:7: Success: expected #<ZeroDivisionError: divided by 0> to raise exception ZeroDivisionError
|
|
271
265
|
#
|
|
272
|
-
# @
|
|
273
|
-
#
|
|
266
|
+
# @param attribute [Symbol] the method to send to the subject, followed
|
|
267
|
+
# by its arguments
|
|
268
|
+
# @yield the example, with its expectation
|
|
269
|
+
# @return [nil]
|
|
270
|
+
# @raise [ArgumentError] without a block, or when the attribute is not
|
|
271
|
+
# a Symbol
|
|
272
|
+
# @raise [SystemExit] when the expectation is not met
|
|
274
273
|
#
|
|
275
274
|
# @api public
|
|
276
275
|
def self.its(attribute, *, **, &block)
|
|
277
|
-
|
|
278
|
-
example_with_attribute(attribute, *, **).new
|
|
279
|
-
.instance_eval(&block)
|
|
280
|
-
end
|
|
276
|
+
raise ::ArgumentError, "a block must be given" unless block
|
|
281
277
|
|
|
282
|
-
|
|
278
|
+
challenge = ::Defi::Challenge.new(attribute, *, **)
|
|
279
|
+
example = ::Class.new(self) do
|
|
280
|
+
prepend ExpectationHelper::Matcher
|
|
281
|
+
define_method(:is_expected) { ExpectationTarget.new(-> { challenge.to(subject).call }) }
|
|
282
|
+
end
|
|
283
|
+
example.new.instance_eval(&block)
|
|
284
|
+
nil
|
|
285
|
+
end
|
|
283
286
|
|
|
284
|
-
# Defines a pending test case.
|
|
285
|
-
#
|
|
286
|
-
# `&block` is never evaluated. It can be used to describe behaviour that
|
|
287
|
-
# is not yet implemented.
|
|
287
|
+
# Defines a pending test case: its block, if any, is never run.
|
|
288
288
|
#
|
|
289
289
|
# @example
|
|
290
290
|
# require "r_spec"
|
|
@@ -294,53 +294,29 @@ module RSpec
|
|
|
294
294
|
# expect something to be finished
|
|
295
295
|
# end
|
|
296
296
|
#
|
|
297
|
-
# pending "is not yet implemented
|
|
297
|
+
# pending "is not yet implemented"
|
|
298
298
|
# end
|
|
299
299
|
#
|
|
300
|
-
# #
|
|
301
|
-
# #
|
|
302
|
-
# # Warning: is not yet implemented and waiting.
|
|
300
|
+
# # spec/pending_spec.rb:4: Pending: is implemented but waiting
|
|
301
|
+
# # spec/pending_spec.rb:8: Pending: is not yet implemented
|
|
303
302
|
#
|
|
304
|
-
# @param message [String]
|
|
305
|
-
#
|
|
306
|
-
# @return [nil]
|
|
303
|
+
# @param message [String] why the example is pending
|
|
304
|
+
# @yield never: the block is not run
|
|
305
|
+
# @return [nil]
|
|
307
306
|
#
|
|
308
307
|
# @api public
|
|
309
|
-
def self.pending(message)
|
|
310
|
-
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
# Example class for concrete test case.
|
|
314
|
-
def self.example_without_attribute
|
|
315
|
-
::Class.new(self) do
|
|
316
|
-
prepend ExpectationHelper::It
|
|
317
|
-
end
|
|
308
|
+
def self.pending(message, &)
|
|
309
|
+
Report.pending(Report.location, message)
|
|
318
310
|
end
|
|
319
311
|
|
|
320
|
-
# Example class for concrete test case that specifies the actual value of
|
|
321
|
-
# an attribute of the subject.
|
|
322
|
-
def self.example_with_attribute(attribute, *args, **kwargs)
|
|
323
|
-
::Class.new(self) do
|
|
324
|
-
prepend ExpectationHelper::Its
|
|
325
|
-
|
|
326
|
-
define_method(:actual) do
|
|
327
|
-
subject.public_send(attribute, *args, **kwargs)
|
|
328
|
-
end
|
|
329
|
-
end
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
private_class_method :example_without_attribute, :example_with_attribute
|
|
333
|
-
|
|
334
312
|
private
|
|
335
313
|
|
|
336
|
-
#
|
|
337
|
-
# module), this method will be overridden to return it.
|
|
314
|
+
# Overridden by `describe` when it is given a module.
|
|
338
315
|
def described_class
|
|
339
|
-
raise Error::UndefinedDescribedClass,
|
|
340
|
-
"the first argument to at least one example group must be a module"
|
|
316
|
+
raise Error::UndefinedDescribedClass, "the first argument to at least one example group must be a module"
|
|
341
317
|
end
|
|
342
318
|
|
|
343
|
-
#
|
|
319
|
+
# Overridden by `subject`.
|
|
344
320
|
def subject
|
|
345
321
|
raise Error::UndefinedSubject, "subject not explicitly defined"
|
|
346
322
|
end
|
data/lib/r_spec/clone/error.rb
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative File.join("error", "pending_expectation")
|
|
4
|
-
require_relative File.join("error", "reserved_method")
|
|
5
|
-
require_relative File.join("error", "undefined_described_class")
|
|
6
|
-
require_relative File.join("error", "undefined_subject")
|
|
7
|
-
|
|
8
3
|
module RSpec
|
|
9
4
|
module Clone
|
|
10
|
-
#
|
|
5
|
+
# The errors of the clone, raised where a spec asks for what it did not
|
|
6
|
+
# define.
|
|
11
7
|
module Error
|
|
8
|
+
# Raised by `let` for a name the clone keeps for itself.
|
|
9
|
+
class ReservedMethod < ::RuntimeError
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Raised by `described_class` when no enclosing `describe` names a
|
|
13
|
+
# module.
|
|
14
|
+
class UndefinedDescribedClass < ::RuntimeError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Raised by `subject` when no enclosing group defines one.
|
|
18
|
+
class UndefinedSubject < ::RuntimeError
|
|
19
|
+
end
|
|
12
20
|
end
|
|
13
21
|
end
|
|
14
22
|
end
|
|
@@ -1,39 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "matcher"
|
|
4
4
|
require_relative File.join("..", "expectation_target")
|
|
5
5
|
|
|
6
6
|
module RSpec
|
|
7
7
|
module Clone
|
|
8
8
|
module ExpectationHelper
|
|
9
|
-
#
|
|
9
|
+
# The words of an `it` example: `expect`, `is_expected` and the
|
|
10
|
+
# matchers.
|
|
10
11
|
module It
|
|
11
|
-
include
|
|
12
|
+
include Matcher
|
|
12
13
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# @param value [#object_id, nil] An actual value.
|
|
16
|
-
# @param block [#call, nil] A code to evaluate.
|
|
17
|
-
#
|
|
18
|
-
# @return [Block, Value] The wrapped target of an expectation.
|
|
14
|
+
# Wraps the target of an expectation: a value, or a block whose
|
|
15
|
+
# value or exception the matcher judges.
|
|
19
16
|
#
|
|
20
17
|
# @example
|
|
21
|
-
# expect("foo")
|
|
22
|
-
# expect {
|
|
18
|
+
# expect("foo")
|
|
19
|
+
# expect { 1 / 0 }
|
|
23
20
|
#
|
|
24
|
-
# @
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
# @param values [Array] the actual value, when no block is given
|
|
22
|
+
# @yieldreturn [Object] the actual value
|
|
23
|
+
# @return [ExpectationTarget]
|
|
24
|
+
# @raise [ArgumentError] with both a value and a block, or neither
|
|
25
|
+
def expect(*values, &block)
|
|
26
|
+
raise ::ArgumentError, "expect takes one value or a block" unless values.size + (block ? 1 : 0) == 1
|
|
27
|
+
|
|
28
|
+
ExpectationTarget.new(block || -> { values.fetch(0) })
|
|
27
29
|
end
|
|
28
30
|
|
|
29
|
-
# Wraps the
|
|
30
|
-
#
|
|
31
|
-
# @return [Block] The wrapped target of an expectation.
|
|
32
|
-
#
|
|
33
|
-
# @example
|
|
34
|
-
# is_expected # => #<RSpec::Clone::ExpectationTarget::Block:0x00007fb6b8 @callable=#<Proc:0x00007fb6b8>>
|
|
31
|
+
# Wraps the subject as a block: `is_expected.to raise_exception X`
|
|
32
|
+
# judges what `subject` raises.
|
|
35
33
|
#
|
|
36
|
-
# @
|
|
34
|
+
# @return [ExpectationTarget]
|
|
37
35
|
def is_expected
|
|
38
36
|
expect { subject }
|
|
39
37
|
end
|