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/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
|
|