rspec-core 2.99.0.beta2 → 2.99.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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog.md +122 -43
  3. data/features/command_line/line_number_option.feature +6 -11
  4. data/features/configuration/read_options_from_file.feature +2 -2
  5. data/features/expectation_framework_integration/configure_expectation_framework.feature +120 -25
  6. data/lib/autotest/discover.rb +10 -1
  7. data/lib/autotest/rspec2.rb +1 -1
  8. data/lib/rspec/core/command_line.rb +16 -5
  9. data/lib/rspec/core/configuration.rb +151 -119
  10. data/lib/rspec/core/deprecated_mutable_array_proxy.rb +32 -0
  11. data/lib/rspec/core/example.rb +3 -1
  12. data/lib/rspec/core/example_group.rb +174 -125
  13. data/lib/rspec/core/filter_manager.rb +48 -10
  14. data/lib/rspec/core/formatters.rb +137 -0
  15. data/lib/rspec/core/formatters/base_text_formatter.rb +25 -29
  16. data/lib/rspec/core/formatters/console_codes.rb +42 -0
  17. data/lib/rspec/core/formatters/deprecation_formatter.rb +14 -5
  18. data/lib/rspec/core/formatters/helpers.rb +1 -1
  19. data/lib/rspec/core/memoized_helpers.rb +2 -1
  20. data/lib/rspec/core/metadata.rb +63 -1
  21. data/lib/rspec/core/minitest_assertions_adapter.rb +28 -0
  22. data/lib/rspec/core/option_parser.rb +20 -1
  23. data/lib/rspec/core/pending.rb +26 -4
  24. data/lib/rspec/core/reporter.rb +1 -1
  25. data/lib/rspec/core/runner.rb +2 -2
  26. data/lib/rspec/core/shared_example_group.rb +11 -4
  27. data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
  28. data/lib/rspec/core/version.rb +1 -1
  29. data/lib/rspec/core/world.rb +2 -2
  30. data/spec/autotest/discover_spec.rb +38 -8
  31. data/spec/rspec/core/command_line_spec.rb +47 -29
  32. data/spec/rspec/core/configuration_options_spec.rb +1 -1
  33. data/spec/rspec/core/configuration_spec.rb +223 -37
  34. data/spec/rspec/core/example_group_spec.rb +116 -6
  35. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +24 -4
  36. data/spec/rspec/core/formatters/console_codes_spec.rb +50 -0
  37. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +20 -3
  38. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +1 -0
  39. data/spec/rspec/core/formatters/html_formatted.html +3 -4
  40. data/spec/rspec/core/formatters/html_formatter_spec.rb +10 -4
  41. data/spec/rspec/core/formatters/text_mate_formatted.html +3 -4
  42. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +9 -3
  43. data/spec/rspec/core/hooks_filtering_spec.rb +5 -5
  44. data/spec/rspec/core/memoized_helpers_spec.rb +38 -0
  45. data/spec/rspec/core/metadata_spec.rb +24 -1
  46. data/spec/rspec/core/option_parser_spec.rb +39 -2
  47. data/spec/rspec/core/pending_example_spec.rb +14 -0
  48. data/spec/rspec/core/pending_spec.rb +27 -0
  49. data/spec/rspec/core/runner_spec.rb +3 -3
  50. data/spec/rspec/core/shared_context_spec.rb +1 -1
  51. data/spec/rspec/core/shared_example_group_spec.rb +18 -0
  52. data/spec/support/helper_methods.rb +4 -0
  53. metadata +105 -106
