rspec-core 2.8.0.rc1 → 2.8.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/License.txt +24 -0
- data/README.md +197 -37
- data/features/command_line/format_option.feature +3 -3
- data/features/command_line/init.feature +18 -0
- data/features/example_groups/shared_examples.feature +1 -1
- data/features/hooks/around_hooks.feature +4 -4
- data/features/pending/pending_examples.feature +5 -5
- data/features/support/env.rb +8 -1
- data/lib/autotest/rspec2.rb +2 -6
- data/lib/rspec/core.rb +48 -158
- data/lib/rspec/core/backward_compatibility.rb +2 -0
- data/lib/rspec/core/command_line.rb +4 -0
- data/lib/rspec/core/configuration.rb +201 -106
- data/lib/rspec/core/configuration_options.rb +2 -1
- data/lib/rspec/core/deprecation.rb +2 -3
- data/lib/rspec/core/drb_options.rb +69 -58
- data/lib/rspec/core/dsl.rb +12 -0
- data/lib/rspec/core/example.rb +53 -18
- data/lib/rspec/core/example_group.rb +144 -54
- data/lib/rspec/core/extensions.rb +4 -4
- data/lib/rspec/core/extensions/instance_eval_with_args.rb +5 -0
- data/lib/rspec/core/extensions/kernel.rb +1 -1
- data/lib/rspec/core/extensions/module_eval_with_args.rb +4 -0
- data/lib/rspec/core/extensions/ordered.rb +7 -2
- data/lib/rspec/core/filter_manager.rb +69 -36
- data/lib/rspec/core/formatters/base_text_formatter.rb +1 -1
- data/lib/rspec/core/formatters/html_formatter.rb +10 -4
- data/lib/rspec/core/hooks.rb +93 -34
- data/lib/rspec/core/let.rb +62 -61
- data/lib/rspec/core/metadata.rb +103 -80
- data/lib/rspec/core/metadata_hash_builder.rb +4 -0
- data/lib/rspec/core/option_parser.rb +42 -44
- data/lib/rspec/core/pending.rb +25 -3
- data/lib/rspec/core/project_initializer.rb +62 -0
- data/lib/rspec/core/rake_task.rb +7 -13
- data/lib/rspec/core/runner.rb +2 -2
- data/lib/rspec/core/shared_context.rb +1 -1
- data/lib/rspec/core/shared_example_group.rb +11 -5
- data/lib/rspec/core/subject.rb +3 -3
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/monkey.rb +1 -1
- data/lib/rspec/monkey/spork/test_framework/rspec.rb +2 -0
- data/spec/command_line/order_spec.rb +19 -13
- data/spec/rspec/core/command_line_spec.rb +1 -5
- data/spec/rspec/core/configuration_options_spec.rb +22 -27
- data/spec/rspec/core/configuration_spec.rb +32 -14
- data/spec/rspec/core/drb_command_line_spec.rb +20 -37
- data/spec/rspec/core/drb_options_spec.rb +51 -3
- data/spec/rspec/core/example_group_spec.rb +101 -84
- data/spec/rspec/core/example_spec.rb +14 -0
- data/spec/rspec/core/filter_manager_spec.rb +114 -33
- data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +17 -69
- data/spec/rspec/core/formatters/html_formatted-1.8.7.html +14 -4
- data/spec/rspec/core/formatters/html_formatted-1.9.2.html +14 -4
- data/spec/rspec/core/formatters/html_formatted-1.9.3.html +14 -4
- data/spec/rspec/core/formatters/html_formatter_spec.rb +1 -1
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +20 -72
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +24 -14
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +29 -19
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.3.html +29 -19
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -2
- data/spec/rspec/core/metadata_spec.rb +77 -45
- data/spec/rspec/core/option_parser_spec.rb +5 -0
- data/spec/rspec/core/pending_example_spec.rb +44 -12
- data/spec/rspec/core/project_initializer_spec.rb +130 -0
- data/spec/rspec/core/rake_task_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/support/matchers.rb +2 -12
- metadata +18 -16
- data/features/command_line/configure.feature +0 -22
- data/lib/rspec/core/command_line_configuration.rb +0 -62
- data/lib/rspec/core/errors.rb +0 -13
- data/spec/rspec/core/command_line_configuration_spec.rb +0 -26
@@ -2,6 +2,7 @@ require 'erb'
|
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module Core
|
5
|
+
# @private
|
5
6
|
class ConfigurationOptions
|
6
7
|
attr_reader :options
|
7
8
|
|
@@ -37,7 +38,7 @@ module RSpec
|
|
37
38
|
|
38
39
|
private
|
39
40
|
|
40
|
-
NON_FORCED_OPTIONS = [:debug, :
|
41
|
+
NON_FORCED_OPTIONS = [:debug, :requires, :libs, :files_or_directories_to_run, :line_numbers, :full_description]
|
41
42
|
|
42
43
|
def force?(key)
|
43
44
|
!NON_FORCED_OPTIONS.include?(key)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module RSpec
|
2
|
-
|
3
2
|
class << self
|
4
|
-
# @
|
3
|
+
# @private
|
5
4
|
#
|
6
5
|
# Used internally to print deprecation warnings
|
7
6
|
def deprecate(method, alternate_method=nil, version=nil)
|
@@ -27,7 +26,7 @@ ADDITIONAL
|
|
27
26
|
warn_deprecation(message)
|
28
27
|
end
|
29
28
|
|
30
|
-
# @
|
29
|
+
# @private
|
31
30
|
#
|
32
31
|
# Used internally to print deprecation warnings
|
33
32
|
def warn_deprecation(message)
|
@@ -1,72 +1,83 @@
|
|
1
1
|
# Builds command line arguments to pass to the rspec command over DRb
|
2
|
-
class RSpec::Core::DrbOptions
|
3
|
-
def initialize(submitted_options, filter_manager)
|
4
|
-
@submitted_options = submitted_options
|
5
|
-
@filter_manager = filter_manager
|
6
|
-
end
|
7
2
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file]
|
16
|
-
argv << "--order" << @submitted_options[:order] if @submitted_options[:order]
|
3
|
+
module RSpec::Core
|
4
|
+
# @private
|
5
|
+
class DrbOptions
|
6
|
+
def initialize(submitted_options, filter_manager)
|
7
|
+
@submitted_options = submitted_options
|
8
|
+
@filter_manager = filter_manager
|
9
|
+
end
|
17
10
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
11
|
+
def options
|
12
|
+
argv = []
|
13
|
+
argv << "--color" if @submitted_options[:color]
|
14
|
+
argv << "--profile" if @submitted_options[:profile_examples]
|
15
|
+
argv << "--backtrace" if @submitted_options[:full_backtrace]
|
16
|
+
argv << "--tty" if @submitted_options[:tty]
|
17
|
+
argv << "--fail-fast" if @submitted_options[:fail_fast]
|
18
|
+
argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file]
|
19
|
+
argv << "--order" << @submitted_options[:order] if @submitted_options[:order]
|
25
20
|
|
26
|
-
|
27
|
-
|
21
|
+
add_failure_exit_code(argv)
|
22
|
+
add_full_description(argv)
|
23
|
+
add_line_numbers(argv)
|
24
|
+
add_filter(argv, :inclusion, @filter_manager.inclusions)
|
25
|
+
add_filter(argv, :exclusion, @filter_manager.exclusions)
|
26
|
+
add_formatters(argv)
|
27
|
+
add_libs(argv)
|
28
|
+
add_requires(argv)
|
28
29
|
|
29
|
-
|
30
|
-
if @submitted_options[:full_description]
|
31
|
-
# The argument to --example is regexp-escaped before being stuffed
|
32
|
-
# into a regexp when received for the first time (see OptionParser).
|
33
|
-
# Hence, merely grabbing the source of this regexp will retain the
|
34
|
-
# backslashes, so we must remove them.
|
35
|
-
argv << "--example" << @submitted_options[:full_description].source.delete('\\')
|
30
|
+
argv + @submitted_options[:files_or_directories_to_run]
|
36
31
|
end
|
37
|
-
end
|
38
32
|
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
def add_failure_exit_code(argv)
|
34
|
+
if @submitted_options[:failure_exit_code]
|
35
|
+
argv << "--failure-exit-code" << @submitted_options[:failure_exit_code].to_s
|
36
|
+
end
|
42
37
|
end
|
43
|
-
end
|
44
38
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
def add_full_description(argv)
|
40
|
+
if @submitted_options[:full_description]
|
41
|
+
# The argument to --example is regexp-escaped before being stuffed
|
42
|
+
# into a regexp when received for the first time (see OptionParser).
|
43
|
+
# Hence, merely grabbing the source of this regexp will retain the
|
44
|
+
# backslashes, so we must remove them.
|
45
|
+
argv << "--example" << @submitted_options[:full_description].source.delete('\\')
|
46
|
+
end
|
47
|
+
end
|
53
48
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
49
|
+
def add_line_numbers(argv)
|
50
|
+
if @submitted_options[:line_numbers]
|
51
|
+
argv.push(*@submitted_options[:line_numbers].inject([]){|a,l| a << "--line_number" << l})
|
52
|
+
end
|
53
|
+
end
|
60
54
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
55
|
+
def add_filter(argv, name, hash)
|
56
|
+
hash.each_pair do |k, v|
|
57
|
+
next if [:if,:unless].include?(k)
|
58
|
+
tag = name == :inclusion ? k.to_s : "~#{k}"
|
59
|
+
tag << ":#{v}" if v.is_a?(String)
|
60
|
+
argv << "--tag" << tag
|
61
|
+
end unless hash.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_formatters(argv)
|
65
|
+
@submitted_options[:formatters].each do |pair|
|
66
|
+
argv << "--format" << pair[0]
|
67
|
+
argv << "--out" << pair[1] if pair[1]
|
68
|
+
end if @submitted_options[:formatters]
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_libs(argv)
|
72
|
+
@submitted_options[:libs].each do |path|
|
73
|
+
argv << "-I" << path
|
74
|
+
end if @submitted_options[:libs]
|
75
|
+
end
|
66
76
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
77
|
+
def add_requires(argv)
|
78
|
+
@submitted_options[:requires].each do |path|
|
79
|
+
argv << "--require" << path
|
80
|
+
end if @submitted_options[:requires]
|
81
|
+
end
|
71
82
|
end
|
72
83
|
end
|
data/lib/rspec/core/dsl.rb
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
3
|
module DSL
|
4
|
+
# Generates a subclass of [ExampleGroup](ExampleGroup)
|
5
|
+
#
|
6
|
+
# ## Examples:
|
7
|
+
#
|
8
|
+
# describe "something" do
|
9
|
+
# it "does something" do
|
10
|
+
# # example code goes here
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @see ExampleGroup
|
15
|
+
# @see ExampleGroup.describe
|
4
16
|
def describe(*args, &example_group_block)
|
5
17
|
RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
|
6
18
|
end
|
data/lib/rspec/core/example.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
|
+
# Wrapper for an instance of a subclass of [ExampleGroup](ExampleGroup). An
|
4
|
+
# instance of `Example` is returned by the
|
5
|
+
# [example](ExampleGroup#example-instance_method) method available in
|
6
|
+
# examples, [before](Hooks#before-instance_method) and
|
7
|
+
# [after](Hooks#after-instance_method) hooks, and yielded to
|
8
|
+
# [around](Hooks#around-instance_method) hooks.
|
9
|
+
# @see ExampleGroup
|
3
10
|
class Example
|
4
|
-
|
11
|
+
# @private
|
12
|
+
#
|
13
|
+
# Used to define methods that delegate to this example's metadata
|
5
14
|
def self.delegate_to_metadata(*keys)
|
6
15
|
keys.each do |key|
|
7
16
|
define_method(key) {@metadata[key]}
|
@@ -20,17 +29,22 @@ module RSpec
|
|
20
29
|
#
|
21
30
|
# Returns the metadata object associated with this example.
|
22
31
|
attr_reader :metadata
|
23
|
-
|
32
|
+
|
24
33
|
# @attr_reader
|
25
|
-
# @
|
34
|
+
# @private
|
26
35
|
#
|
27
36
|
# Returns the example_group_instance that provides the context for
|
28
37
|
# running this example.
|
29
38
|
attr_reader :example_group_instance
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
# Creates a new instance of Example.
|
41
|
+
# @param example_group_class the subclass of ExampleGroup in which this Example is declared
|
42
|
+
# @param description the String passed to the `it` method (or alias)
|
43
|
+
# @param metadata additional args passed to `it` to be used as metadata
|
44
|
+
# @param example_block the block of code that represents the example
|
45
|
+
def initialize(example_group_class, description, metadata, example_block=nil)
|
46
|
+
@example_group_class, @options, @example_block = example_group_class, metadata, example_block
|
47
|
+
@metadata = @example_group_class.metadata.for_example(description, metadata)
|
34
48
|
@exception = nil
|
35
49
|
@pending_declared_in_example = false
|
36
50
|
end
|
@@ -48,6 +62,10 @@ module RSpec
|
|
48
62
|
|
49
63
|
alias_method :pending?, :pending
|
50
64
|
|
65
|
+
# @api private
|
66
|
+
# @param example_group_instance the instance of an ExampleGroup subclass
|
67
|
+
# instance_evals the block submitted to the constructor in the
|
68
|
+
# context of the instance of ExampleGroup
|
51
69
|
def run(example_group_instance, reporter)
|
52
70
|
@example_group_instance = example_group_instance
|
53
71
|
@example_group_instance.example = self
|
@@ -87,34 +105,50 @@ module RSpec
|
|
87
105
|
finish(reporter)
|
88
106
|
end
|
89
107
|
|
90
|
-
|
91
|
-
|
108
|
+
# @private
|
109
|
+
#
|
110
|
+
# Wraps the example block in a Proc so it can invoked using `run` or
|
111
|
+
# `call` in [around](../Hooks#around-instance_method) hooks.
|
112
|
+
def self.procsy(metadata, &proc)
|
113
|
+
Proc.new(&proc).extend(Procsy).with(metadata)
|
92
114
|
end
|
93
115
|
|
116
|
+
# @private
|
94
117
|
module Procsy
|
95
118
|
attr_reader :metadata
|
96
119
|
|
120
|
+
# @private
|
121
|
+
# @param [Proc]
|
122
|
+
# Adds a `run` method to the extended Proc, allowing it to be invoked
|
123
|
+
# in an [around](../Hooks#around-instance_method) hook using either
|
124
|
+
# `run` or `call`.
|
97
125
|
def self.extended(object)
|
98
126
|
def object.run; call; end
|
99
127
|
end
|
100
128
|
|
129
|
+
# @private
|
101
130
|
def with(metadata)
|
102
131
|
@metadata = metadata
|
103
132
|
self
|
104
133
|
end
|
105
134
|
end
|
106
135
|
|
107
|
-
# @
|
136
|
+
# @private
|
137
|
+
def any_apply?(filters)
|
138
|
+
metadata.any_apply?(filters)
|
139
|
+
end
|
140
|
+
|
141
|
+
# @private
|
108
142
|
def all_apply?(filters)
|
109
143
|
@metadata.all_apply?(filters) || @example_group_class.all_apply?(filters)
|
110
144
|
end
|
111
145
|
|
112
|
-
# @
|
146
|
+
# @private
|
113
147
|
def around_hooks
|
114
148
|
@around_hooks ||= example_group.around_hooks_for(self)
|
115
149
|
end
|
116
150
|
|
117
|
-
# @
|
151
|
+
# @private
|
118
152
|
#
|
119
153
|
# Used internally to set an exception in an after hook, which
|
120
154
|
# captures the exception but doesn't raise it.
|
@@ -122,7 +156,7 @@ module RSpec
|
|
122
156
|
@exception ||= exception
|
123
157
|
end
|
124
158
|
|
125
|
-
# @
|
159
|
+
# @private
|
126
160
|
#
|
127
161
|
# Used internally to set an exception and fail without actually executing
|
128
162
|
# the example when an exception is raised in before(:all).
|
@@ -132,11 +166,6 @@ module RSpec
|
|
132
166
|
finish(reporter)
|
133
167
|
end
|
134
168
|
|
135
|
-
# @api private
|
136
|
-
def any_apply?(filters)
|
137
|
-
metadata.any_apply?(filters)
|
138
|
-
end
|
139
|
-
|
140
169
|
private
|
141
170
|
|
142
171
|
def with_around_hooks(&block)
|
@@ -152,8 +181,14 @@ module RSpec
|
|
152
181
|
record :started_at => Time.now
|
153
182
|
end
|
154
183
|
|
184
|
+
# @private
|
185
|
+
module NotPendingExampleFixed
|
186
|
+
def pending_fixed?; false; end
|
187
|
+
end
|
188
|
+
|
155
189
|
def finish(reporter)
|
156
190
|
if @exception
|
191
|
+
@exception.extend(NotPendingExampleFixed) unless @exception.respond_to?(:pending_fixed?)
|
157
192
|
record_finished 'failed', :exception => @exception
|
158
193
|
reporter.example_failed self
|
159
194
|
false
|
@@ -162,7 +197,7 @@ module RSpec
|
|
162
197
|
reporter.example_pending self
|
163
198
|
true
|
164
199
|
elsif pending
|
165
|
-
record_finished 'pending', :pending_message =>
|
200
|
+
record_finished 'pending', :pending_message => String === pending ? pending : Pending::NO_REASON_GIVEN
|
166
201
|
reporter.example_pending self
|
167
202
|
true
|
168
203
|
else
|
@@ -1,32 +1,40 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
|
+
# ExampleGroup and Example are the main structural elements of rspec-core.
|
4
|
+
# Consider this example:
|
5
|
+
#
|
6
|
+
# describe Thing do
|
7
|
+
# it "does something" do
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# The object returned by `describe Thing` is a subclass of ExampleGroup.
|
12
|
+
# The object returned by `it "does something"` is an instance of Example,
|
13
|
+
# which serves as a wrapper for an instance of the ExampleGroup in which it
|
14
|
+
# is declared.
|
3
15
|
class ExampleGroup
|
4
16
|
extend MetadataHashBuilder::WithDeprecationWarning
|
5
17
|
extend Extensions::ModuleEvalWithArgs
|
6
|
-
extend Subject::
|
18
|
+
extend Subject::ExampleGroupMethods
|
7
19
|
extend Hooks
|
8
20
|
|
9
21
|
include Extensions::InstanceEvalWithArgs
|
10
|
-
include Subject::
|
22
|
+
include Subject::ExampleMethods
|
11
23
|
include Pending
|
12
24
|
include Let
|
13
25
|
|
14
|
-
|
15
|
-
|
16
|
-
def running_example
|
17
|
-
RSpec.deprecate("running_example", "example")
|
18
|
-
example
|
19
|
-
end
|
20
|
-
|
26
|
+
# @private
|
21
27
|
def self.world
|
22
28
|
RSpec.world
|
23
29
|
end
|
24
30
|
|
31
|
+
# @private
|
25
32
|
def self.register
|
26
33
|
world.register(self)
|
27
34
|
end
|
28
35
|
|
29
36
|
class << self
|
37
|
+
# @private
|
30
38
|
def self.delegate_to_metadata(*names)
|
31
39
|
names.each do |name|
|
32
40
|
define_method name do
|
@@ -35,16 +43,18 @@ module RSpec
|
|
35
43
|
end
|
36
44
|
end
|
37
45
|
|
38
|
-
delegate_to_metadata :description, :
|
46
|
+
delegate_to_metadata :description, :described_class, :file_path
|
39
47
|
alias_method :display_name, :description
|
40
|
-
|
48
|
+
# @private
|
49
|
+
alias_method :describes, :described_class
|
41
50
|
end
|
42
51
|
|
52
|
+
# @private
|
43
53
|
def self.define_example_method(name, extra_options={})
|
44
54
|
module_eval(<<-END_RUBY, __FILE__, __LINE__)
|
45
55
|
def self.#{name}(desc=nil, *args, &block)
|
46
56
|
options = build_metadata_hash_from(args)
|
47
|
-
options.update(:pending =>
|
57
|
+
options.update(:pending => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
|
48
58
|
options.update(#{extra_options.inspect})
|
49
59
|
examples << RSpec::Core::Example.new(self, desc, options, block)
|
50
60
|
examples.last
|
@@ -53,31 +63,27 @@ module RSpec
|
|
53
63
|
end
|
54
64
|
|
55
65
|
define_example_method :example
|
66
|
+
define_example_method :it
|
67
|
+
define_example_method :specify
|
68
|
+
|
69
|
+
define_example_method :focused, :focused => true, :focus => true
|
70
|
+
define_example_method :focus, :focused => true, :focus => true
|
71
|
+
|
72
|
+
define_example_method :pending, :pending => true
|
73
|
+
define_example_method :xexample, :pending => 'Temporarily disabled with xexample'
|
74
|
+
define_example_method :xit, :pending => 'Temporarily disabled with xit'
|
75
|
+
define_example_method :xspecify, :pending => 'Temporarily disabled with xspecify'
|
56
76
|
|
57
77
|
class << self
|
58
78
|
alias_method :alias_example_to, :define_example_method
|
59
79
|
end
|
60
80
|
|
61
|
-
|
62
|
-
alias_example_to :specify
|
63
|
-
|
64
|
-
alias_example_to :pending, :pending => true
|
65
|
-
alias_example_to :xexample, :pending => true
|
66
|
-
alias_example_to :xit, :pending => true
|
67
|
-
alias_example_to :xspecify, :pending => true
|
68
|
-
|
69
|
-
alias_example_to :focused, :focused => true, :focus => true
|
70
|
-
alias_example_to :focus, :focused => true, :focus => true
|
71
|
-
|
81
|
+
# @private
|
72
82
|
def self.define_nested_shared_group_method(new_name, report_label=nil)
|
73
83
|
module_eval(<<-END_RUBY, __FILE__, __LINE__)
|
74
84
|
def self.#{new_name}(name, *args, &customization_block)
|
75
|
-
shared_block = find_shared("examples", name)
|
76
|
-
raise "Could not find shared examples \#{name.inspect}" unless shared_block
|
77
|
-
|
78
85
|
group = describe("#{report_label || "it should behave like"} \#{name}") do
|
79
|
-
|
80
|
-
module_eval(&customization_block) if customization_block
|
86
|
+
find_and_eval_shared("examples", name, *args, &customization_block)
|
81
87
|
end
|
82
88
|
group.metadata[:shared_group_name] = name
|
83
89
|
group
|
@@ -93,45 +99,82 @@ module RSpec
|
|
93
99
|
|
94
100
|
alias_it_should_behave_like_to :it_behaves_like, "behaves like"
|
95
101
|
|
96
|
-
|
97
|
-
|
102
|
+
# Includes shared content declared with `name`.
|
103
|
+
#
|
104
|
+
# @see SharedExampleGroup
|
105
|
+
def self.include_context(name, *args)
|
106
|
+
block_given? ? block_not_supported("context") : find_and_eval_shared("context", name, *args)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Includes shared content declared with `name`.
|
110
|
+
#
|
111
|
+
# @see SharedExampleGroup
|
112
|
+
def self.include_examples(name, *args)
|
113
|
+
block_given? ? block_not_supported("examples") : find_and_eval_shared("examples", name, *args)
|
98
114
|
end
|
99
115
|
|
100
|
-
|
101
|
-
|
116
|
+
# @private
|
117
|
+
def self.block_not_supported(label)
|
118
|
+
warn("Customization blocks not supported for include_#{label}. Use it_behaves_like instead.")
|
102
119
|
end
|
103
120
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
121
|
+
# @private
|
122
|
+
def self.find_and_eval_shared(label, name, *args, &customization_block)
|
123
|
+
raise ArgumentError, "Could not find shared #{label} #{name.inspect}" unless
|
124
|
+
shared_block = world.shared_example_groups[name]
|
125
|
+
|
126
|
+
module_eval_with_args(*args, &shared_block)
|
127
|
+
module_eval(&customization_block) if customization_block
|
110
128
|
end
|
111
129
|
|
130
|
+
# @private
|
112
131
|
def self.examples
|
113
132
|
@examples ||= []
|
114
133
|
end
|
115
|
-
|
134
|
+
|
135
|
+
# @private
|
116
136
|
def self.filtered_examples
|
117
137
|
world.filtered_examples[self]
|
118
138
|
end
|
119
139
|
|
140
|
+
# @private
|
120
141
|
def self.descendant_filtered_examples
|
121
142
|
@descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
|
122
143
|
end
|
123
144
|
|
145
|
+
# The [Metadata](Metadata) object associated with this group.
|
124
146
|
# @see Metadata
|
125
147
|
def self.metadata
|
126
148
|
@metadata if defined?(@metadata)
|
127
149
|
end
|
128
150
|
|
129
|
-
# @
|
151
|
+
# @private
|
130
152
|
# @return [Metadata] belonging to the parent of a nested [ExampleGroup](ExampleGroup)
|
131
153
|
def self.superclass_metadata
|
132
154
|
@superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
|
133
155
|
end
|
134
156
|
|
157
|
+
# Generates a subclass of this example group which inherits
|
158
|
+
# everything except the examples themselves.
|
159
|
+
#
|
160
|
+
# ## Examples
|
161
|
+
#
|
162
|
+
# describe "something" do # << This describe method is defined in
|
163
|
+
# # << RSpec::Core::DSL, included in the
|
164
|
+
# # << global namespace
|
165
|
+
# before do
|
166
|
+
# do_something_before
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# let(:thing) { Thing.new }
|
170
|
+
#
|
171
|
+
# describe "attribute (of something)" do
|
172
|
+
# # examples in the group get the before hook
|
173
|
+
# # declared above, and can access `thing`
|
174
|
+
# end
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# @see DSL#describe
|
135
178
|
def self.describe(*args, &example_group_block)
|
136
179
|
@_subclass_count ||= 0
|
137
180
|
@_subclass_count += 1
|
@@ -151,6 +194,7 @@ module RSpec
|
|
151
194
|
alias_method :context, :describe
|
152
195
|
end
|
153
196
|
|
197
|
+
# @private
|
154
198
|
def self.subclass(parent, args, &example_group_block)
|
155
199
|
subclass = Class.new(parent)
|
156
200
|
subclass.set_it_up(*args)
|
@@ -158,22 +202,27 @@ module RSpec
|
|
158
202
|
subclass
|
159
203
|
end
|
160
204
|
|
205
|
+
# @private
|
161
206
|
def self.children
|
162
207
|
@children ||= [].extend(Extensions::Ordered)
|
163
208
|
end
|
164
209
|
|
210
|
+
# @private
|
165
211
|
def self.descendants
|
166
212
|
@_descendants ||= [self] + children.inject([]) {|list, c| list + c.descendants}
|
167
213
|
end
|
168
214
|
|
215
|
+
# @private
|
169
216
|
def self.ancestors
|
170
217
|
@_ancestors ||= super().select {|a| a < RSpec::Core::ExampleGroup}
|
171
218
|
end
|
172
219
|
|
220
|
+
# @private
|
173
221
|
def self.top_level?
|
174
222
|
@top_level ||= superclass == ExampleGroup
|
175
223
|
end
|
176
224
|
|
225
|
+
# @private
|
177
226
|
def self.ensure_example_groups_are_configured
|
178
227
|
unless defined?(@@example_groups_configured)
|
179
228
|
RSpec.configuration.configure_mock_framework
|
@@ -182,6 +231,7 @@ module RSpec
|
|
182
231
|
end
|
183
232
|
end
|
184
233
|
|
234
|
+
# @private
|
185
235
|
def self.set_it_up(*args)
|
186
236
|
# Ruby 1.9 has a bug that can lead to infinite recursion and a
|
187
237
|
# SystemStackError if you include a module in a superclass after
|
@@ -199,22 +249,26 @@ module RSpec
|
|
199
249
|
world.configure_group(self)
|
200
250
|
end
|
201
251
|
|
252
|
+
# @private
|
202
253
|
def self.before_all_ivars
|
203
254
|
@before_all_ivars ||= {}
|
204
255
|
end
|
205
256
|
|
257
|
+
# @private
|
206
258
|
def self.store_before_all_ivars(example_group_instance)
|
207
259
|
return if example_group_instance.instance_variables.empty?
|
208
|
-
example_group_instance.instance_variables.each { |ivar|
|
260
|
+
example_group_instance.instance_variables.each { |ivar|
|
209
261
|
before_all_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
|
210
262
|
}
|
211
263
|
end
|
212
264
|
|
265
|
+
# @private
|
213
266
|
def self.assign_before_all_ivars(ivars, example_group_instance)
|
214
267
|
return if ivars.empty?
|
215
268
|
ivars.each { |ivar, val| example_group_instance.instance_variable_set(ivar, val) }
|
216
269
|
end
|
217
270
|
|
271
|
+
# @private
|
218
272
|
def self.run_before_all_hooks(example_group_instance)
|
219
273
|
return if descendant_filtered_examples.empty?
|
220
274
|
assign_before_all_ivars(superclass.before_all_ivars, example_group_instance)
|
@@ -223,6 +277,7 @@ module RSpec
|
|
223
277
|
store_before_all_ivars(example_group_instance)
|
224
278
|
end
|
225
279
|
|
280
|
+
# @private
|
226
281
|
def self.run_around_each_hooks(example, initial_procsy)
|
227
282
|
example.around_hooks.reverse.inject(initial_procsy) do |procsy, around_hook|
|
228
283
|
Example.procsy(procsy.metadata) do
|
@@ -231,16 +286,19 @@ module RSpec
|
|
231
286
|
end
|
232
287
|
end
|
233
288
|
|
289
|
+
# @private
|
234
290
|
def self.run_before_each_hooks(example)
|
235
291
|
world.run_hook_filtered(:before, :each, self, example.example_group_instance, example)
|
236
292
|
ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example.example_group_instance) }
|
237
293
|
end
|
238
294
|
|
295
|
+
# @private
|
239
296
|
def self.run_after_each_hooks(example)
|
240
297
|
ancestors.each { |ancestor| ancestor.run_hook(:after, :each, example.example_group_instance) }
|
241
298
|
world.run_hook_filtered(:after, :each, self, example.example_group_instance, example)
|
242
299
|
end
|
243
300
|
|
301
|
+
# @private
|
244
302
|
def self.run_after_all_hooks(example_group_instance)
|
245
303
|
return if descendant_filtered_examples.empty?
|
246
304
|
assign_before_all_ivars(before_all_ivars, example_group_instance)
|
@@ -261,10 +319,12 @@ An error occurred in an after(:all) hook.
|
|
261
319
|
world.run_hook_filtered(:after, :all, self, example_group_instance)
|
262
320
|
end
|
263
321
|
|
322
|
+
# @private
|
264
323
|
def self.around_hooks_for(example)
|
265
324
|
world.find_hook(:around, :each, self, example) + ancestors.reverse.inject([]){|l,a| l + a.find_hook(:around, :each, self, example)}
|
266
325
|
end
|
267
326
|
|
327
|
+
# Runs all the examples in this group
|
268
328
|
def self.run(reporter)
|
269
329
|
if RSpec.wants_to_quit
|
270
330
|
RSpec.clear_remaining_example_groups if top_level?
|
@@ -286,6 +346,19 @@ An error occurred in an after(:all) hook.
|
|
286
346
|
end
|
287
347
|
end
|
288
348
|
|
349
|
+
# @private
|
350
|
+
def self.run_examples(reporter)
|
351
|
+
filtered_examples.ordered.map do |example|
|
352
|
+
next if RSpec.wants_to_quit
|
353
|
+
instance = new
|
354
|
+
set_ivars(instance, before_all_ivars)
|
355
|
+
succeeded = example.run(instance, reporter)
|
356
|
+
RSpec.wants_to_quit = true if fail_fast? && !succeeded
|
357
|
+
succeeded
|
358
|
+
end.all?
|
359
|
+
end
|
360
|
+
|
361
|
+
# @private
|
289
362
|
def self.fail_filtered_examples(exception, reporter)
|
290
363
|
filtered_examples.each { |example| example.fail_with_exception(reporter, exception) }
|
291
364
|
|
@@ -297,49 +370,66 @@ An error occurred in an after(:all) hook.
|
|
297
370
|
false
|
298
371
|
end
|
299
372
|
|
373
|
+
# @private
|
300
374
|
def self.fail_fast?
|
301
375
|
RSpec.configuration.fail_fast?
|
302
376
|
end
|
303
377
|
|
304
|
-
|
305
|
-
filtered_examples.ordered.map do |example|
|
306
|
-
next if RSpec.wants_to_quit
|
307
|
-
instance = new
|
308
|
-
set_ivars(instance, before_all_ivars)
|
309
|
-
succeeded = example.run(instance, reporter)
|
310
|
-
RSpec.wants_to_quit = true if fail_fast? && !succeeded
|
311
|
-
succeeded
|
312
|
-
end.all?
|
313
|
-
end
|
314
|
-
|
315
|
-
# @api private
|
378
|
+
# @private
|
316
379
|
def self.any_apply?(filters)
|
317
380
|
metadata.any_apply?(filters)
|
318
381
|
end
|
319
382
|
|
320
|
-
# @
|
383
|
+
# @private
|
321
384
|
def self.all_apply?(filters)
|
322
385
|
metadata.all_apply?(filters)
|
323
386
|
end
|
324
387
|
|
388
|
+
# @private
|
325
389
|
def self.declaration_line_numbers
|
326
390
|
@declaration_line_numbers ||= [metadata[:example_group][:line_number]] +
|
327
391
|
examples.collect {|e| e.metadata[:line_number]} +
|
328
392
|
children.inject([]) {|l,c| l + c.declaration_line_numbers}
|
329
393
|
end
|
330
394
|
|
395
|
+
# @private
|
331
396
|
def self.top_level_description
|
332
397
|
ancestors.last.description
|
333
398
|
end
|
334
399
|
|
400
|
+
# @private
|
335
401
|
def self.set_ivars(instance, ivars)
|
336
402
|
ivars.each {|name, value| instance.instance_variable_set(name, value)}
|
337
403
|
end
|
338
404
|
|
405
|
+
# @attr_reader
|
406
|
+
# Returns the [Example](Example) object that wraps this instance of
|
407
|
+
# `ExampleGroup`
|
408
|
+
attr_accessor :example
|
409
|
+
|
410
|
+
# @deprecated use [example](ExampleGroup#example-instance_method)
|
411
|
+
def running_example
|
412
|
+
RSpec.deprecate("running_example", "example")
|
413
|
+
example
|
414
|
+
end
|
415
|
+
|
416
|
+
# Returns the class or module passed to the `describe` method (or alias).
|
417
|
+
# Returns nil if the subject is not a class or module.
|
418
|
+
# @example
|
419
|
+
# describe Thing do
|
420
|
+
# it "does something" do
|
421
|
+
# described_class == Thing
|
422
|
+
# end
|
423
|
+
# end
|
424
|
+
#
|
425
|
+
#
|
339
426
|
def described_class
|
340
427
|
self.class.described_class
|
341
428
|
end
|
342
429
|
|
430
|
+
# @private
|
431
|
+
# instance_evals the block, capturing and reporting an exception if
|
432
|
+
# raised
|
343
433
|
def instance_eval_with_rescue(&hook)
|
344
434
|
begin
|
345
435
|
instance_eval(&hook)
|