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/lib/rspec/core/pending.rb
CHANGED
@@ -5,6 +5,47 @@ module RSpec
|
|
5
5
|
|
6
6
|
DEFAULT_MESSAGE = 'No reason given'
|
7
7
|
|
8
|
+
# @overload pending()
|
9
|
+
# @overload pending(message)
|
10
|
+
# @overload pending(message, &block)
|
11
|
+
#
|
12
|
+
# Stops execution of an example, and reports it as pending. Takes an
|
13
|
+
# optional message and block.
|
14
|
+
#
|
15
|
+
# @param [String] message optional message to add to the summary report.
|
16
|
+
# @param [Block] block optional block. If it fails, the example is
|
17
|
+
# reported as pending. If it executes cleanly the example fails.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# describe "an example" do
|
22
|
+
# # reported as "Pending: no reason given"
|
23
|
+
# it "is pending with no message" do
|
24
|
+
# pending
|
25
|
+
# this_does_not_get_executed
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # reported as "Pending: something else getting finished"
|
29
|
+
# it "is pending with a custom message" do
|
30
|
+
# pending("something else getting finished")
|
31
|
+
# this_does_not_get_executed
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # reported as "Pending: something else getting finished"
|
35
|
+
# it "is pending with a failing block" do
|
36
|
+
# pending("something else getting finished") do
|
37
|
+
# raise "this is the failure"
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # reported as failure, saying we expected the block to fail but
|
42
|
+
# # it passed.
|
43
|
+
# it "is pending with a passing block" do
|
44
|
+
# pending("something else getting finished") do
|
45
|
+
# true.should be(true)
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
# end
|
8
49
|
def pending(*args)
|
9
50
|
return self.class.before(:each) { pending(*args) } unless example
|
10
51
|
|
data/lib/rspec/core/rake_task.rb
CHANGED
@@ -20,39 +20,26 @@ module RSpec
|
|
20
20
|
# 'spec/**/*_spec.rb'
|
21
21
|
attr_accessor :pattern
|
22
22
|
|
23
|
-
#
|
24
|
-
# ENV['BUNDLE_GEMFILE'] instead.
|
25
|
-
#
|
26
|
-
# By default, if there is a Gemfile, the generated command will include
|
27
|
-
# 'bundle exec'. Set this to true to ignore the presence of a Gemfile, and
|
28
|
-
# not add 'bundle exec' to the command.
|
29
|
-
#
|
30
|
-
# default:
|
31
|
-
# false
|
23
|
+
# @deprecated
|
24
|
+
# Has no effect. The rake task now checks ENV['BUNDLE_GEMFILE'] instead.
|
32
25
|
def skip_bundler=(*)
|
33
26
|
RSpec.deprecate("RSpec::Core::RakeTask#skip_bundler=")
|
34
27
|
end
|
35
28
|
|
36
|
-
#
|
37
|
-
# ENV['BUNDLE_GEMFILE'] instead.
|
38
|
-
#
|
39
|
-
# Name of Gemfile to use.
|
40
|
-
#
|
41
|
-
# default:
|
42
|
-
# Gemfile
|
29
|
+
# @deprecated
|
30
|
+
# Has no effect. The rake task now checks ENV['BUNDLE_GEMFILE'] instead.
|
43
31
|
def gemfile=(*)
|
44
32
|
RSpec.deprecate("RSpec::Core::RakeTask#gemfile=", 'ENV["BUNDLE_GEMFILE"]')
|
45
33
|
end
|
46
34
|
|
47
|
-
#
|
35
|
+
# @deprecated
|
36
|
+
# Use ruby_opts="-w" instead.
|
48
37
|
#
|
49
38
|
# When true, requests that the specs be run with the warning flag set.
|
50
39
|
# e.g. "ruby -w"
|
51
40
|
#
|
52
41
|
# default:
|
53
42
|
# false
|
54
|
-
attr_reader :warning
|
55
|
-
|
56
43
|
def warning=(true_or_false)
|
57
44
|
RSpec.deprecate("RSpec::Core::RakeTask#warning=", 'ruby_opts="-w"')
|
58
45
|
@warning = true_or_false
|
@@ -110,7 +97,8 @@ module RSpec
|
|
110
97
|
# nil
|
111
98
|
attr_accessor :rspec_opts
|
112
99
|
|
113
|
-
#
|
100
|
+
# @deprecated
|
101
|
+
# Use rspec_opts instead.
|
114
102
|
#
|
115
103
|
# Command line options to pass to rspec.
|
116
104
|
#
|
@@ -167,7 +155,7 @@ module RSpec
|
|
167
155
|
cmd_parts = []
|
168
156
|
cmd_parts << RUBY
|
169
157
|
cmd_parts << ruby_opts
|
170
|
-
cmd_parts << "-w" if warning
|
158
|
+
cmd_parts << "-w" if @warning
|
171
159
|
cmd_parts << "-S"
|
172
160
|
cmd_parts << runner
|
173
161
|
if rcov
|
@@ -189,10 +177,6 @@ module RSpec
|
|
189
177
|
rcov ? rcov_path : rspec_path
|
190
178
|
end
|
191
179
|
|
192
|
-
def warning?
|
193
|
-
warning
|
194
|
-
end
|
195
|
-
|
196
180
|
def blank
|
197
181
|
lambda {|s| s == ""}
|
198
182
|
end
|
data/lib/rspec/core/reporter.rb
CHANGED
@@ -3,33 +3,42 @@ module RSpec::Core
|
|
3
3
|
def initialize(*formatters)
|
4
4
|
@formatters = formatters
|
5
5
|
@example_count = @failure_count = @pending_count = 0
|
6
|
-
@duration = nil
|
6
|
+
@duration = @start = nil
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
# @api
|
10
|
+
# @overload report(count, &block)
|
11
|
+
# @overload report(count, seed, &block)
|
12
|
+
# @param [Integer] count the number of examples being run
|
13
|
+
# @param [Integer] seed the seed used to randomize the spec run
|
14
|
+
# @param [Block] block yields itself for further reporting.
|
15
|
+
#
|
16
|
+
# Initializes the report run and yields itself for further reporting. The
|
17
|
+
# block is required, so that the reporter can manage cleaning up after the
|
18
|
+
# run.
|
19
|
+
#
|
20
|
+
# ### Warning:
|
21
|
+
#
|
22
|
+
# The `seed` argument is an internal API and is not guaranteed to be
|
23
|
+
# supported in the future.
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
#
|
27
|
+
# reporter.report(group.examples.size) do |r|
|
28
|
+
# example_groups.map {|g| g.run(r) }
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
def report(expected_example_count, seed=nil)
|
32
|
+
start(expected_example_count)
|
11
33
|
begin
|
12
34
|
yield self
|
13
35
|
ensure
|
14
|
-
finish
|
36
|
+
finish(seed)
|
15
37
|
end
|
16
38
|
end
|
17
39
|
|
18
|
-
def finish
|
19
|
-
begin
|
20
|
-
stop
|
21
|
-
notify :start_dump
|
22
|
-
notify :dump_pending
|
23
|
-
notify :dump_failures
|
24
|
-
notify :dump_summary, @duration, @example_count, @failure_count, @pending_count
|
25
|
-
ensure
|
26
|
-
notify :close
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
alias_method :abort, :finish
|
31
|
-
|
32
40
|
def start(expected_example_count)
|
41
|
+
@start = Time.now
|
33
42
|
notify :start, expected_example_count
|
34
43
|
end
|
35
44
|
|
@@ -64,8 +73,23 @@ module RSpec::Core
|
|
64
73
|
notify :example_pending, example
|
65
74
|
end
|
66
75
|
|
76
|
+
def finish(seed)
|
77
|
+
begin
|
78
|
+
stop
|
79
|
+
notify :start_dump
|
80
|
+
notify :dump_pending
|
81
|
+
notify :dump_failures
|
82
|
+
notify :dump_summary, @duration, @example_count, @failure_count, @pending_count
|
83
|
+
notify :seed, seed if seed
|
84
|
+
ensure
|
85
|
+
notify :close
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :abort, :finish
|
90
|
+
|
67
91
|
def stop
|
68
|
-
@duration = Time.now -
|
92
|
+
@duration = Time.now - @start if @start
|
69
93
|
notify :stop
|
70
94
|
end
|
71
95
|
|
@@ -1,7 +1,26 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
|
+
# Exposes [ExampleGroup](ExampleGroup)-level methods to a module, so you
|
4
|
+
# can include that module in an [ExampleGroup](ExampleGroup).
|
5
|
+
#
|
6
|
+
# @note exposed as `RSpec::SharedContext`
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# module LoggedInAsAdmin
|
11
|
+
# extend RSpec::SharedContext
|
12
|
+
# before(:each) do
|
13
|
+
# log_in_as :admin
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# describe "admin section" do
|
18
|
+
# include LoggedInAsAdmin
|
19
|
+
# # ...
|
20
|
+
# end
|
3
21
|
module SharedContext
|
4
22
|
include Hooks
|
23
|
+
include Let::ClassMethods
|
5
24
|
|
6
25
|
def included(group)
|
7
26
|
[:before, :after].each do |type|
|
@@ -9,8 +28,24 @@ module RSpec
|
|
9
28
|
group.hooks[type][scope].concat hooks[type][scope]
|
10
29
|
end
|
11
30
|
end
|
31
|
+
_nested_group_declarations.each do |name, block, *args|
|
32
|
+
group.describe name, *args, &block
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def describe(name, *args, &block)
|
37
|
+
_nested_group_declarations << [name, block, *args]
|
12
38
|
end
|
13
39
|
|
40
|
+
alias_method :context, :describe
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def _nested_group_declarations
|
45
|
+
@_nested_group_declarations ||= []
|
46
|
+
end
|
14
47
|
end
|
15
48
|
end
|
49
|
+
|
50
|
+
SharedContext = Core::SharedContext
|
16
51
|
end
|
data/lib/rspec/core/subject.rb
CHANGED
@@ -11,7 +11,7 @@ module RSpec
|
|
11
11
|
# declared in the example group, then +subject+ will return a new
|
12
12
|
# instance of that class.
|
13
13
|
#
|
14
|
-
#
|
14
|
+
# @example
|
15
15
|
#
|
16
16
|
# # explicit subject defined by the subject method
|
17
17
|
# describe Person do
|
@@ -45,7 +45,7 @@ module RSpec
|
|
45
45
|
# an implicit subject (see +subject+), this supports very concise
|
46
46
|
# expressions.
|
47
47
|
#
|
48
|
-
#
|
48
|
+
# @example
|
49
49
|
#
|
50
50
|
# describe Person do
|
51
51
|
# it { should be_eligible_to_vote }
|
@@ -57,7 +57,7 @@ module RSpec
|
|
57
57
|
# Just like +should+, +should_not+ delegates to the subject (implicit or
|
58
58
|
# explicit) of the example group.
|
59
59
|
#
|
60
|
-
#
|
60
|
+
# @example
|
61
61
|
#
|
62
62
|
# describe Person do
|
63
63
|
# it { should_not be_eligible_to_vote }
|
@@ -139,7 +139,7 @@ module RSpec
|
|
139
139
|
# Defines an explicit subject for an example group which can then be the
|
140
140
|
# implicit receiver (through delegation) of calls to +should+.
|
141
141
|
#
|
142
|
-
#
|
142
|
+
# @example
|
143
143
|
#
|
144
144
|
# describe CheckingAccount, "with $50" do
|
145
145
|
# subject { CheckingAccount.new(:amount => 50, :currency => :USD) }
|
data/lib/rspec/core/version.rb
CHANGED
data/lib/rspec/core/world.rb
CHANGED
@@ -2,27 +2,6 @@ module RSpec
|
|
2
2
|
module Core
|
3
3
|
class World
|
4
4
|
|
5
|
-
module Describable
|
6
|
-
PROC_HEX_NUMBER = /0x[0-9a-f]+@/
|
7
|
-
PROJECT_DIR = File.expand_path('.')
|
8
|
-
|
9
|
-
def description
|
10
|
-
reject { |k, v| RSpec::Core::Configuration::CONDITIONAL_FILTERS[k] == v }.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','')
|
11
|
-
end
|
12
|
-
|
13
|
-
def empty_without_conditional_filters?
|
14
|
-
reject { |k, v| RSpec::Core::Configuration::CONDITIONAL_FILTERS[k] == v }.empty?
|
15
|
-
end
|
16
|
-
|
17
|
-
def reject
|
18
|
-
super rescue {}
|
19
|
-
end
|
20
|
-
|
21
|
-
def empty?
|
22
|
-
super rescue false
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
5
|
include RSpec::Core::Hooks
|
27
6
|
|
28
7
|
attr_reader :example_groups, :filtered_examples, :wants_to_quit
|
@@ -30,13 +9,13 @@ module RSpec
|
|
30
9
|
|
31
10
|
def initialize(configuration=RSpec.configuration)
|
32
11
|
@configuration = configuration
|
33
|
-
@example_groups = []
|
12
|
+
@example_groups = [].extend(Extensions::Ordered)
|
34
13
|
@filtered_examples = Hash.new { |hash,group|
|
35
14
|
hash[group] = begin
|
36
15
|
examples = group.examples.dup
|
37
|
-
examples =
|
38
|
-
examples = apply_inclusion_filters(examples, inclusion_filter)
|
16
|
+
examples = filter_manager.prune(examples)
|
39
17
|
examples.uniq
|
18
|
+
examples.extend(Extensions::Ordered)
|
40
19
|
end
|
41
20
|
}
|
42
21
|
end
|
@@ -45,17 +24,21 @@ module RSpec
|
|
45
24
|
example_groups.clear
|
46
25
|
end
|
47
26
|
|
27
|
+
def filter_manager
|
28
|
+
@configuration.filter_manager
|
29
|
+
end
|
30
|
+
|
48
31
|
def register(example_group)
|
49
32
|
example_groups << example_group
|
50
33
|
example_group
|
51
34
|
end
|
52
35
|
|
53
36
|
def inclusion_filter
|
54
|
-
@configuration.inclusion_filter
|
37
|
+
@configuration.inclusion_filter
|
55
38
|
end
|
56
39
|
|
57
40
|
def exclusion_filter
|
58
|
-
@configuration.exclusion_filter
|
41
|
+
@configuration.exclusion_filter
|
59
42
|
end
|
60
43
|
|
61
44
|
def configure_group(group)
|
@@ -70,16 +53,6 @@ module RSpec
|
|
70
53
|
example_groups.collect {|g| g.descendants}.flatten.inject(0) { |sum, g| sum += g.filtered_examples.size }
|
71
54
|
end
|
72
55
|
|
73
|
-
def apply_inclusion_filters(examples, filters)
|
74
|
-
filters.empty? ? examples : examples.select {|e| e.metadata.any_apply?(filters)}
|
75
|
-
end
|
76
|
-
|
77
|
-
alias_method :find, :apply_inclusion_filters
|
78
|
-
|
79
|
-
def apply_exclusion_filters(examples, filters)
|
80
|
-
filters.empty? ? examples : examples.reject {|e| e.metadata.any_apply?(filters)}
|
81
|
-
end
|
82
|
-
|
83
56
|
def preceding_declaration_line(filter_line)
|
84
57
|
declaration_line_numbers.sort.inject(nil) do |highest_prior_declaration_line, line|
|
85
58
|
line <= filter_line ? line : highest_prior_declaration_line
|
@@ -93,43 +66,52 @@ module RSpec
|
|
93
66
|
def announce_filters
|
94
67
|
filter_announcements = []
|
95
68
|
|
69
|
+
announce_inclusion_filter filter_announcements
|
70
|
+
announce_exclusion_filter filter_announcements
|
71
|
+
|
72
|
+
unless filter_manager.empty?
|
73
|
+
if filter_announcements.length == 1
|
74
|
+
reporter.message("Run options: #{filter_announcements[0]}")
|
75
|
+
else
|
76
|
+
reporter.message("Run options:\n #{filter_announcements.join("\n ")}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
96
80
|
if @configuration.run_all_when_everything_filtered? && example_count.zero?
|
97
|
-
reporter.message(
|
81
|
+
reporter.message("#{everything_filtered_message}; ignoring #{inclusion_filter.description}")
|
98
82
|
filtered_examples.clear
|
99
|
-
|
83
|
+
inclusion_filter.clear
|
100
84
|
end
|
101
85
|
|
102
|
-
announce_inclusion_filter filter_announcements
|
103
|
-
announce_exclusion_filter filter_announcements
|
104
|
-
|
105
86
|
if example_count.zero?
|
106
87
|
example_groups.clear
|
107
|
-
if
|
88
|
+
if filter_manager.empty?
|
108
89
|
reporter.message("No examples found.")
|
109
|
-
elsif
|
110
|
-
message =
|
90
|
+
elsif exclusion_filter.empty_without_conditional_filters?
|
91
|
+
message = everything_filtered_message
|
111
92
|
if @configuration.run_all_when_everything_filtered?
|
112
|
-
message << "
|
93
|
+
message << "; ignoring #{inclusion_filter.description}"
|
113
94
|
end
|
114
95
|
reporter.message(message)
|
115
|
-
elsif
|
116
|
-
reporter.message(
|
117
|
-
"No examples were matched. Perhaps #{exclusion_filter.description} is excluding everything?")
|
96
|
+
elsif inclusion_filter.empty?
|
97
|
+
reporter.message(everything_filtered_message)
|
118
98
|
end
|
119
|
-
elsif !filter_announcements.empty?
|
120
|
-
reporter.message("Run filtered #{filter_announcements.join(', ')}")
|
121
99
|
end
|
122
100
|
end
|
123
101
|
|
102
|
+
def everything_filtered_message
|
103
|
+
"\nAll examples were filtered out"
|
104
|
+
end
|
105
|
+
|
124
106
|
def announce_inclusion_filter(announcements)
|
125
107
|
unless inclusion_filter.empty?
|
126
|
-
announcements << "
|
108
|
+
announcements << "include #{inclusion_filter.description}"
|
127
109
|
end
|
128
110
|
end
|
129
111
|
|
130
112
|
def announce_exclusion_filter(announcements)
|
131
113
|
unless exclusion_filter.empty_without_conditional_filters?
|
132
|
-
announcements << "
|
114
|
+
announcements << "exclude #{exclusion_filter.description}"
|
133
115
|
end
|
134
116
|
end
|
135
117
|
|