rspec-core 2.7.1 → 2.8.0.rc1
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.
- data/README.md +1 -1
- data/features/command_line/order.feature +29 -0
- data/features/command_line/tag.feature +10 -9
- data/features/configuration/default_path.feature +2 -2
- data/features/filtering/exclusion_filters.feature +1 -1
- data/features/filtering/run_all_when_everything_filtered.feature +1 -1
- data/features/subject/attribute_of_subject.feature +1 -1
- data/lib/rspec/core.rb +148 -12
- data/lib/rspec/core/command_line.rb +2 -2
- data/lib/rspec/core/configuration.rb +300 -155
- data/lib/rspec/core/configuration_options.rb +34 -53
- data/lib/rspec/core/deprecation.rb +4 -0
- data/lib/rspec/core/drb_options.rb +72 -0
- data/lib/rspec/core/example.rb +58 -24
- data/lib/rspec/core/example_group.rb +10 -5
- data/lib/rspec/core/extensions.rb +1 -0
- data/lib/rspec/core/extensions/ordered.rb +16 -0
- data/lib/rspec/core/filter_manager.rb +170 -0
- data/lib/rspec/core/formatters/base_formatter.rb +3 -1
- data/lib/rspec/core/formatters/base_text_formatter.rb +6 -0
- data/lib/rspec/core/formatters/snippet_extractor.rb +1 -1
- data/lib/rspec/core/hooks.rb +197 -1
- data/lib/rspec/core/let.rb +3 -2
- data/lib/rspec/core/metadata.rb +25 -4
- data/lib/rspec/core/option_parser.rb +89 -54
- data/lib/rspec/core/pending.rb +41 -0
- data/lib/rspec/core/rake_task.rb +9 -25
- data/lib/rspec/core/reporter.rb +43 -19
- data/lib/rspec/core/shared_context.rb +35 -0
- data/lib/rspec/core/shared_example_group.rb +0 -1
- data/lib/rspec/core/subject.rb +4 -4
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +34 -52
- data/spec/autotest/failed_results_re_spec.rb +2 -2
- data/spec/command_line/order_spec.rb +131 -0
- data/spec/rspec/core/command_line_spec.rb +2 -1
- data/spec/rspec/core/configuration_options_spec.rb +83 -163
- data/spec/rspec/core/configuration_spec.rb +311 -139
- data/spec/rspec/core/drb_options_spec.rb +131 -0
- data/spec/rspec/core/example_group_spec.rb +22 -11
- data/spec/rspec/core/example_spec.rb +1 -2
- data/spec/rspec/core/filter_manager_spec.rb +175 -0
- data/spec/rspec/core/formatters/helpers_spec.rb +1 -1
- data/spec/rspec/core/formatters/html_formatter_spec.rb +3 -2
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -1
- data/spec/rspec/core/metadata_spec.rb +21 -6
- data/spec/rspec/core/option_parser_spec.rb +74 -0
- data/spec/rspec/core/reporter_spec.rb +18 -1
- data/spec/rspec/core/shared_context_spec.rb +54 -17
- data/spec/rspec/core/subject_spec.rb +1 -1
- data/spec/rspec/core/world_spec.rb +7 -188
- data/spec/spec_helper.rb +47 -43
- data/spec/support/config_options_helper.rb +27 -0
- metadata +28 -12
- data/lib/rspec/core/expecting/with_rspec.rb +0 -9
- data/lib/rspec/core/expecting/with_stdlib.rb +0 -9
data/README.md
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: --order (new in rspec-core-2.8)
|
2
|
+
|
3
|
+
Use the `--order` option to tell RSpec how to order the files, groups, and
|
4
|
+
examples. Options are `default` and `rand`:
|
5
|
+
|
6
|
+
Default is:
|
7
|
+
|
8
|
+
* files are ordered based on the underlying file system's order (typically
|
9
|
+
case-sensitive alpha on *nix OS's and case-insenstive alpha in Windows)
|
10
|
+
* groups/examples are loaded in the order in which they are declared
|
11
|
+
|
12
|
+
Use `rand` to randomize the order of files, groups within files, and
|
13
|
+
examples within groups.*
|
14
|
+
|
15
|
+
* Nested groups are always run from top-level to bottom-level in order to avoid
|
16
|
+
executing `before(:all)` and `after(:all)` hooks more than once, but the order
|
17
|
+
of groups at each level is randomized.
|
18
|
+
|
19
|
+
You can also specify a seed
|
20
|
+
|
21
|
+
<h3>Examples</h3>
|
22
|
+
|
23
|
+
--order default
|
24
|
+
--order rand
|
25
|
+
--order rand:123
|
26
|
+
--seed 123 # same as --order rand:123
|
27
|
+
|
28
|
+
The `default` option is only necessary when you have `--order rand` stored in a
|
29
|
+
config file (e.g. `.rspec`) and you want to override it from the command line.
|
@@ -33,19 +33,19 @@ Feature: --tag option
|
|
33
33
|
|
34
34
|
Scenario: filter examples with a simple tag
|
35
35
|
When I run `rspec . --tag focus`
|
36
|
-
Then the output should contain "
|
36
|
+
Then the output should contain "include {:focus=>true}"
|
37
37
|
And the examples should all pass
|
38
38
|
|
39
39
|
Scenario: filter examples with a simple tag and @
|
40
40
|
When I run `rspec . --tag @focus`
|
41
|
-
Then the output should contain "
|
41
|
+
Then the output should contain "include {:focus=>true}"
|
42
42
|
Then the examples should all pass
|
43
43
|
|
44
44
|
Scenario: filter examples with a name:value tag
|
45
45
|
When I run `rspec . --tag type:special`
|
46
46
|
Then the output should contain:
|
47
47
|
"""
|
48
|
-
|
48
|
+
include {:type=>"special"}
|
49
49
|
"""
|
50
50
|
And the output should contain "2 examples"
|
51
51
|
And the examples should all pass
|
@@ -54,25 +54,25 @@ Feature: --tag option
|
|
54
54
|
When I run `rspec . --tag @type:special`
|
55
55
|
Then the output should contain:
|
56
56
|
"""
|
57
|
-
|
57
|
+
include {:type=>"special"}
|
58
58
|
"""
|
59
59
|
And the examples should all pass
|
60
60
|
|
61
61
|
Scenario: exclude examples with a simple tag
|
62
62
|
When I run `rspec . --tag ~skip`
|
63
|
-
Then the output should contain "
|
63
|
+
Then the output should contain "exclude {:skip=>true}"
|
64
64
|
Then the examples should all pass
|
65
65
|
|
66
66
|
Scenario: exclude examples with a simple tag and @
|
67
67
|
When I run `rspec . --tag ~@skip`
|
68
|
-
Then the output should contain "
|
68
|
+
Then the output should contain "exclude {:skip=>true}"
|
69
69
|
Then the examples should all pass
|
70
70
|
|
71
71
|
Scenario: exclude examples with a name:value tag
|
72
72
|
When I run `rspec . --tag ~speed:slow`
|
73
73
|
Then the output should contain:
|
74
74
|
"""
|
75
|
-
|
75
|
+
exclude {:speed=>"slow"}
|
76
76
|
"""
|
77
77
|
Then the examples should all pass
|
78
78
|
|
@@ -80,11 +80,12 @@ Feature: --tag option
|
|
80
80
|
When I run `rspec . --tag ~@speed:slow`
|
81
81
|
Then the output should contain:
|
82
82
|
"""
|
83
|
-
|
83
|
+
exclude {:speed=>"slow"}
|
84
84
|
"""
|
85
85
|
Then the examples should all pass
|
86
86
|
|
87
87
|
Scenario: filter examples with a simple tag, exclude examples with another tag
|
88
88
|
When I run `rspec . --tag focus --tag ~skip`
|
89
|
-
Then the output should contain "
|
89
|
+
Then the output should contain "include {:focus=>true}"
|
90
|
+
And the output should contain "exclude {:skip=>true}"
|
90
91
|
And the examples should all pass
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Feature: default_path
|
2
2
|
|
3
|
-
As of rspec-2.7
|
4
|
-
|
3
|
+
As of rspec-2.7, you can just type `rspec` to run all specs that live
|
4
|
+
in the `spec` directory.
|
5
5
|
|
6
6
|
This is supported by a `--default_path` option, which is set to `spec` by
|
7
7
|
default. If you prefer to keep your specs in a different directory, or assign
|
@@ -81,7 +81,7 @@ Feature: exclusion filters
|
|
81
81
|
end
|
82
82
|
"""
|
83
83
|
When I run `rspec ./spec/sample_spec.rb --format doc`
|
84
|
-
Then the output should match /
|
84
|
+
Then the output should match /All examples were filtered out/
|
85
85
|
And the examples should all pass
|
86
86
|
And the output should not contain "group 1"
|
87
87
|
And the output should not contain "group 2"
|
@@ -32,7 +32,7 @@ Feature: run all when everything filtered
|
|
32
32
|
end
|
33
33
|
"""
|
34
34
|
When I run `rspec spec/sample_spec.rb --format doc`
|
35
|
-
Then the output should contain "
|
35
|
+
Then the output should contain "All examples were filtered out; ignoring {:focus=>true}"
|
36
36
|
And the examples should all pass
|
37
37
|
And the output should contain:
|
38
38
|
"""
|
data/lib/rspec/core.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'rspec/core/filter_manager'
|
2
2
|
require 'rspec/core/dsl'
|
3
3
|
require 'rspec/core/extensions'
|
4
4
|
require 'rspec/core/load_path'
|
@@ -17,37 +17,40 @@ require 'rspec/core/world'
|
|
17
17
|
require 'rspec/core/configuration'
|
18
18
|
require 'rspec/core/command_line_configuration'
|
19
19
|
require 'rspec/core/option_parser'
|
20
|
+
require 'rspec/core/drb_options'
|
20
21
|
require 'rspec/core/configuration_options'
|
21
22
|
require 'rspec/core/command_line'
|
22
23
|
require 'rspec/core/drb_command_line'
|
23
24
|
require 'rspec/core/runner'
|
24
25
|
require 'rspec/core/example'
|
25
|
-
require 'rspec/core/shared_context'
|
26
26
|
require 'rspec/core/shared_example_group'
|
27
27
|
require 'rspec/core/example_group'
|
28
28
|
require 'rspec/core/version'
|
29
29
|
require 'rspec/core/errors'
|
30
30
|
|
31
31
|
module RSpec
|
32
|
-
autoload :Matchers,
|
33
|
-
|
34
|
-
SharedContext = Core::SharedContext
|
32
|
+
autoload :Matchers, 'rspec/matchers'
|
33
|
+
autoload :SharedContext, 'rspec/core/shared_context'
|
35
34
|
|
35
|
+
# @api private
|
36
36
|
# Used internally to determine what to do when a SIGINT is received
|
37
37
|
def self.wants_to_quit
|
38
38
|
world.wants_to_quit
|
39
39
|
end
|
40
40
|
|
41
|
+
# @api private
|
41
42
|
# Used internally to determine what to do when a SIGINT is received
|
42
43
|
def self.wants_to_quit=(maybe)
|
43
44
|
world.wants_to_quit=(maybe)
|
44
45
|
end
|
45
46
|
|
47
|
+
# @api private
|
46
48
|
# Internal container for global non-configuration data
|
47
49
|
def self.world
|
48
50
|
@world ||= RSpec::Core::World.new
|
49
51
|
end
|
50
52
|
|
53
|
+
# @api private
|
51
54
|
# Used internally to ensure examples get reloaded between multiple runs in
|
52
55
|
# the same process.
|
53
56
|
def self.reset
|
@@ -55,26 +58,159 @@ module RSpec
|
|
55
58
|
configuration.reset
|
56
59
|
end
|
57
60
|
|
58
|
-
# Returns the global
|
61
|
+
# Returns the global [Configuration](Core/Configuration) object. While you
|
62
|
+
# _can_ use this method to access the configuration, the more common
|
63
|
+
# convention is to use [RSpec.configure](RSpec#configure-class_method).
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# RSpec.configuration.drb_port = 1234
|
67
|
+
# @see RSpec.configure
|
68
|
+
# @see Core::Configuration
|
59
69
|
def self.configuration
|
60
70
|
@configuration ||= RSpec::Core::Configuration.new
|
61
71
|
end
|
62
72
|
|
63
|
-
#
|
64
|
-
#
|
65
|
-
# == Examples
|
73
|
+
# @yield [Configuration] global configuration
|
66
74
|
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
75
|
+
# @example
|
76
|
+
# RSpec.configure do |config|
|
77
|
+
# config.add_formatter 'documentation'
|
78
|
+
# end
|
79
|
+
# @see Core::Configuration
|
70
80
|
def self.configure
|
71
81
|
yield configuration if block_given?
|
72
82
|
end
|
73
83
|
|
84
|
+
# @api private
|
74
85
|
# Used internally to clear remaining groups when fail_fast is set
|
75
86
|
def self.clear_remaining_example_groups
|
76
87
|
world.example_groups.clear
|
77
88
|
end
|
89
|
+
|
90
|
+
# rspec-core provides the structure for writing executable examples of how
|
91
|
+
# your code should behave. It uses the words "describe" and "it" so we can
|
92
|
+
# express concepts like a conversation:
|
93
|
+
#
|
94
|
+
# "Describe an order."
|
95
|
+
# "It sums the prices of its line items."
|
96
|
+
#
|
97
|
+
# ## Basic structure
|
98
|
+
#
|
99
|
+
# describe Order do
|
100
|
+
# it "sums the prices of its line items" do
|
101
|
+
# order = Order.new
|
102
|
+
# order.add_entry(LineItem.new(:item => Item.new(
|
103
|
+
# :price => Money.new(1.11, :USD)
|
104
|
+
# )
|
105
|
+
# order.add_entry(LineItem.new(:item => Item.new(
|
106
|
+
# :price => Money.new(2.22, :USD),
|
107
|
+
# :quantity => 2
|
108
|
+
# )
|
109
|
+
# order.total.should eq(Money.new(5.55, :USD))
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# The `describe` method creates an [ExampleGroup](Core/ExampleGroup). Within the
|
114
|
+
# block passed to `describe` you can declare examples using the `it` method.
|
115
|
+
#
|
116
|
+
# Under the hood, an example group is a class in which the block passed to
|
117
|
+
# `describe` is evaluated. The blocks passed to `it` are evaluated in the
|
118
|
+
# context of an _instance_ of that class.
|
119
|
+
#
|
120
|
+
# ## Nested groups
|
121
|
+
#
|
122
|
+
# You can also declare nested nested groups using the `describe` or `context`
|
123
|
+
# methods:
|
124
|
+
#
|
125
|
+
# describe Order to
|
126
|
+
# context "with no items" do
|
127
|
+
# it "behaves one way" do
|
128
|
+
# # ...
|
129
|
+
# end
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# context "with one item" do
|
133
|
+
# it "behaves another way" do
|
134
|
+
# # ...
|
135
|
+
# end
|
136
|
+
# end
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# ## Aliases
|
140
|
+
#
|
141
|
+
# You can declare example groups using either `describe` or `context`, though
|
142
|
+
# only `describe` is available at the top level.
|
143
|
+
#
|
144
|
+
# You can declare examples within a group using any of `it`, `specify`, or
|
145
|
+
# `example`.
|
146
|
+
#
|
147
|
+
# ## Shared examples
|
148
|
+
#
|
149
|
+
# Declare a shared example group using `shared_examples`, and then include it
|
150
|
+
# in each group using `include_examples`.
|
151
|
+
#
|
152
|
+
# shared_examples "collections" do |collection_class|
|
153
|
+
# it "is empty when first created" do
|
154
|
+
# collection_class.new.should be_empty
|
155
|
+
# end
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# describe Array do
|
159
|
+
# include_examples "collections", Array
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# ## Metadata
|
163
|
+
#
|
164
|
+
# rspec-core stores a metadata hash with every example and group, which
|
165
|
+
# contains like their descriptions, the locations at which they were
|
166
|
+
# declared, etc, etc. This hash powers many of rspec-core's features,
|
167
|
+
# including output formatters (which access descriptions and locations),
|
168
|
+
# and filtering before and after hooks.
|
169
|
+
#
|
170
|
+
# Although you probably won't ever need this unless you are writing an
|
171
|
+
# extension, you can access it from an example like this:
|
172
|
+
#
|
173
|
+
# it "does something" do
|
174
|
+
# example.metadata[:description].should eq("does something")
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# ### `described_class`
|
178
|
+
#
|
179
|
+
# When a class is passed to `describe`, you can access it from an example
|
180
|
+
# using the `described_class` method, which is a wrapper for
|
181
|
+
# `example.metadata[:described_class]`.
|
182
|
+
#
|
183
|
+
# describe Widget do
|
184
|
+
# example do
|
185
|
+
# described_class.should equal(Widget)
|
186
|
+
# end
|
187
|
+
# end
|
188
|
+
#
|
189
|
+
# This is useful in extensions or shared example groups in which the specific
|
190
|
+
# class is unknown. Taking the shared examples example from above, we can
|
191
|
+
# clean it up a bit using `described_class`:
|
192
|
+
#
|
193
|
+
# shared_examples "collections" do
|
194
|
+
# it "is empty when first created" do
|
195
|
+
# described.new.should be_empty
|
196
|
+
# end
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# describe Array do
|
200
|
+
# include_examples "collections"
|
201
|
+
# end
|
202
|
+
#
|
203
|
+
# describe Hash do
|
204
|
+
# include_examples "collections"
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
# ## The `rspec` command
|
208
|
+
#
|
209
|
+
# When you install the rspec-core gem, it installs the `rspec` executable,
|
210
|
+
# which you'll use to run rspec. The `rspec` comes with many useful options.
|
211
|
+
# Run `rspec --help` to see the complete list.
|
212
|
+
module Core
|
213
|
+
end
|
78
214
|
end
|
79
215
|
|
80
216
|
require 'rspec/core/backward_compatibility'
|
@@ -18,10 +18,10 @@ module RSpec
|
|
18
18
|
@configuration.load_spec_files
|
19
19
|
@world.announce_filters
|
20
20
|
|
21
|
-
@configuration.reporter.report(@world.example_count) do |reporter|
|
21
|
+
@configuration.reporter.report(@world.example_count, @configuration.randomize? ? @configuration.seed : nil) do |reporter|
|
22
22
|
begin
|
23
23
|
@configuration.run_hook(:before, :suite)
|
24
|
-
@world.example_groups.map {|g| g.run(reporter)}.all? ? 0 : @configuration.failure_exit_code
|
24
|
+
@world.example_groups.ordered.map {|g| g.run(reporter)}.all? ? 0 : @configuration.failure_exit_code
|
25
25
|
ensure
|
26
26
|
@configuration.run_hook(:after, :suite)
|
27
27
|
end
|
@@ -3,51 +3,81 @@ require 'fileutils'
|
|
3
3
|
|
4
4
|
module RSpec
|
5
5
|
module Core
|
6
|
+
# Stores runtime configuration information.
|
7
|
+
#
|
8
|
+
# @example Standard settings
|
9
|
+
# RSpec.configure do |c|
|
10
|
+
# c.drb_port = 1234
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @example Hooks
|
14
|
+
# RSpec.configure do |c|
|
15
|
+
# c.before(:suite) { establish_connection }
|
16
|
+
# c.before(:each) { log_in_as :authorized }
|
17
|
+
# c.around(:each) { |ex| Database.transaction(&ex) }
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @see RSpec.configure
|
21
|
+
# @see Hooks
|
6
22
|
class Configuration
|
7
23
|
include RSpec::Core::Hooks
|
8
24
|
|
9
25
|
class MustBeConfiguredBeforeExampleGroupsError < StandardError; end
|
10
26
|
|
27
|
+
def self.define_predicate_for(*names)
|
28
|
+
names.each {|name| alias_method "#{name}?", name}
|
29
|
+
end
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
#
|
33
|
+
# Invoked by the `add_setting` instance method. Use that method on a
|
34
|
+
# `Configuration` instance rather than this class method.
|
11
35
|
def self.add_setting(name, opts={})
|
36
|
+
raise "Use the instance add_setting method if you want to set a default" if opts.has_key?(:default)
|
12
37
|
if opts[:alias]
|
38
|
+
RSpec.warn_deprecation <<-MESSAGE
|
39
|
+
The :alias option to add_setting is deprecated. Use :alias_with on the original setting instead.
|
40
|
+
Called from #{caller(0)[4]}
|
41
|
+
MESSAGE
|
13
42
|
alias_method name, opts[:alias]
|
14
43
|
alias_method "#{name}=", "#{opts[:alias]}="
|
15
|
-
|
44
|
+
define_predicate_for name
|
16
45
|
else
|
17
|
-
|
18
|
-
|
19
|
-
|
46
|
+
attr_writer name
|
47
|
+
eval <<-CODE
|
48
|
+
def #{name}
|
49
|
+
value_for(#{name.inspect}, defined?(@#{name}) ? @#{name} : nil)
|
50
|
+
end
|
51
|
+
CODE
|
52
|
+
define_predicate_for name
|
53
|
+
end
|
54
|
+
if opts[:alias_with]
|
55
|
+
[opts[:alias_with]].flatten.each do |alias_name|
|
56
|
+
alias_method alias_name, name
|
57
|
+
alias_method "#{alias_name}=", "#{name}="
|
58
|
+
define_predicate_for alias_name
|
59
|
+
end
|
20
60
|
end
|
21
61
|
end
|
22
62
|
|
23
63
|
add_setting :error_stream
|
24
|
-
add_setting :output_stream
|
25
|
-
add_setting :output, :alias => :output_stream
|
26
|
-
add_setting :out, :alias => :output_stream
|
64
|
+
add_setting :output_stream, :alias_with => [:output, :out]
|
27
65
|
add_setting :drb
|
28
66
|
add_setting :drb_port
|
29
67
|
add_setting :profile_examples
|
30
68
|
add_setting :fail_fast
|
31
|
-
add_setting :failure_exit_code
|
69
|
+
add_setting :failure_exit_code
|
32
70
|
add_setting :run_all_when_everything_filtered
|
33
|
-
add_setting :
|
34
|
-
add_setting :inclusion_filter
|
35
|
-
add_setting :filter, :alias => :inclusion_filter
|
36
|
-
add_setting :pattern, :default => '**/*_spec.rb'
|
37
|
-
add_setting :filename_pattern, :alias => :pattern
|
71
|
+
add_setting :pattern, :alias_with => :filename_pattern
|
38
72
|
add_setting :files_to_run
|
39
73
|
add_setting :include_or_extend_modules
|
40
74
|
add_setting :backtrace_clean_patterns
|
41
75
|
add_setting :tty
|
42
|
-
add_setting :treat_symbols_as_metadata_keys_with_true_values
|
76
|
+
add_setting :treat_symbols_as_metadata_keys_with_true_values
|
43
77
|
add_setting :expecting_with_rspec
|
44
|
-
add_setting :default_path
|
45
|
-
add_setting :show_failures_in_pending_blocks
|
46
|
-
|
47
|
-
CONDITIONAL_FILTERS = {
|
48
|
-
:if => lambda { |value, metadata| metadata.has_key?(:if) && !value },
|
49
|
-
:unless => lambda { |value| value }
|
50
|
-
}
|
78
|
+
add_setting :default_path
|
79
|
+
add_setting :show_failures_in_pending_blocks
|
80
|
+
add_setting :order
|
51
81
|
|
52
82
|
DEFAULT_BACKTRACE_PATTERNS = [
|
53
83
|
/\/lib\d*\/ruby\//,
|
@@ -59,92 +89,107 @@ module RSpec
|
|
59
89
|
]
|
60
90
|
|
61
91
|
def initialize
|
62
|
-
@
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
92
|
+
@expectation_frameworks = []
|
93
|
+
@include_or_extend_modules = []
|
94
|
+
@mock_framework = nil
|
95
|
+
@files_to_run = []
|
96
|
+
@formatters = []
|
97
|
+
@color = false
|
98
|
+
@pattern = '**/*_spec.rb'
|
99
|
+
@failure_exit_code = 1
|
100
|
+
@backtrace_clean_patterns = DEFAULT_BACKTRACE_PATTERNS.dup
|
101
|
+
@default_path = 'spec'
|
102
|
+
@filter_manager = FilterManager.new
|
103
|
+
@preferred_options = {}
|
104
|
+
@seed = srand % 0xFFFF
|
105
|
+
end
|
106
|
+
|
107
|
+
attr_accessor :filter_manager
|
108
|
+
|
109
|
+
def force(hash)
|
110
|
+
@preferred_options.merge!(hash)
|
111
|
+
end
|
112
|
+
|
113
|
+
def force_include(hash)
|
114
|
+
filter_manager.include hash
|
115
|
+
end
|
116
|
+
|
117
|
+
def force_exclude(hash)
|
118
|
+
filter_manager.exclude hash
|
67
119
|
end
|
68
120
|
|
69
121
|
def reset
|
70
122
|
@reporter = nil
|
71
|
-
@formatters.clear
|
123
|
+
@formatters.clear
|
72
124
|
end
|
73
125
|
|
74
|
-
#
|
75
|
-
#
|
76
|
-
# add_setting(:name, :default => "default_value")
|
77
|
-
# add_setting(:name, :alias => :other_setting)
|
126
|
+
# @overload add_setting(name)
|
127
|
+
# @overload add_setting(name, options_hash)
|
78
128
|
#
|
79
|
-
#
|
129
|
+
# Adds a custom setting to the RSpec.configuration object.
|
80
130
|
#
|
81
|
-
#
|
131
|
+
# RSpec.configuration.add_setting :foo
|
82
132
|
#
|
83
|
-
#
|
84
|
-
#
|
133
|
+
# Used internally and by extension frameworks like rspec-rails, so they
|
134
|
+
# can add config settings that are domain specific. For example:
|
135
|
+
#
|
136
|
+
# RSpec.configure do |c|
|
137
|
+
# c.add_setting :use_transactional_fixtures,
|
138
|
+
# :default => true,
|
139
|
+
# :alias_with => :use_transactional_examples
|
140
|
+
# end
|
85
141
|
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# RSpec.configuration.foo?() # returns true if foo returns anything but nil or false
|
142
|
+
# `add_setting` creates three methods on the configuration object, a
|
143
|
+
# setter, a getter, and a predicate:
|
89
144
|
#
|
90
|
-
#
|
91
|
-
#
|
145
|
+
# RSpec.configuration.foo=(value)
|
146
|
+
# RSpec.configuration.foo
|
147
|
+
# RSpec.configuration.foo? # returns true if foo returns anything but nil or false
|
92
148
|
#
|
93
|
-
#
|
94
|
-
# c.add_setting :use_transactional_fixtures, :default => true
|
95
|
-
# c.add_setting :use_transactional_examples, :alias => :use_transactional_fixtures
|
96
|
-
# end
|
149
|
+
# ### Options
|
97
150
|
#
|
98
|
-
#
|
151
|
+
# `add_setting` takes an optional hash that supports the keys `:default`
|
152
|
+
# and `:alias_with`.
|
99
153
|
#
|
100
|
-
#
|
101
|
-
#
|
154
|
+
# Use `:default` to set a default value for the generated getter and
|
155
|
+
# predicate methods:
|
102
156
|
#
|
103
|
-
#
|
157
|
+
# add_setting(:foo, :default => "default value")
|
104
158
|
#
|
105
|
-
#
|
106
|
-
#
|
159
|
+
# Use `:alias_with` to alias the setter, getter, and predicate to another
|
160
|
+
# name, or names:
|
107
161
|
#
|
108
|
-
#
|
162
|
+
# add_setting(:foo, :alias_with => :bar)
|
163
|
+
# add_setting(:foo, :alias_with => [:bar, :baz])
|
109
164
|
#
|
110
|
-
# Aliases its setter, getter, and predicate, to those for the
|
111
|
-
# +other_setting+.
|
112
165
|
def add_setting(name, opts={})
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
119
|
-
|
120
|
-
def settings
|
121
|
-
@settings ||= {}
|
122
|
-
end
|
123
|
-
|
124
|
-
def clear_inclusion_filter
|
125
|
-
self.inclusion_filter = nil
|
166
|
+
default = opts.delete(:default)
|
167
|
+
(class << self; self; end).class_eval do
|
168
|
+
add_setting(name, opts)
|
169
|
+
end
|
170
|
+
send("#{name}=", default) if default
|
126
171
|
end
|
127
172
|
|
173
|
+
# Used by formatters to ask whether a backtrace line should be displayed
|
174
|
+
# or not, based on the line matching any `backtrace_clean_patterns`.
|
128
175
|
def cleaned_from_backtrace?(line)
|
129
176
|
backtrace_clean_patterns.any? { |regex| line =~ regex }
|
130
177
|
end
|
131
178
|
|
132
179
|
# Returns the configured mock framework adapter module
|
133
180
|
def mock_framework
|
134
|
-
|
135
|
-
|
136
|
-
RSpec::Core::MockFrameworkAdapter
|
137
|
-
end
|
181
|
+
mock_with :rspec unless @mock_framework
|
182
|
+
@mock_framework
|
138
183
|
end
|
139
184
|
|
140
185
|
# Delegates to mock_framework=(framework)
|
141
|
-
def
|
142
|
-
|
186
|
+
def mock_framework=(framework)
|
187
|
+
mock_with framework
|
143
188
|
end
|
144
189
|
|
145
190
|
# Sets the mock framework adapter module.
|
146
191
|
#
|
147
|
-
#
|
192
|
+
# `framework` can be a Symbol or a Module.
|
148
193
|
#
|
149
194
|
# Given any of :rspec, :mocha, :flexmock, or :rr, configures the named
|
150
195
|
# framework.
|
@@ -164,11 +209,10 @@ module RSpec
|
|
164
209
|
#
|
165
210
|
# teardown_mocks_for_rspec
|
166
211
|
# - called after verify_mocks_for_rspec (even if there are errors)
|
167
|
-
def
|
168
|
-
|
169
|
-
case framework
|
212
|
+
def mock_with(framework)
|
213
|
+
framework_module = case framework
|
170
214
|
when Module
|
171
|
-
|
215
|
+
framework
|
172
216
|
when String, Symbol
|
173
217
|
require case framework.to_s
|
174
218
|
when /rspec/i
|
@@ -182,72 +226,87 @@ module RSpec
|
|
182
226
|
else
|
183
227
|
'rspec/core/mocking/with_absolutely_nothing'
|
184
228
|
end
|
185
|
-
|
186
|
-
|
229
|
+
RSpec::Core::MockFrameworkAdapter
|
230
|
+
end
|
231
|
+
|
232
|
+
new_name, old_name = [framework_module, @mock_framework].map do |mod|
|
233
|
+
mod.respond_to?(:framework_name) ? mod.framework_name : :unnamed
|
234
|
+
end
|
235
|
+
|
236
|
+
unless new_name == old_name
|
237
|
+
assert_no_example_groups_defined(:mock_framework)
|
187
238
|
end
|
239
|
+
|
240
|
+
@mock_framework = framework_module
|
188
241
|
end
|
189
242
|
|
190
243
|
# Returns the configured expectation framework adapter module(s)
|
191
244
|
def expectation_frameworks
|
192
|
-
expect_with :rspec
|
193
|
-
|
245
|
+
expect_with :rspec if @expectation_frameworks.empty?
|
246
|
+
@expectation_frameworks
|
194
247
|
end
|
195
248
|
|
196
|
-
# Delegates to expect_with(
|
249
|
+
# Delegates to expect_with(framework)
|
197
250
|
def expectation_framework=(framework)
|
198
|
-
expect_with(
|
251
|
+
expect_with(framework)
|
199
252
|
end
|
200
253
|
|
201
254
|
# Sets the expectation framework module(s).
|
202
255
|
#
|
203
|
-
#
|
256
|
+
# `frameworks` can be :rspec, :stdlib, or both
|
204
257
|
#
|
205
258
|
# Given :rspec, configures rspec/expectations.
|
206
259
|
# Given :stdlib, configures test/unit/assertions
|
207
260
|
# Given both, configures both
|
208
261
|
def expect_with(*frameworks)
|
209
|
-
|
210
|
-
settings[:expectation_frameworks] = []
|
211
|
-
frameworks.each do |framework|
|
262
|
+
modules = frameworks.map do |framework|
|
212
263
|
case framework
|
213
|
-
when
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
end
|
223
|
-
settings[:expectation_frameworks] << RSpec::Core::ExpectationFrameworkAdapter
|
264
|
+
when :rspec
|
265
|
+
require 'rspec/expectations'
|
266
|
+
self.expecting_with_rspec = true
|
267
|
+
::RSpec::Matchers
|
268
|
+
when :stdlib
|
269
|
+
require 'test/unit/assertions'
|
270
|
+
::Test::Unit::Assertions
|
271
|
+
else
|
272
|
+
raise ArgumentError, "#{framework.inspect} is not supported"
|
224
273
|
end
|
225
274
|
end
|
226
|
-
end
|
227
275
|
|
228
|
-
|
229
|
-
|
276
|
+
if (modules - @expectation_frameworks).any?
|
277
|
+
assert_no_example_groups_defined(:expect_with)
|
278
|
+
end
|
279
|
+
|
280
|
+
@expectation_frameworks.clear
|
281
|
+
@expectation_frameworks.push(*modules)
|
230
282
|
end
|
231
283
|
|
232
|
-
def
|
233
|
-
@
|
284
|
+
def full_backtrace=(true_or_false)
|
285
|
+
@backtrace_clean_patterns = true_or_false ? [] : DEFAULT_BACKTRACE_PATTERNS
|
234
286
|
end
|
235
287
|
|
236
|
-
def
|
237
|
-
|
288
|
+
def color
|
289
|
+
return false unless output_to_tty?
|
290
|
+
value_for(:color, @color)
|
238
291
|
end
|
239
292
|
|
240
|
-
def
|
293
|
+
def color=(bool)
|
241
294
|
return unless bool
|
242
|
-
@
|
295
|
+
@color = true
|
243
296
|
if bool && ::RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
244
297
|
unless ENV['ANSICON']
|
245
298
|
warn "You must use ANSICON 1.31 or later (http://adoxa.110mb.com/ansicon/) to use colour on Windows"
|
246
|
-
@
|
299
|
+
@color = false
|
247
300
|
end
|
248
301
|
end
|
249
302
|
end
|
250
303
|
|
304
|
+
# TODO - deprecate color_enabled - probably not until the last 2.x
|
305
|
+
# release before 3.0
|
306
|
+
alias_method :color_enabled, :color
|
307
|
+
alias_method :color_enabled=, :color=
|
308
|
+
define_predicate_for :color_enabled, :color
|
309
|
+
|
251
310
|
def libs=(libs)
|
252
311
|
libs.map {|lib| $LOAD_PATH.unshift lib}
|
253
312
|
end
|
@@ -277,24 +336,26 @@ EOM
|
|
277
336
|
end
|
278
337
|
end
|
279
338
|
|
280
|
-
# Run examples defined on
|
339
|
+
# Run examples defined on `line_numbers` in all files to run.
|
281
340
|
def line_numbers=(line_numbers)
|
282
|
-
filter_run
|
283
|
-
end
|
284
|
-
|
285
|
-
def add_location(file_path, line_numbers)
|
286
|
-
# Filter locations is a hash of expanded paths to arrays of line numbers
|
287
|
-
# to match against.
|
288
|
-
#
|
289
|
-
filter_locations = ((self.filter || {})[:locations] ||= {})
|
290
|
-
(filter_locations[File.expand_path(file_path)] ||= []).push(*line_numbers)
|
291
|
-
filter_run({ :locations => filter_locations })
|
341
|
+
filter_run :line_numbers => line_numbers.map{|l| l.to_i}
|
292
342
|
end
|
293
343
|
|
294
344
|
def full_description=(description)
|
295
|
-
filter_run
|
345
|
+
filter_run :full_description => /#{description}/
|
296
346
|
end
|
297
347
|
|
348
|
+
# @overload add_formatter(formatter)
|
349
|
+
#
|
350
|
+
# Adds a formatter to the formatters collection. `formatter` can be a
|
351
|
+
# string representing any of the built-in formatters (see
|
352
|
+
# `built_in_formatter`), or a custom formatter class.
|
353
|
+
#
|
354
|
+
# ### Note
|
355
|
+
#
|
356
|
+
# For internal purposes, `add_formatter` also accepts the name of a class
|
357
|
+
# and path to a file that contains that class definition, but you should
|
358
|
+
# consider that a private api that may change at any time without notice.
|
298
359
|
def add_formatter(formatter_to_use, path=nil)
|
299
360
|
formatter_class =
|
300
361
|
built_in_formatter(formatter_to_use) ||
|
@@ -323,10 +384,12 @@ EOM
|
|
323
384
|
self.files_to_run = get_files_to_run(files)
|
324
385
|
end
|
325
386
|
|
387
|
+
# @api private
|
326
388
|
def command
|
327
389
|
$0.split(File::SEPARATOR).last
|
328
390
|
end
|
329
391
|
|
392
|
+
# @api private
|
330
393
|
def get_files_to_run(files)
|
331
394
|
patterns = pattern.split(",")
|
332
395
|
files.map do |file|
|
@@ -341,7 +404,7 @@ EOM
|
|
341
404
|
else
|
342
405
|
if file =~ /^(.*?)((?:\:\d+)+)$/
|
343
406
|
path, lines = $1, $2[1..-1].split(":").map{|n| n.to_i}
|
344
|
-
add_location path, lines
|
407
|
+
filter_manager.add_location path, lines
|
345
408
|
path
|
346
409
|
else
|
347
410
|
file
|
@@ -350,8 +413,27 @@ EOM
|
|
350
413
|
end.flatten
|
351
414
|
end
|
352
415
|
|
353
|
-
#
|
354
|
-
#
|
416
|
+
# Creates a method that delegates to `example` including the submitted
|
417
|
+
# `args`. Used internally to add variants of `example` like `pending`:
|
418
|
+
#
|
419
|
+
# @example
|
420
|
+
# alias_example_to :pending, :pending => true
|
421
|
+
#
|
422
|
+
# # This lets you do this:
|
423
|
+
#
|
424
|
+
# describe Thing do
|
425
|
+
# pending "does something" do
|
426
|
+
# thing = Thing.new
|
427
|
+
# end
|
428
|
+
# end
|
429
|
+
#
|
430
|
+
# # ... which is the equivalent of
|
431
|
+
#
|
432
|
+
# describe Thing do
|
433
|
+
# it "does something", :pending => true do
|
434
|
+
# thing = Thing.new
|
435
|
+
# end
|
436
|
+
# end
|
355
437
|
def alias_example_to(new_name, *args)
|
356
438
|
extra_options = build_metadata_hash_from(args)
|
357
439
|
RSpec::Core::ExampleGroup.alias_example_to(new_name, extra_options)
|
@@ -382,50 +464,82 @@ EOM
|
|
382
464
|
RSpec::Core::ExampleGroup.alias_it_should_behave_like_to(new_name, report_label)
|
383
465
|
end
|
384
466
|
|
385
|
-
|
386
|
-
|
387
|
-
|
467
|
+
# Adds key/value pairs to the `inclusion_filter`. If the
|
468
|
+
# `treat_symbols_as_metadata_keys_with_true_values` config option is set
|
469
|
+
# to true and `args` includes any symbols that are not part of a hash,
|
470
|
+
# each symbol is treated as a key in the hash with the value `true`.
|
471
|
+
#
|
472
|
+
# ### Note
|
473
|
+
#
|
474
|
+
# Filters set using this method can be overridden from the command line
|
475
|
+
# or config files (e.g. `.rspec`).
|
476
|
+
#
|
477
|
+
# @example
|
478
|
+
# filter_run_including :x => 'y'
|
479
|
+
#
|
480
|
+
# # with treat_symbols_as_metadata_keys_with_true_values = true
|
481
|
+
# filter_run_including :foo # results in {:foo => true}
|
482
|
+
def filter_run_including(*args)
|
483
|
+
filter_manager.include :low_priority, build_metadata_hash_from(args)
|
388
484
|
end
|
389
485
|
|
390
|
-
|
391
|
-
def exclusion_filter
|
392
|
-
settings[:exclusion_filter] || {}
|
393
|
-
end
|
486
|
+
alias_method :filter_run, :filter_run_including
|
394
487
|
|
488
|
+
# Clears and reassigns the `inclusion_filter`. Set to `nil` if you don't
|
489
|
+
# want any inclusion filter at all.
|
490
|
+
#
|
491
|
+
# ### Warning
|
492
|
+
#
|
493
|
+
# This overrides any inclusion filters/tags set on the command line or in
|
494
|
+
# configuration files.
|
395
495
|
def inclusion_filter=(filter)
|
396
|
-
|
496
|
+
filter_manager.include :replace, build_metadata_hash_from([filter])
|
397
497
|
end
|
398
498
|
|
499
|
+
alias_method :filter=, :inclusion_filter=
|
500
|
+
|
501
|
+
# Returns the `inclusion_filter`. If none has been set, returns an empty
|
502
|
+
# hash.
|
399
503
|
def inclusion_filter
|
400
|
-
|
504
|
+
filter_manager.inclusions
|
401
505
|
end
|
402
506
|
|
403
|
-
|
404
|
-
force_overwrite = if args.last.is_a?(Hash) || args.last.is_a?(Symbol)
|
405
|
-
false
|
406
|
-
else
|
407
|
-
args.pop
|
408
|
-
end
|
409
|
-
|
410
|
-
options = build_metadata_hash_from(args)
|
507
|
+
alias_method :filter, :inclusion_filter
|
411
508
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
509
|
+
# Adds key/value pairs to the `exclusion_filter`. If the
|
510
|
+
# `treat_symbols_as_metadata_keys_with_true_values` config option is set
|
511
|
+
# to true and `args` excludes any symbols that are not part of a hash,
|
512
|
+
# each symbol is treated as a key in the hash with the value `true`.
|
513
|
+
#
|
514
|
+
# ### Note
|
515
|
+
#
|
516
|
+
# Filters set using this method can be overridden from the command line
|
517
|
+
# or config files (e.g. `.rspec`).
|
518
|
+
#
|
519
|
+
# @example
|
520
|
+
# filter_run_excluding :x => 'y'
|
521
|
+
#
|
522
|
+
# # with treat_symbols_as_metadata_keys_with_true_values = true
|
523
|
+
# filter_run_excluding :foo # results in {:foo => true}
|
524
|
+
def filter_run_excluding(*args)
|
525
|
+
filter_manager.exclude :low_priority, build_metadata_hash_from(args)
|
422
526
|
end
|
423
527
|
|
424
|
-
|
528
|
+
# Clears and reassigns the `exclusion_filter`. Set to `nil` if you don't
|
529
|
+
# want any exclusion filter at all.
|
530
|
+
#
|
531
|
+
# ### Warning
|
532
|
+
#
|
533
|
+
# This overrides any exclusion filters/tags set on the command line or in
|
534
|
+
# configuration files.
|
535
|
+
def exclusion_filter=(filter)
|
536
|
+
filter_manager.exclude :replace, build_metadata_hash_from([filter])
|
537
|
+
end
|
425
538
|
|
426
|
-
|
427
|
-
|
428
|
-
|
539
|
+
# Returns the `exclusion_filter`. If none has been set, returns an empty
|
540
|
+
# hash.
|
541
|
+
def exclusion_filter
|
542
|
+
filter_manager.exclusions
|
429
543
|
end
|
430
544
|
|
431
545
|
def include(mod, *args)
|
@@ -438,6 +552,10 @@ EOM
|
|
438
552
|
include_or_extend_modules << [:extend, mod, filters]
|
439
553
|
end
|
440
554
|
|
555
|
+
# @api private
|
556
|
+
#
|
557
|
+
# Used internally to extend a group with modules using `include` and/or
|
558
|
+
# `extend`.
|
441
559
|
def configure_group(group)
|
442
560
|
include_or_extend_modules.each do |include_or_extend, mod, filters|
|
443
561
|
next unless filters.empty? || group.any_apply?(filters)
|
@@ -460,8 +578,35 @@ EOM
|
|
460
578
|
raise_if_rspec_1_is_loaded
|
461
579
|
end
|
462
580
|
|
581
|
+
attr_reader :seed
|
582
|
+
|
583
|
+
def seed=(seed)
|
584
|
+
@order = 'rand'
|
585
|
+
@seed = seed.to_i
|
586
|
+
end
|
587
|
+
|
588
|
+
def randomize?
|
589
|
+
order.to_s.match(/rand/)
|
590
|
+
end
|
591
|
+
|
592
|
+
remove_method :order=
|
593
|
+
def order=(type)
|
594
|
+
order, seed = type.to_s.split(':')
|
595
|
+
if order == 'default'
|
596
|
+
@order = nil
|
597
|
+
@seed = nil
|
598
|
+
else
|
599
|
+
@order = order
|
600
|
+
@seed = seed.to_i if seed
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
463
604
|
private
|
464
605
|
|
606
|
+
def value_for(key, default=nil)
|
607
|
+
@preferred_options.has_key?(key) ? @preferred_options[key] : default
|
608
|
+
end
|
609
|
+
|
465
610
|
def assert_no_example_groups_defined(config_option)
|
466
611
|
if RSpec.world.example_groups.any?
|
467
612
|
raise MustBeConfiguredBeforeExampleGroupsError.new(
|
@@ -524,7 +669,7 @@ MESSAGE
|
|
524
669
|
end
|
525
670
|
end
|
526
671
|
end
|
527
|
-
|
672
|
+
|
528
673
|
def string_const?(str)
|
529
674
|
str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
|
530
675
|
end
|