@@ -0,0 +1,32 @@
1
+ module RSpec
2
+ module Core
3
+ class DeprecatedMutableArrayProxy
4
+
5
+ def initialize(array)
6
+ @array = array
7
+ end
8
+
9
+ mutated_methods =
10
+ [
11
+ :<<, :[]=, :clear, :collect!, :compact!, :concat, :delete,
12
+ :delete_at, :delete_if, :fill, :flatten!, :keep_if, :map!,
13
+ :pop, :push, :reject!, :replace, :reverse!, :rotate!,
14
+ :select!, :shift, :shuffle!, :slice!, :sort!, :sort_by!,
15
+ :uniq!, :unshift
16
+ ]
17
+ array_methods = Array.instance_methods.map(&:to_sym)
18
+
19
+ (array_methods & mutated_methods).each do |name|
20
+ define_method(name) do |*args, &block|
21
+ RSpec.deprecate "Mutating the `RSpec.configuration.formatters` array"
22
+ @array.__send__ name, *args, &block
23
+ end
24
+ end
25
+
26
+ (array_methods - mutated_methods).each do |name|
27
+ define_method(name) { |*args, &block| @array.__send__ name, *args, &block }
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -85,6 +85,8 @@ module RSpec
85
85
 
86
86
  # @deprecated access options via metadata instead
87
87
  def options
88
+ RSpec.deprecate("`RSpec::Core::Example#options`",
89
+ :replacement => "`RSpec::Core::Example#metadata`")
88
90
  @options
89
91
  end
90
92
 
@@ -112,7 +114,7 @@ module RSpec
112
114
  begin
113
115
  run_before_each
114
116
  @example_group_instance.instance_eval_with_args(self, &@example_block)
115
- rescue Pending::PendingDeclaredInExample => e
117
+ rescue Pending::SkipDeclaredInExample => e
116
118
  @pending_declared_in_example = e.message
117
119
  rescue Exception => e
118
120
  set_exception(e)
@@ -49,139 +49,166 @@ module RSpec
49
49
  end
50
50
 
51
51
  delegate_to_metadata :described_class, :file_path
52
- alias_method :display_name, :description
53
- # @private
54
- alias_method :describes, :described_class
55
52
 
56
53
  # @private
