Class: Crspec::ExampleGroup
Constant Summary
collapse
- FORBIDDEN_HOOK_SCOPES =
%i[all context suite].freeze
Crspec::Expectations::ExpectationNotMetError, Crspec::Expectations::UNDEFINED
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#after(*args, **kwargs, &block) ⇒ Object
-
#ancestor_eager_lets ⇒ Object
-
#ancestor_hooks(type, example = nil) ⇒ Object
-
#ancestor_included_modules ⇒ Object
-
#ancestor_let_blocks ⇒ Object
-
#ancestor_metadata ⇒ Object
-
#around(*args, **kwargs, &block) ⇒ Object
-
#attr_accessor(*names) ⇒ Object
-
#attr_reader(*names) ⇒ Object
-
#attr_writer(*names) ⇒ Object
-
#before(*args, **kwargs, &block) ⇒ Object
-
#create_instance(example) ⇒ Object
-
#describe(*args, **kwargs, &block) ⇒ Object
(also: #context)
-
#described_class ⇒ Object
-
#effective_type_for(example) ⇒ Object
-
#fdescribe(*args, **kwargs, &block) ⇒ Object
(also: #fcontext)
-
#finalize! ⇒ Object
-
#fit(description = nil, metadata = {}, &block) ⇒ Object
-
#focused? ⇒ Boolean
-
#include(mod) ⇒ Object
-
#initialize(description, metadata = {}, parent = nil) ⇒ ExampleGroup
constructor
A new instance of ExampleGroup.
-
#it(description = nil, metadata = {}, &block) ⇒ Object
(also: #specify)
-
#let(name, &block) ⇒ Object
-
#let!(name, &block) ⇒ Object
-
#mark_focused! ⇒ Object
-
#mark_pending! ⇒ Object
-
#modules_for_example(example) ⇒ Object
-
#pending? ⇒ Boolean
-
#private(*args) ⇒ Object
-
#protected(*args) ⇒ Object
-
#public(*args) ⇒ Object
-
#reject_serial_scope!(hook_name, args) ⇒ Object
-
#render_views(*args) ⇒ Object
-
#run_eager_lets(instance) ⇒ Object
-
#subject(name = nil, &block) ⇒ Object
-
#xdescribe(*args, **kwargs, &block) ⇒ Object
(also: #xcontext)
-
#xit(description = nil, metadata = {}, &block) ⇒ Object
(also: #pending, #skip)
Methods included from SharedDSL
#include_context, #it_behaves_like, #shared_examples
Methods included from Mock::DSL
#allow, #allow_any_instance_of, #double, #expect_any_instance_of, #have_received, #instance_double, #receive, #receive_messages, #spy
#an_instance_of, #anything, args_match?, #array_including, #duck_type, #hash_excluding, #hash_including, #kind_of, kwargs_match?
#aggregate_failures, #expect, #is_expected
Methods included from Matchers
#all, #be, #be_a, #be_an_instance_of, #be_falsy, #be_nil, #be_truthy, #be_within, #change, #contain_exactly, #end_with, #eq, #have_attributes, #have_http_status, #match, #match_array, #method_missing, #output, #raise_error, #respond_to, #respond_to_missing?, #satisfy, #start_with, #yield_control, #yield_successive_args, #yield_with_args
Constructor Details
#initialize(description, metadata = {}, parent = nil) ⇒ ExampleGroup
Returns a new instance of ExampleGroup.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/crspec/example_group.rb', line 19
def initialize(description, metadata = {}, parent = nil)
@description = description
@described_module = description.is_a?(Module) ? description : nil
@metadata = metadata.freeze
@parent = parent
@examples = []
@children = []
@before_hooks = []
@after_hooks = []
@around_hooks = []
@let_blocks = {}
@eager_lets = []
@included_modules = []
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
in the class Crspec::Matchers
Instance Attribute Details
#after_hooks ⇒ Object
Returns the value of attribute after_hooks.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def after_hooks
@after_hooks
end
|
#around_hooks ⇒ Object
Returns the value of attribute around_hooks.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def around_hooks
@around_hooks
end
|
#before_hooks ⇒ Object
Returns the value of attribute before_hooks.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def before_hooks
@before_hooks
end
|
#children ⇒ Object
Returns the value of attribute children.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def children
@children
end
|
#described_module ⇒ Object
Returns the value of attribute described_module.
17
18
19
|
# File 'lib/crspec/example_group.rb', line 17
def described_module
@described_module
end
|
#description ⇒ Object
Returns the value of attribute description.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def description
@description
end
|
#examples ⇒ Object
Returns the value of attribute examples.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def examples
@examples
end
|
Returns the value of attribute metadata.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def metadata
@metadata
end
|
#parent ⇒ Object
Returns the value of attribute parent.
16
17
18
|
# File 'lib/crspec/example_group.rb', line 16
def parent
@parent
end
|
Class Method Details
.define(description, metadata = {}, parent = nil, &block) ⇒ Object
34
35
36
37
38
|
# File 'lib/crspec/example_group.rb', line 34
def self.define(description, metadata = {}, parent = nil, &block)
group = new(description, metadata, parent)
group.instance_eval(&block) if block
group
end
|
Instance Method Details
#after(*args, **kwargs, &block) ⇒ Object
170
171
172
173
|
# File 'lib/crspec/example_group.rb', line 170
def after(*args, **kwargs, &block)
reject_serial_scope!(:after, args)
@after_hooks.unshift({ block: block, filters: args, kwfilters: kwargs })
end
|
#ancestor_eager_lets ⇒ Object
238
239
240
241
242
|
# File 'lib/crspec/example_group.rb', line 238
def ancestor_eager_lets
@ancestor_eager_lets ||= ancestor_chain.flat_map do |grp|
grp.instance_variable_get(:@eager_lets)
end.freeze
end
|
#ancestor_hooks(type, example = nil) ⇒ Object
216
217
218
|
# File 'lib/crspec/example_group.rb', line 216
def ancestor_hooks(type, example = nil)
filtered_hooks(type, example ? effective_type_for(example) : ancestor_metadata[:type])
end
|
#ancestor_included_modules ⇒ Object
244
245
246
247
248
|
# File 'lib/crspec/example_group.rb', line 244
def ancestor_included_modules
@ancestor_included_modules ||= ancestor_chain.flat_map do |grp|
grp.instance_variable_get(:@included_modules) || []
end.freeze
end
|
#ancestor_let_blocks ⇒ Object
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
# File 'lib/crspec/example_group.rb', line 220
def ancestor_let_blocks
@ancestor_let_blocks ||= begin
blocks = {}
ancestor_chain.each do |grp|
blocks.merge!(grp.instance_variable_get(:@let_blocks))
end
unless blocks.key?(:subject)
desc_cls = described_class
if desc_cls.is_a?(Class)
blocks[:subject] = proc { desc_cls.new rescue nil }
elsif desc_cls
blocks[:subject] = proc { desc_cls }
end
end
blocks.freeze
end
end
|
250
251
252
253
254
255
256
257
258
|
# File 'lib/crspec/example_group.rb', line 250
def ancestor_metadata
@ancestor_metadata ||= begin
meta = {}
ancestor_chain.each do |grp|
meta.merge!(grp.metadata || {})
end
meta.freeze
end
end
|
#around(*args, **kwargs, &block) ⇒ Object
193
194
195
|
# File 'lib/crspec/example_group.rb', line 193
def around(*args, **kwargs, &block)
@around_hooks << { block: block, filters: args, kwfilters: kwargs }
end
|
#attr_accessor(*names) ⇒ Object
140
141
142
143
|
# File 'lib/crspec/example_group.rb', line 140
def attr_accessor(*names)
attr_reader(*names)
attr_writer(*names)
end
|
#attr_reader(*names) ⇒ Object
128
129
130
131
132
|
# File 'lib/crspec/example_group.rb', line 128
def attr_reader(*names)
names.each do |name|
let(name) { instance_variable_get("@#{name}") }
end
end
|
#attr_writer(*names) ⇒ Object
134
135
136
137
138
|
# File 'lib/crspec/example_group.rb', line 134
def attr_writer(*names)
names.each do |name|
define_method("#{name}=") { |val| instance_variable_set("@#{name}", val) }
end
end
|
#before(*args, **kwargs, &block) ⇒ Object
165
166
167
168
|
# File 'lib/crspec/example_group.rb', line 165
def before(*args, **kwargs, &block)
reject_serial_scope!(:before, args)
@before_hooks << { block: block, filters: args, kwfilters: kwargs }
end
|
#create_instance(example) ⇒ Object
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
# File 'lib/crspec/example_group.rb', line 292
def create_instance(example)
klass = example_class_for(effective_type_for(example))
inst = klass.new(example)
klass.setup_callbacks.each do |cb|
if cb.is_a?(Symbol) || cb.is_a?(String)
inst.send(cb)
elsif cb.respond_to?(:call)
inst.instance_exec(&cb)
end
end
inst
end
|
#describe(*args, **kwargs, &block) ⇒ Object
Also known as:
context
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/crspec/example_group.rb', line 40
def describe(*args, **kwargs, &block)
metadata = kwargs.dup
metadata.merge!(args.pop) if args.last.is_a?(Hash)
described = args.first.is_a?(Module) ? args.first : nil
description = described && args.size == 1 ? described : args.map(&:to_s).join(" ")
child = self.class.new(description, metadata, self)
child.described_module = described
child.instance_eval(&block) if block
@children << child
child
end
|
#described_class ⇒ Object
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
# File 'lib/crspec/example_group.rb', line 264
def described_class
return @described_class if defined?(@described_class)
@described_class = begin
found = nil
curr = self
while curr
if curr.described_module
found = curr.described_module
break
end
curr = curr.parent
end
found
end
end
|
#effective_type_for(example) ⇒ Object
281
282
283
284
|
# File 'lib/crspec/example_group.rb', line 281
def effective_type_for(example)
meta = example.metadata || {}
meta.key?(:type) ? meta[:type] : ancestor_metadata[:type]
end
|
#fdescribe(*args, **kwargs, &block) ⇒ Object
Also known as:
fcontext
60
61
62
63
64
|
# File 'lib/crspec/example_group.rb', line 60
def fdescribe(*args, **kwargs, &block)
child = describe(*args, **kwargs, &block)
child.mark_focused!
child
end
|
#finalize! ⇒ Object
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/crspec/example_group.rb', line 197
def finalize!
ancestor_metadata
ancestor_let_blocks
ancestor_eager_lets
ancestor_included_modules
described_class
%i[before after around].each { |type| raw_hooks_for(type) }
example_types = examples.map { |ex| effective_type_for(ex) }.uniq
example_types.each do |type|
%i[before after around].each { |hook_type| filtered_hooks(hook_type, type) }
modules_for_type(type)
example_class_for(type)
end
children.each(&:finalize!)
self
end
|
#fit(description = nil, metadata = {}, &block) ⇒ Object
84
85
86
87
88
|
# File 'lib/crspec/example_group.rb', line 84
def fit(description = nil, metadata = {}, &block)
example = it(description, metadata, &block)
example.focused = true
example
end
|
#focused? ⇒ Boolean
108
109
110
|
# File 'lib/crspec/example_group.rb', line 108
def focused?
!!@focused
end
|
#include(mod) ⇒ Object
112
113
114
|
# File 'lib/crspec/example_group.rb', line 112
def include(mod)
@included_modules << mod
end
|
#it(description = nil, metadata = {}, &block) ⇒ Object
Also known as:
specify
67
68
69
70
71
72
|
# File 'lib/crspec/example_group.rb', line 67
def it(description = nil, metadata = {}, &block)
example = Example.new(description || "unnamed example", metadata, self, block,
pending: pending?)
@examples << example
example
end
|
#let(name, &block) ⇒ Object
145
146
147
|
# File 'lib/crspec/example_group.rb', line 145
def let(name, &block)
@let_blocks[name.to_sym] = block
end
|
#let!(name, &block) ⇒ Object
149
150
151
152
|
# File 'lib/crspec/example_group.rb', line 149
def let!(name, &block)
let(name, &block)
@eager_lets << name.to_sym
end
|
#mark_focused! ⇒ Object
101
102
103
104
105
106
|
# File 'lib/crspec/example_group.rb', line 101
def mark_focused!
@focused = true
@examples.each { |ex| ex.focused = true }
@children.each(&:mark_focused!)
self
end
|
#mark_pending! ⇒ Object
90
91
92
93
94
95
|
# File 'lib/crspec/example_group.rb', line 90
def mark_pending!
@pending = true
@examples.each { |ex| ex.instance_variable_set(:@pending, true) }
@children.each(&:mark_pending!)
self
end
|
#modules_for_example(example) ⇒ Object
260
261
262
|
# File 'lib/crspec/example_group.rb', line 260
def modules_for_example(example)
modules_for_type(effective_type_for(example))
end
|
#pending? ⇒ Boolean
97
98
99
|
# File 'lib/crspec/example_group.rb', line 97
def pending?
!!@pending || (parent ? parent.pending? : false)
end
|
#private(*args) ⇒ Object
119
120
|
# File 'lib/crspec/example_group.rb', line 119
def private(*args)
end
|
#protected(*args) ⇒ Object
125
126
|
# File 'lib/crspec/example_group.rb', line 125
def protected(*args)
end
|
#public(*args) ⇒ Object
122
123
|
# File 'lib/crspec/example_group.rb', line 122
def public(*args)
end
|
#reject_serial_scope!(hook_name, args) ⇒ Object
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
# File 'lib/crspec/example_group.rb', line 175
def reject_serial_scope!(hook_name, args)
scope = args.first
return unless scope.is_a?(Symbol) && FORBIDDEN_HOOK_SCOPES.include?(scope)
raise MigrationError, <<~MSG
#{hook_name}(:#{scope}) is not supported by Crspec: shared state across
examples is inherently serial and breaks the P processes x N threads x
M fibers execution model.
Migrate to per-example setup instead:
- use before(:each) if the setup is cheap
- use let/let! for lazily-built (memoized per example) values
Run `crspec-transpile --analyze` on your suite to find and rewrite all
occurrences automatically.
MSG
end
|
#render_views(*args) ⇒ Object
116
117
|
# File 'lib/crspec/example_group.rb', line 116
def render_views(*args)
end
|
#run_eager_lets(instance) ⇒ Object
286
287
288
289
290
|
# File 'lib/crspec/example_group.rb', line 286
def run_eager_lets(instance)
ancestor_eager_lets.each do |name|
instance.send(name)
end
end
|
#subject(name = nil, &block) ⇒ Object
154
155
156
157
158
159
160
161
|
# File 'lib/crspec/example_group.rb', line 154
def subject(name = nil, &block)
if name
let(name, &block)
let(:subject) { send(name) }
else
let(:subject, &block)
end
end
|
#xdescribe(*args, **kwargs, &block) ⇒ Object
Also known as:
xcontext
53
54
55
56
57
|
# File 'lib/crspec/example_group.rb', line 53
def xdescribe(*args, **kwargs, &block)
child = describe(*args, **kwargs, &block)
child.mark_pending!
child
end
|
#xit(description = nil, metadata = {}, &block) ⇒ Object
Also known as:
pending, skip
75
76
77
78
79
80
|
# File 'lib/crspec/example_group.rb', line 75
def xit(description = nil, metadata = {}, &block)
example = Example.new(description || "unnamed example", metadata, self, block,
pending: true)
@examples << example
example
end
|