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.
Files changed (56) hide show
  1. data/README.md +1 -1
  2. data/features/command_line/order.feature +29 -0
  3. data/features/command_line/tag.feature +10 -9
  4. data/features/configuration/default_path.feature +2 -2
  5. data/features/filtering/exclusion_filters.feature +1 -1
  6. data/features/filtering/run_all_when_everything_filtered.feature +1 -1
  7. data/features/subject/attribute_of_subject.feature +1 -1
  8. data/lib/rspec/core.rb +148 -12
  9. data/lib/rspec/core/command_line.rb +2 -2
  10. data/lib/rspec/core/configuration.rb +300 -155
  11. data/lib/rspec/core/configuration_options.rb +34 -53
  12. data/lib/rspec/core/deprecation.rb +4 -0
  13. data/lib/rspec/core/drb_options.rb +72 -0
  14. data/lib/rspec/core/example.rb +58 -24
  15. data/lib/rspec/core/example_group.rb +10 -5
  16. data/lib/rspec/core/extensions.rb +1 -0
  17. data/lib/rspec/core/extensions/ordered.rb +16 -0
  18. data/lib/rspec/core/filter_manager.rb +170 -0
  19. data/lib/rspec/core/formatters/base_formatter.rb +3 -1
  20. data/lib/rspec/core/formatters/base_text_formatter.rb +6 -0
  21. data/lib/rspec/core/formatters/snippet_extractor.rb +1 -1
  22. data/lib/rspec/core/hooks.rb +197 -1
  23. data/lib/rspec/core/let.rb +3 -2
  24. data/lib/rspec/core/metadata.rb +25 -4
  25. data/lib/rspec/core/option_parser.rb +89 -54
  26. data/lib/rspec/core/pending.rb +41 -0
  27. data/lib/rspec/core/rake_task.rb +9 -25
  28. data/lib/rspec/core/reporter.rb +43 -19
  29. data/lib/rspec/core/shared_context.rb +35 -0
  30. data/lib/rspec/core/shared_example_group.rb +0 -1
  31. data/lib/rspec/core/subject.rb +4 -4
  32. data/lib/rspec/core/version.rb +1 -1
  33. data/lib/rspec/core/world.rb +34 -52
  34. data/spec/autotest/failed_results_re_spec.rb +2 -2
  35. data/spec/command_line/order_spec.rb +131 -0
  36. data/spec/rspec/core/command_line_spec.rb +2 -1
  37. data/spec/rspec/core/configuration_options_spec.rb +83 -163
  38. data/spec/rspec/core/configuration_spec.rb +311 -139
  39. data/spec/rspec/core/drb_options_spec.rb +131 -0
  40. data/spec/rspec/core/example_group_spec.rb +22 -11
  41. data/spec/rspec/core/example_spec.rb +1 -2
  42. data/spec/rspec/core/filter_manager_spec.rb +175 -0
  43. data/spec/rspec/core/formatters/helpers_spec.rb +1 -1
  44. data/spec/rspec/core/formatters/html_formatter_spec.rb +3 -2
  45. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -1
  46. data/spec/rspec/core/metadata_spec.rb +21 -6
  47. data/spec/rspec/core/option_parser_spec.rb +74 -0
  48. data/spec/rspec/core/reporter_spec.rb +18 -1
  49. data/spec/rspec/core/shared_context_spec.rb +54 -17
  50. data/spec/rspec/core/subject_spec.rb +1 -1
  51. data/spec/rspec/core/world_spec.rb +7 -188
  52. data/spec/spec_helper.rb +47 -43
  53. data/spec/support/config_options_helper.rb +27 -0
  54. metadata +28 -12
  55. data/lib/rspec/core/expecting/with_rspec.rb +0 -9
  56. data/lib/rspec/core/expecting/with_stdlib.rb +0 -9
@@ -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
 
@@ -20,39 +20,26 @@ module RSpec
20
20
  # 'spec/**/*_spec.rb'
21
21
  attr_accessor :pattern
22
22
 
23
- # Deprecated and has no effect. The rake task now checks
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
- # Deprecated and has no effect. The rake task now checks
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
- # Deprecated. Use ruby_opts="-w" instead.
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
- # Deprecated. Use rspec_opts instead.
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
@@ -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
- def report(count)
10
- start(count)
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 - $rspec_start_time
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
@@ -15,7 +15,6 @@ module RSpec
15
15
  host.class_eval(&block)
16
16
  end
17
17
  RSpec.configuration.extend(mod, *args)
18
- else
19
18
  end
20
19
  end
21
20
 
@@ -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
- # == Examples
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
- # == Examples
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
- # == Examples
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
- # == Examples
142
+ # @example
143
143
  #
144
144
  # describe CheckingAccount, "with $50" do
145
145
  # subject { CheckingAccount.new(:amount => 50, :currency => :USD) }
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Version
4
- STRING = '2.7.1'
4
+ STRING = '2.8.0.rc1'
5
5
  end
6
6
  end
7
7
  end
@@ -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 = apply_exclusion_filters(examples, exclusion_filter)
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.extend(Describable)
37
+ @configuration.inclusion_filter
55
38
  end
56
39
 
57
40
  def exclusion_filter
58
- @configuration.exclusion_filter.extend(Describable)
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( "No examples matched #{inclusion_filter.description}. Running all.")
81
+ reporter.message("#{everything_filtered_message}; ignoring #{inclusion_filter.description}")
98
82
  filtered_examples.clear
99
- @configuration.clear_inclusion_filter
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 filter_announcements.empty?
88
+ if filter_manager.empty?
108
89
  reporter.message("No examples found.")
109
- elsif !inclusion_filter.empty?
110
- message = "No examples matched #{inclusion_filter.description}."
90
+ elsif exclusion_filter.empty_without_conditional_filters?
91
+ message = everything_filtered_message
111
92
  if @configuration.run_all_when_everything_filtered?
112
- message << " Running all."
93
+ message << "; ignoring #{inclusion_filter.description}"
113
94
  end
114
95
  reporter.message(message)
115
- elsif !exclusion_filter.empty?
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 << "including #{inclusion_filter.description}"
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 << "excluding #{exclusion_filter.description}"
114
+ announcements << "exclude #{exclusion_filter.description}"
133
115
  end
134
116
  end
135
117