57
- # @macro [attach] define_example_method
58
- # @param [String] name
59
- # @param [Hash] extra_options
60
- # @param [Block] implementation
61
- # @yield [Example] the example object
62
- def self.define_example_method(name, extra_options={})
63
- module_eval(<<-END_RUBY, __FILE__, __LINE__)
64
- def #{name}(desc=nil, *args, &block)
65
- if #{name.inspect} == :pending
66
- RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\\|/, ''))
67
- |The semantics of `RSpec::Core::ExampleGroup#pending` are changing in RSpec 3.
68
- |In RSpec 2.x, it caused the example to be skipped. In RSpec 3, the example will
69
- |still be run but is expected to fail, and will be marked as a failure (rather
70
- |than as pending) if the example passes, just like how `pending` with a block
71
- |from within an example already works.
72
- |
73
- |To keep the same skip semantics, change `pending` to `skip`. Otherwise, if you
74
- |want the new RSpec 3 behavior, you can safely ignore this warning and continue
75
- |to upgrade to RSpec 3 without addressing it.
76
- |
77
- |Called from \#{CallerFilter.first_non_rspec_line}.
78
- |
79
- EOS
80
- end
81
- options = build_metadata_hash_from(args)
82
- options.update(:pending => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
83
- options.update(#{extra_options.inspect})
84
- examples << RSpec::Core::Example.new(self, desc, options, block)
85
- examples.last
86
- end
87
- END_RUBY
54
+ def display_name
55
+ RSpec.deprecate('`RSpec::Core::ExampleGroup.display_name`',
56
+ :replacement => "`RSpec::Core::ExampleGroup.description`")
57
+ description
88
58
  end
89
59
 
90
- # Defines an example within a group.
91
- # @example
92
- # example do
93
- # end
94
- #
95
- # example "does something" do
96
- # end
97
- #
98
- # example "does something", :with => 'additional metadata' do
99
- # end
100
- #
101
- # example "does something" do |ex|
102
- # # ex is the Example object that evals this block
103
- # end
104
- define_example_method :example
105
- # Defines an example within a group.
106
- # @example
107
- define_example_method :it
108
- # Defines an example within a group.
109
- # This is here primarily for backward compatibility with early versions
110
- # of RSpec which used `context` and `specify` instead of `describe` and
111
- # `it`.
112
- define_example_method :specify
113
-
114
- # Shortcut to define an example with `:focus` => true
115
- # @see example
116
- define_example_method :focus, :focused => true, :focus => true
117
- # Shortcut to define an example with `:focus` => true
118
- # @see example
119
- define_example_method :focused, :focused => true, :focus => true
120
- # Shortcut to define an example with `:focus` => true
121
- # @see example
122
- define_example_method :fit, :focused => true, :focus => true
123
-
124
- # Shortcut to define an example with :pending => true
125
- # @see example
126
- define_example_method :pending, :pending => true
127
- # Shortcut to define an example with :pending => true
128
- # Backported from RSpec 3 to aid migration.
129
- # @see example
130
- define_example_method :skip, :pending => true
131
- # Shortcut to define an example with :pending => 'Temporarily disabled with xexample'
132
- # @see example
133
- define_example_method :xexample, :pending => 'Temporarily disabled with xexample'
134
- # Shortcut to define an example with :pending => 'Temporarily disabled with xit'
135
- # @see example
136
- define_example_method :xit, :pending => 'Temporarily disabled with xit'
137
- # Shortcut to define an example with :pending => 'Temporarily disabled with xspecify'
138
- # @see example
139
- define_example_method :xspecify, :pending => 'Temporarily disabled with xspecify'
140
-
141
- # Works like `alias_method :name, :example` with the added benefit of
142
- # assigning default metadata to the generated example.
143
- #
144
- # @note Use with caution. This extends the language used in your
145
- # specs, but does not add any additional documentation. We use this
146
- # in rspec to define methods like `focus` and `xit`, but we also add
147
- # docs for those methods.
148
- def alias_example_to name, extra={}
149
- (class << self; self; end).define_example_method name, extra
60
+ # @private
61
+ def describes
62
+ RSpec.deprecate('`RSpec::Core::ExampleGroup.describes`',
63
+ :replacement => "`RSpec::Core::ExampleGroup.described_class`")
64
+ described_class
150
65
  end
66
+ end
151
67
 
152
- # @private
153
- # @macro [attach] define_nested_shared_group_method
154
- #
155
- # @see SharedExampleGroup
156
- def self.define_nested_shared_group_method(new_name, report_label=nil)
157
- module_eval(<<-END_RUBY, __FILE__, __LINE__)
158
- def #{new_name}(name, *args, &customization_block)
159
- group = describe("#{report_label || "it should behave like"} \#{name}") do
160
- find_and_eval_shared("examples", name, *args, &customization_block)
161
- end
162
- group.metadata[:shared_group_name] = name
163
- group
68
+ # @private
69
+ # @macro [attach] define_example_method
70
+ # @param [String] name
71
+ # @param [Hash] extra_options
72
+ # @param [Block] implementation
73
+ # @yield [Example] the example object
74
+ def self.define_example_method(name, extra_options={})
75
+ module_eval(<<-END_RUBY, __FILE__, __LINE__)
76
+ def self.#{name}(desc=nil, *args, &block)
77
+ if #{name.inspect} == :pending
78
+ RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\\|/, ''))
79
+ |The semantics of `RSpec::Core::ExampleGroup.pending` are changing in RSpec 3.
80
+ |In RSpec 2.x, it caused the example to be skipped. In RSpec 3, the example will
81
+ |still be run but is expected to fail, and will be marked as a failure (rather
82
+ |than as pending) if the example passes, just like how `pending` with a block
83
+ |from within an example already works.
84
+ |
85
+ |To keep the same skip semantics, change `pending` to `skip`. Otherwise, if you
86
+ |want the new RSpec 3 behavior, you can safely ignore this warning and continue
87
+ |to upgrade to RSpec 3 without addressing it.
88
+ |
89
+ |Called from \#{CallerFilter.first_non_rspec_line}.
90
+ |
91
+ EOS
164
92
  end
