rspec-core 2.99.0.beta2 → 2.99.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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