rspec-core 2.7.1 → 2.8.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|