165
- END_RUBY
166
- end
93
+ options = build_metadata_hash_from(args)
94
+ options.update(:pending => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
95
+ # Backport from RSpec 3 to assist with upgrading
96
+ options.update(:pending => options[:skip]) if options[:skip]
97
+ options.update(#{extra_options.inspect})
98
+ examples << RSpec::Core::Example.new(self, desc, options, block)
99
+ examples.last
100
+ end
101
+ END_RUBY
102
+ end
103
+
104
+ # Defines an example within a group.
105
+ # @example
106
+ # example do
107
+ # end
108
+ #
109
+ # example "does something" do
110
+ # end
111
+ #
112
+ # example "does something", :with => 'additional metadata' do
113
+ # end
114
+ #
115
+ # example "does something" do |ex|
116
+ # # ex is the Example object that evals this block
117
+ # end
118
+ define_example_method :example
119
+ # Defines an example within a group.
120
+ # @example
121
+ define_example_method :it
122
+ # Defines an example within a group.
123
+ # This is here primarily for backward compatibility with early versions
124
+ # of RSpec which used `context` and `specify` instead of `describe` and
125
+ # `it`.
126
+ define_example_method :specify
127
+
128
+ # Shortcut to define an example with `:focus` => true
129
+ # @see example
130
+ define_example_method :focus, :focused => true, :focus => true
131
+ # Shortcut to define an example with `:focus` => true
132
+ # @see example
133
+ define_example_method :fit, :focused => true, :focus => true
134
+
135
+ # Shortcut to define an example with :pending => true
136
+ # @see example
137
+ define_example_method :pending, :pending => true
138
+ # Shortcut to define an example with :pending => true
139
+ # Backported from RSpec 3 to aid migration.
140
+ # @see example
141
+ define_example_method :skip, :pending => true
142
+ # Shortcut to define an example with :pending => 'Temporarily disabled with xexample'
143
+ # @see example
144
+ define_example_method :xexample, :pending => 'Temporarily disabled with xexample'
145
+ # Shortcut to define an example with :pending => 'Temporarily disabled with xit'
146
+ # @see example
147
+ define_example_method :xit, :pending => 'Temporarily disabled with xit'
148
+ # Shortcut to define an example with :pending => 'Temporarily disabled with xspecify'
149
+ # @see example
150
+ define_example_method :xspecify, :pending => 'Temporarily disabled with xspecify'
151
+
152
+ # Shortcut to define an example with `:focus` => true
153
+ # @see example
154
+ def self.focused(desc=nil, *args, &block)
155
+ RSpec.deprecate("`RSpec::Core::ExampleGroup.focused`",
156
+ :replacement => "`RSpec::Core::ExampleGroup.focus`")
157
+
158
+ metadata = Hash === args.last ? args.pop : {}
159
+ metadata.merge!(:focus => true, :focused => true)
160
+ args << metadata
161
+
162
+ example(desc, *args, &block)
163
+ end
164
+
165
+ # Works like `alias_method :name, :example` with the added benefit of
166
+ # assigning default metadata to the generated example.
167
+ #
168
+ # @note Use with caution. This extends the language used in your
169
+ # specs, but does not add any additional documentation. We use this
170
+ # in rspec to define methods like `focus` and `xit`, but we also add
171
+ # docs for those methods.
172
+ def self.alias_example_to name, extra={}
173
+ RSpec.deprecate("`RSpec::Core::ExampleGroup.alias_example_to`",
174
+ :replacement => "`RSpec::Core::Configuration#alias_example_to`")
175
+ define_example_method name, extra
176
+ end
167
177
 
168
- # Generates a nested example group and includes the shared content
169
- # mapped to `name` in the nested group.
170
- define_nested_shared_group_method :it_behaves_like, "behaves like"
171
- # Generates a nested example group and includes the shared content
172
- # mapped to `name` in the nested group.
173
- define_nested_shared_group_method :it_should_behave_like
178
+ # @private
179
+ # @macro [attach] define_nested_shared_group_method
180
+ #
181
+ # @see SharedExampleGroup
182
+ def self.define_nested_shared_group_method(new_name, report_label=nil)
183
+ module_eval(<<-END_RUBY, __FILE__, __LINE__)
184
+ def self.#{new_name}(name, *args, &customization_block)
185
+ group = describe("#{report_label || "it should behave like"} \#{name}") do
186
+ find_and_eval_shared("examples", name, *args, &customization_block)
187
+ end
188
+ group.metadata[:shared_group_name] = name
189
+ group
190
+ end
191
+ END_RUBY
192
+ end
174
193
 
175
- # Works like `alias_method :name, :it_behaves_like` with the added
176
- # benefit of assigning default metadata to the generated example.
177
- #
178
- # @note Use with caution. This extends the language used in your
179
- # specs, but does not add any additional documentation. We use this
180
- # in rspec to define `it_should_behave_like` (for backward
181
- # compatibility), but we also add docs for that method.
182
- def alias_it_behaves_like_to name, *args, &block
183
- (class << self; self; end).define_nested_shared_group_method name, *args, &block
184
- end
194
+ # Generates a nested example group and includes the shared content
195
+ # mapped to `name` in the nested group.
196
+ define_nested_shared_group_method :it_behaves_like, "behaves like"
197
+ # Generates a nested example group and includes the shared content
198
+ # mapped to `name` in the nested group.
199
+ define_nested_shared_group_method :it_should_behave_like
200
+
201
+ # Works like `alias_method :name, :it_behaves_like` with the added
202
+ # benefit of assigning default metadata to the generated example.
203
+ #
204
+ # @note Use with caution. This extends the language used in your
205
+ # specs, but does not add any additional documentation. We use this
206
+ # in rspec to define `it_should_behave_like` (for backward
207
+ # compatibility), but we also add docs for that method.
208
+ def self.alias_it_behaves_like_to name, *args, &block
209
+ RSpec.deprecate("`RSpec::Core::ExampleGroup.alias_it_behaves_like_to`",
210
+ :replacement => "`RSpec::Core::Configuration#alias_it_behaves_like_to`")
211
+ define_nested_shared_group_method name, *args, &block
185
212
  end
186
213
 
187
214
  # Includes shared content mapped to `name` directly in the group in which
@@ -296,8 +323,18 @@ WARNING
296
323
  def self.describe(*args, &example_group_block)
297
324
  @_subclass_count ||= 0
298
325
  @_subclass_count += 1
326
+
327
+ if Symbol === args.first || Hash === args.first
328
+ description_arg_behavior_changing_in_rspec_3 = DescriptionBehaviorChange.new(
329
+ args.first, CallerFilter.first_non_rspec_line
330
+ )
331
+ end
332
+
299
333
  args << {} unless args.last.is_a?(Hash)
300
- args.last.update(:example_group_block => example_group_block)
334
+ args.last.update(
335
+ :example_group_block => example_group_block,
336
+ :description_arg_behavior_changing_in_rspec_3 => description_arg_behavior_changing_in_rspec_3
337
+ )
301
338
 
302
339
  # TODO 2010-05-05: Because we don't know if const_set is thread-safe
303
340
  child = const_set(
@@ -308,6 +345,18 @@ WARNING
308
345
  child
309
346
  end
310
347
 
348
+ DescriptionBehaviorChange = Struct.new(:arg, :call_site) do
349
+ def warning
350
+ <<-EOS.gsub(/^\s+\|/, '')
351
+ |The semantics of `describe <a #{arg.class.name}>` are changing in RSpec 3. In RSpec 2,
352
+ |this would be treated as metadata, but as the first `describe` argument,
353
+ |this will be treated as the described object in RSpec 3. If you want this
354
+ |to be treated as metadata, pass a description as the first argument.
355
+ |(Example group defined at #{call_site})
356
+ EOS
357
+ end
358
+ end
359
+
311
360
  class << self
312
361
  alias_method :context, :describe
313
362
  end
@@ -66,23 +66,51 @@ module RSpec
66
66
  # @see Configuration#filter_run_including
67
67
  # @see Configuration#filter_run_excluding
68
68
  class FilterManager
69
- DEFAULT_EXCLUSIONS = {
70
- :if => lambda { |value| !value },
71
- :unless => lambda { |value| value }
72
- }
69
+ class << self
70
+ def const_missing(name)
71
+ case name
72
+ when :DEFAULT_EXCLUSIONS
73
+ RSpec.deprecate("RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS is deprecated")
74
+ default_exclusions
75
+ when :STANDALONE_FILTERS
76
+ RSpec.deprecate("RSpec::Core::FilterManager::STANDALONE_FILTERS is deprecated")
77
+ standalone_filters
78
+ else
79
+ super
80
+ end
81
+ end
82
+
83
+ # @private
84
+ def default_exclusions
85
+ @default_exclusions ||= {
86
+ :if => lambda { |value| !value },
87
+ :unless => lambda { |value| value }
88
+ }
89
+ end
73
90
 
74
- STANDALONE_FILTERS = [:locations, :line_numbers, :full_description]
91
+ # @private
92
+ def standalone_filters
93
+ @standalone_filters ||= [:locations, :line_numbers, :full_description]
94
+ end
95
+ end
75
96
 
76
97
  module Describable
77
98
  PROC_HEX_NUMBER = /0x[0-9a-f]+\s?@/
78
99
  PROJECT_DIR = File.expand_path('.')
79
100
 
80
101
  def description
81
- reject { |k, v| RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS[k] == v }.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','').gsub('__is_lambda__=true','')
102
+ reject { |k, v| RSpec::Core::FilterManager.default_exclusions[k] == v }.inspect.
103
+ gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','').gsub('__is_lambda__=true','')
82
104
  end
83
105
 
84
106
  def empty_without_conditional_filters?
85
- reject { |k, v| RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS[k] == v }.empty?
107
+ RSpec.deprecate("(inclusion_filter | exclusion_filter)#empty_without_conditional_filters? is deprecated")
108
+ rules_empty?
109
+ end
110
+
111
+ # @private
112
+ def rules_empty?
113
+ reject { |k, v| RSpec::Core::FilterManager.default_exclusions[k] == v }.empty?
86
114
  end
87
115
  end
88
116
 
@@ -115,7 +143,7 @@ module RSpec
115
143
  attr_reader :exclusions, :inclusions
116
144
 
117
145
  def initialize
118
- @exclusions = DEFAULT_EXCLUSIONS.dup.extend(Describable)
146
+ @exclusions = self.class.default_exclusions.dup.extend(Describable)
119
147
  @inclusions = {}.extend(Describable)
120
148
  extend(BackwardCompatibility)
121
149
  end
@@ -131,7 +159,7 @@ module RSpec
131
159
  end
132
160
 
133
161
  def empty?
134
- inclusions.empty? && exclusions.empty_without_conditional_filters?
162
+ inclusions.empty? && exclusions.rules_empty?
135
163
  end
136
164
 
137
165
  def prune(examples)
@@ -143,6 +171,11 @@ module RSpec
143
171
  end
144
172
 
145
173
  def exclude!(*args)
174
+ RSpec.deprecate("FilterManager#exclude! is deprecated. Use FilterManager#exclude_only")
175
+ exclude_only(*args)
176
+ end
177
+
178
+ def exclude_only(*args)
146
179
  replace(@exclusions, @inclusions, *args)
147
180
  end
148
181
 
@@ -159,6 +192,11 @@ module RSpec
159
192
  end
160
193
 
161
194
  def include!(*args)
195
+ RSpec.deprecate("FilterManager#include! is deprecated. Use FilterManager#include_only")
196
+ include_only(*args)
197
+ end
198
+
199
+ def include_only(*args)
162
200
  unless_standalone(*args) { replace(@inclusions, @exclusions, *args) }
163
201
  end
164
202
 
@@ -196,7 +234,7 @@ module RSpec
196
234
  end
197
235
 
198
236
  def is_standalone_filter?(filter)
199
- STANDALONE_FILTERS.any? {|key| filter.has_key?(key)}
237
+ self.class.standalone_filters.any? {|key| filter.has_key?(key)}
200
238
  end
201
239
  end
202
240
  end