rspec-core 2.99.0 → 3.0.0

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 (216) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +1 -0
  4. data/Changelog.md +339 -1
  5. data/License.txt +1 -0
  6. data/README.md +19 -37
  7. data/exe/rspec +2 -23
  8. data/lib/rspec/core/backport_random.rb +336 -0
  9. data/lib/rspec/core/backtrace_formatter.rb +70 -0
  10. data/lib/rspec/core/configuration.rb +479 -577
  11. data/lib/rspec/core/configuration_options.rb +71 -54
  12. data/lib/rspec/core/drb.rb +111 -0
  13. data/lib/rspec/core/dsl.rb +86 -18
  14. data/lib/rspec/core/example.rb +267 -119
  15. data/lib/rspec/core/example_group.rb +381 -393
  16. data/lib/rspec/core/filter_manager.rb +133 -114
  17. data/lib/rspec/core/flat_map.rb +18 -0
  18. data/lib/rspec/core/formatters/base_formatter.rb +51 -125
  19. data/lib/rspec/core/formatters/base_text_formatter.rb +34 -286
  20. data/lib/rspec/core/formatters/console_codes.rb +24 -1
  21. data/lib/rspec/core/formatters/deprecation_formatter.rb +25 -26
  22. data/lib/rspec/core/formatters/documentation_formatter.rb +27 -25
  23. data/lib/rspec/core/formatters/helpers.rb +14 -36
  24. data/lib/rspec/core/formatters/html_formatter.rb +58 -65
  25. data/lib/rspec/core/formatters/html_printer.rb +12 -18
  26. data/lib/rspec/core/formatters/json_formatter.rb +54 -31
  27. data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
  28. data/lib/rspec/core/formatters/progress_formatter.rb +11 -15
  29. data/lib/rspec/core/formatters/snippet_extractor.rb +22 -11
  30. data/lib/rspec/core/formatters.rb +90 -43
  31. data/lib/rspec/core/hooks.rb +325 -270
  32. data/lib/rspec/core/memoized_helpers.rb +45 -156
  33. data/lib/rspec/core/metadata.rb +284 -236
  34. data/lib/rspec/core/metadata_filter.rb +86 -0
  35. data/lib/rspec/core/mocking_adapters/flexmock.rb +29 -0
  36. data/lib/rspec/core/{mocking/with_mocha.rb → mocking_adapters/mocha.rb} +19 -16
  37. data/lib/rspec/core/mocking_adapters/null.rb +12 -0
  38. data/lib/rspec/core/mocking_adapters/rr.rb +29 -0
  39. data/lib/rspec/core/mocking_adapters/rspec.rb +30 -0
  40. data/lib/rspec/core/notifications.rb +511 -0
  41. data/lib/rspec/core/option_parser.rb +49 -74
  42. data/lib/rspec/core/ordering.rb +156 -0
  43. data/lib/rspec/core/pending.rb +94 -96
  44. data/lib/rspec/core/project_initializer/.rspec +3 -0
  45. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +78 -0
  46. data/lib/rspec/core/project_initializer.rb +24 -64
  47. data/lib/rspec/core/rake_task.rb +44 -130
  48. data/lib/rspec/core/reporter.rb +76 -59
  49. data/lib/rspec/core/ruby_project.rb +2 -1
  50. data/lib/rspec/core/runner.rb +117 -52
  51. data/lib/rspec/core/shared_context.rb +10 -10
  52. data/lib/rspec/core/shared_example_group.rb +108 -121
  53. data/lib/rspec/core/version.rb +3 -1
  54. data/lib/rspec/core/warnings.rb +40 -0
  55. data/lib/rspec/core/world.rb +66 -10
  56. data/lib/rspec/core.rb +64 -104
  57. data.tar.gz.sig +3 -0
  58. metadata +75 -322
  59. metadata.gz.sig +1 -0
  60. data/exe/autospec +0 -13
  61. data/features/Autotest.md +0 -38
  62. data/features/README.md +0 -17
  63. data/features/Upgrade.md +0 -364
  64. data/features/command_line/README.md +0 -28
  65. data/features/command_line/example_name_option.feature +0 -97
  66. data/features/command_line/exit_status.feature +0 -82
  67. data/features/command_line/format_option.feature +0 -75
  68. data/features/command_line/init.feature +0 -18
  69. data/features/command_line/line_number_appended_to_path.feature +0 -140
  70. data/features/command_line/line_number_option.feature +0 -53
  71. data/features/command_line/order.feature +0 -26
  72. data/features/command_line/pattern_option.feature +0 -49
  73. data/features/command_line/rake_task.feature +0 -122
  74. data/features/command_line/require_option.feature +0 -43
  75. data/features/command_line/ruby.feature +0 -22
  76. data/features/command_line/tag.feature +0 -98
  77. data/features/command_line/warnings_option.feature +0 -29
  78. data/features/configuration/alias_example_to.feature +0 -48
  79. data/features/configuration/backtrace_clean_patterns.feature +0 -102
  80. data/features/configuration/custom_settings.feature +0 -84
  81. data/features/configuration/default_path.feature +0 -38
  82. data/features/configuration/deprecation_stream.feature +0 -58
  83. data/features/configuration/fail_fast.feature +0 -77
  84. data/features/configuration/failure_exit_code.feature +0 -36
  85. data/features/configuration/order_and_seed.feature +0 -3
  86. data/features/configuration/output_stream.feature +0 -24
  87. data/features/configuration/pattern.feature +0 -38
  88. data/features/configuration/profile.feature +0 -220
  89. data/features/configuration/read_options_from_file.feature +0 -90
  90. data/features/configuration/run_all_when_everything_filtered.feature +0 -76
  91. data/features/configuration/show_failures_in_pending_blocks.feature +0 -61
  92. data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +0 -52
  93. data/features/example_groups/basic_structure.feature +0 -55
  94. data/features/example_groups/shared_context.feature +0 -74
  95. data/features/example_groups/shared_examples.feature +0 -294
  96. data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -197
  97. data/features/filtering/exclusion_filters.feature +0 -138
  98. data/features/filtering/if_and_unless.feature +0 -168
  99. data/features/filtering/inclusion_filters.feature +0 -105
  100. data/features/formatters/configurable_colors.feature +0 -31
  101. data/features/formatters/custom_formatter.feature +0 -36
  102. data/features/formatters/json_formatter.feature +0 -30
  103. data/features/formatters/text_formatter.feature +0 -46
  104. data/features/helper_methods/arbitrary_methods.feature +0 -40
  105. data/features/helper_methods/let.feature +0 -50
  106. data/features/helper_methods/modules.feature +0 -149
  107. data/features/hooks/around_hooks.feature +0 -343
  108. data/features/hooks/before_and_after_hooks.feature +0 -427
  109. data/features/hooks/filtering.feature +0 -234
  110. data/features/metadata/current_example.feature +0 -56
  111. data/features/metadata/described_class.feature +0 -17
  112. data/features/metadata/user_defined.feature +0 -113
  113. data/features/mock_framework_integration/use_any_framework.feature +0 -106
  114. data/features/mock_framework_integration/use_flexmock.feature +0 -96
  115. data/features/mock_framework_integration/use_mocha.feature +0 -97
  116. data/features/mock_framework_integration/use_rr.feature +0 -98
  117. data/features/mock_framework_integration/use_rspec.feature +0 -97
  118. data/features/pending/pending_examples.feature +0 -229
  119. data/features/spec_files/arbitrary_file_suffix.feature +0 -13
  120. data/features/step_definitions/additional_cli_steps.rb +0 -49
  121. data/features/subject/attribute_of_subject.feature +0 -124
  122. data/features/subject/explicit_subject.feature +0 -101
  123. data/features/subject/implicit_subject.feature +0 -63
  124. data/features/subject/one_liner_syntax.feature +0 -71
  125. data/features/support/env.rb +0 -14
  126. data/features/support/rubinius.rb +0 -6
  127. data/lib/autotest/discover.rb +0 -10
  128. data/lib/autotest/rspec2.rb +0 -77
  129. data/lib/rspec/core/backtrace_cleaner.rb +0 -46
  130. data/lib/rspec/core/backward_compatibility.rb +0 -55
  131. data/lib/rspec/core/caller_filter.rb +0 -60
  132. data/lib/rspec/core/command_line.rb +0 -47
  133. data/lib/rspec/core/deprecated_mutable_array_proxy.rb +0 -32
  134. data/lib/rspec/core/deprecation.rb +0 -26
  135. data/lib/rspec/core/drb_command_line.rb +0 -26
  136. data/lib/rspec/core/drb_options.rb +0 -87
  137. data/lib/rspec/core/extensions/instance_eval_with_args.rb +0 -44
  138. data/lib/rspec/core/extensions/kernel.rb +0 -9
  139. data/lib/rspec/core/extensions/module_eval_with_args.rb +0 -38
  140. data/lib/rspec/core/extensions/ordered.rb +0 -27
  141. data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -34
  142. data/lib/rspec/core/metadata_hash_builder.rb +0 -97
  143. data/lib/rspec/core/mocking/with_absolutely_nothing.rb +0 -11
  144. data/lib/rspec/core/mocking/with_flexmock.rb +0 -27
  145. data/lib/rspec/core/mocking/with_rr.rb +0 -27
  146. data/lib/rspec/core/mocking/with_rspec.rb +0 -27
  147. data/lib/rspec/core/shared_example_group/collection.rb +0 -45
  148. data/spec/autotest/discover_spec.rb +0 -49
  149. data/spec/autotest/failed_results_re_spec.rb +0 -45
  150. data/spec/autotest/rspec_spec.rb +0 -133
  151. data/spec/command_line/order_spec.rb +0 -204
  152. data/spec/rspec/core/backtrace_cleaner_spec.rb +0 -68
  153. data/spec/rspec/core/caller_filter_spec.rb +0 -58
  154. data/spec/rspec/core/command_line_spec.rb +0 -127
  155. data/spec/rspec/core/command_line_spec_output.txt +0 -0
  156. data/spec/rspec/core/configuration_options_spec.rb +0 -417
  157. data/spec/rspec/core/configuration_spec.rb +0 -2072
  158. data/spec/rspec/core/deprecation_spec.rb +0 -27
  159. data/spec/rspec/core/deprecations_spec.rb +0 -59
  160. data/spec/rspec/core/drb_command_line_spec.rb +0 -102
  161. data/spec/rspec/core/drb_options_spec.rb +0 -193
  162. data/spec/rspec/core/dsl_spec.rb +0 -25
  163. data/spec/rspec/core/example_group_spec.rb +0 -1337
  164. data/spec/rspec/core/example_spec.rb +0 -502
  165. data/spec/rspec/core/filter_manager_spec.rb +0 -246
  166. data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -108
  167. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -524
  168. data/spec/rspec/core/formatters/console_codes_spec.rb +0 -50
  169. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -263
  170. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -89
  171. data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
  172. data/spec/rspec/core/formatters/html_formatted.html +0 -397
  173. data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -131
  174. data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -115
  175. data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -30
  176. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
  177. data/spec/rspec/core/formatters/text_mate_formatted.html +0 -397
  178. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +0 -107
  179. data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
  180. data/spec/rspec/core/hooks_spec.rb +0 -269
  181. data/spec/rspec/core/kernel_extensions_spec.rb +0 -9
  182. data/spec/rspec/core/memoized_helpers_spec.rb +0 -776
  183. data/spec/rspec/core/metadata_spec.rb +0 -514
  184. data/spec/rspec/core/option_parser_spec.rb +0 -297
  185. data/spec/rspec/core/pending_example_spec.rb +0 -260
  186. data/spec/rspec/core/pending_spec.rb +0 -27
  187. data/spec/rspec/core/project_initializer_spec.rb +0 -130
  188. data/spec/rspec/core/rake_task_spec.rb +0 -202
  189. data/spec/rspec/core/reporter_spec.rb +0 -167
  190. data/spec/rspec/core/resources/a_bar.rb +0 -0
  191. data/spec/rspec/core/resources/a_foo.rb +0 -0
  192. data/spec/rspec/core/resources/a_spec.rb +0 -1
  193. data/spec/rspec/core/resources/custom_example_group_runner.rb +0 -14
  194. data/spec/rspec/core/resources/formatter_specs.rb +0 -60
  195. data/spec/rspec/core/resources/utf8_encoded.rb +0 -8
  196. data/spec/rspec/core/rspec_matchers_spec.rb +0 -45
  197. data/spec/rspec/core/ruby_project_spec.rb +0 -26
  198. data/spec/rspec/core/runner_spec.rb +0 -82
  199. data/spec/rspec/core/shared_context_spec.rb +0 -114
  200. data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -70
  201. data/spec/rspec/core/shared_example_group_spec.rb +0 -138
  202. data/spec/rspec/core/world_spec.rb +0 -142
  203. data/spec/rspec/core_spec.rb +0 -108
  204. data/spec/spec_helper.rb +0 -135
  205. data/spec/support/config_options_helper.rb +0 -15
  206. data/spec/support/helper_methods.rb +0 -55
  207. data/spec/support/in_sub_process.rb +0 -37
  208. data/spec/support/isolate_load_path_mutation.rb +0 -6
  209. data/spec/support/isolated_directory.rb +0 -10
  210. data/spec/support/isolated_home_directory.rb +0 -16
  211. data/spec/support/matchers.rb +0 -65
  212. data/spec/support/mathn_integration_support.rb +0 -12
  213. data/spec/support/sandboxed_mock_space.rb +0 -116
  214. data/spec/support/shared_example_groups.rb +0 -42
  215. data/spec/support/silence_dsl_deprecations.rb +0 -32
  216. data/spec/support/spec_files.rb +0 -44
@@ -1,5 +1,6 @@
1
1
  module RSpec
2
2
  module Core
3
+ # @private
3
4
  # Manages the filtering of examples and groups by matching tags declared on
4
5
  # the command line or options files, or filters declared via
5
6
  # `RSpec.configure`, with hash key/values submitted within example group
@@ -66,175 +67,193 @@ module RSpec
66
67
  # @see Configuration#filter_run_including
67
68
  # @see Configuration#filter_run_excluding
68
69
  class FilterManager
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
70
+ attr_reader :exclusions, :inclusions
82
71
 
83
- # @private
84
- def default_exclusions
85
- @default_exclusions ||= {
86
- :if => lambda { |value| !value },
87
- :unless => lambda { |value| value }
88
- }
89
- end
72
+ def initialize
73
+ @exclusions, @inclusions = FilterRules.build
74
+ end
90
75
 
91
- # @private
92
- def standalone_filters
93
- @standalone_filters ||= [:locations, :line_numbers, :full_description]
94
- end
76
+ # @api private
77
+ #
78
+ # @param file_path [String]
79
+ # @param line_numbers [Array]
80
+ def add_location(file_path, line_numbers)
81
+ # locations is a hash of expanded paths to arrays of line
82
+ # numbers to match against. e.g.
83
+ # { "path/to/file.rb" => [37, 42] }
84
+ locations = inclusions.delete(:locations) || Hash.new { |h,k| h[k] = [] }
85
+ locations[File.expand_path(file_path)].push(*line_numbers)
86
+ inclusions.add_location(locations)
95
87
  end
96
88
 
97
- module Describable
98
- PROC_HEX_NUMBER = /0x[0-9a-f]+\s?@/
99
- PROJECT_DIR = File.expand_path('.')
89
+ def empty?
90
+ inclusions.empty? && exclusions.empty?
91
+ end
100
92
 
101
- def description
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','')
93
+ def prune(examples)
94
+ if inclusions.standalone?
95
+ base_exclusions = ExclusionRules.new
96
+ examples.select {|e| !base_exclusions.include_example?(e) && include?(e) }
97
+ else
98
+ examples.select {|e| !exclude?(e) && include?(e)}
104
99
  end
100
+ end
105
101
 
106
- def empty_without_conditional_filters?
107
- RSpec.deprecate("(inclusion_filter | exclusion_filter)#empty_without_conditional_filters? is deprecated")
108
- rules_empty?
109
- end
102
+ def exclude(*args)
103
+ exclusions.add(args.last)
104
+ end
110
105
 
111
- # @private
112
- def rules_empty?
113
- reject { |k, v| RSpec::Core::FilterManager.default_exclusions[k] == v }.empty?
114
- end
106
+ def exclude_only(*args)
107
+ exclusions.use_only(args.last)
115
108
  end
116
109
 
117
- module BackwardCompatibility
118
- def merge(orig, opposite, *updates)
119
- _warn_deprecated_keys(updates.last)
120
- super
121
- end
110
+ def exclude_with_low_priority(*args)
111
+ exclusions.add_with_low_priority(args.last)
112
+ end
122
113
 
123
- def reverse_merge(orig, opposite, *updates)
124
- _warn_deprecated_keys(updates.last)
125
- super
126
- end
114
+ def exclude?(example)
115
+ exclusions.include_example?(example)
116
+ end
127
117
 
128
- # Supports a use case that probably doesn't exist: overriding the
129
- # if/unless procs.
130
- def _warn_deprecated_keys(updates)
131
- _warn_deprecated_key(:unless, updates) if updates.has_key?(:unless)
132
- _warn_deprecated_key(:if, updates) if updates.has_key?(:if)
133
- end
118
+ def include(*args)
119
+ inclusions.add(args.last)
120
+ end
134
121
 
135
- # Emits a deprecation warning for keys that will not be supported in
136
- # the future.
137
- def _warn_deprecated_key(key, updates)
138
- RSpec.deprecate("FilterManager#exclude(#{key.inspect} => #{updates[key].inspect})")
139
- @exclusions[key] = updates.delete(key)
140
- end
122
+ def include_only(*args)
123
+ inclusions.use_only(args.last)
141
124
  end
142
125
 
143
- attr_reader :exclusions, :inclusions
126
+ def include_with_low_priority(*args)
127
+ inclusions.add_with_low_priority(args.last)
128
+ end
144
129
 
145
- def initialize
146
- @exclusions = self.class.default_exclusions.dup.extend(Describable)
147
- @inclusions = {}.extend(Describable)
148
- extend(BackwardCompatibility)
130
+ def include?(example)
131
+ inclusions.include_example?(example)
149
132
  end
133
+ end
150
134
 
151
- def add_location(file_path, line_numbers)
152
- # locations is a hash of expanded paths to arrays of line
153
- # numbers to match against. e.g.
154
- # { "path/to/file.rb" => [37, 42] }
155
- locations = @inclusions.delete(:locations) || Hash.new {|h,k| h[k] = []}
156
- locations[File.expand_path(file_path)].push(*line_numbers)
157
- @inclusions.replace(:locations => locations)
158
- @exclusions.clear
135
+ # @private
136
+ class FilterRules
137
+ PROC_HEX_NUMBER = /0x[0-9a-f]+@/
138
+ PROJECT_DIR = File.expand_path('.')
139
+
140
+ attr_accessor :opposite
141
+ attr_reader :rules
142
+
143
+ def self.build
144
+ exclusions = ExclusionRules.new
145
+ inclusions = InclusionRules.new
146
+ exclusions.opposite = inclusions
147
+ inclusions.opposite = exclusions
148
+ [exclusions, inclusions]
159
149
  end
160
150
 
161
- def empty?
162
- inclusions.empty? && exclusions.rules_empty?
151
+ def initialize(*args, &block)
152
+ @rules = Hash.new(*args, &block)
163
153
  end
164
154
 
165
- def prune(examples)
166
- examples.select {|e| !exclude?(e) && include?(e)}
155
+ def add(updated)
156
+ @rules.merge!(updated).each_key { |k| opposite.delete(k) }
167
157
  end
168
158
 
169
- def exclude(*args)
170
- merge(@exclusions, @inclusions, *args)
159
+ def add_with_low_priority(_updated)
160
+ updated = _updated.merge(@rules)
161
+ opposite.each_pair { |k,v| updated.delete(k) if updated[k] == v }
162
+ @rules.replace(updated)
171
163
  end
172
164
 
173
- def exclude!(*args)
174
- RSpec.deprecate("FilterManager#exclude! is deprecated. Use FilterManager#exclude_only")
175
- exclude_only(*args)
165
+ def use_only(updated)
166
+ updated.each_key { |k| opposite.delete(k) }
167
+ @rules.replace(updated)
176
168
  end
177
169
 
178
- def exclude_only(*args)
179
- replace(@exclusions, @inclusions, *args)
170
+ def clear
171
+ @rules.clear
180
172
  end
181
173
 
182
- def exclude_with_low_priority(*args)
183
- reverse_merge(@exclusions, @inclusions, *args)
174
+ def delete(key)
175
+ @rules.delete(key)
184
176
  end
185
177
 
186
- def exclude?(example)
187
- @exclusions.empty? ? false : example.any_apply?(@exclusions)
178
+ def fetch(*args, &block)
179
+ @rules.fetch(*args, &block)
188
180
  end
189
181
 
190
- def include(*args)
191
- unless_standalone(*args) { merge(@inclusions, @exclusions, *args) }
182
+ def [](key)
183
+ @rules[key]
192
184
  end
193
185
 
194
- def include!(*args)
195
- RSpec.deprecate("FilterManager#include! is deprecated. Use FilterManager#include_only")
196
- include_only(*args)
186
+ def empty?
187
+ rules.empty?
197
188
  end
198
189
 
199
- def include_only(*args)
200
- unless_standalone(*args) { replace(@inclusions, @exclusions, *args) }
190
+ def each_pair(&block)
191
+ @rules.each_pair(&block)
201
192
  end
202
193
 
203
- def include_with_low_priority(*args)
204
- unless_standalone(*args) { reverse_merge(@inclusions, @exclusions, *args) }
194
+ def description
195
+ rules.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','')
196
+ end
197
+ end
198
+
199
+ # @private
200
+ class InclusionRules < FilterRules
201
+ STANDALONE_FILTERS = [:locations, :full_description]
202
+
203
+ def add_location(locations)
204
+ replace_filters({ :locations => locations })
205
205
  end
206
206
 
207
- def include?(example)
208
- @inclusions.empty? ? true : example.any_apply?(@inclusions)
207
+ def add(*args)
208
+ set_standalone_filter(*args) || super
209
209
  end
210
210
 
211
- private
211
+ def add_with_low_priority(*args)
212
+ set_standalone_filter(*args) || super
213
+ end
214
+
215
+ def use(*args)
216
+ set_standalone_filter(*args) || super
217
+ end
212
218
 
213
- def unless_standalone(*args)
214
- is_standalone_filter?(args.last) ? @inclusions.replace(args.last) : yield unless already_set_standalone_filter?
219
+ def include_example?(example)
220
+ @rules.empty? ? true : example.any_apply?(@rules)
215
221
  end
216
222
 
217
- def merge(orig, opposite, *updates)
218
- orig.merge!(updates.last).each_key {|k| opposite.delete(k)}
223
+ def standalone?
224
+ is_standalone_filter?(@rules)
219
225
  end
220
226
 
221
- def replace(orig, opposite, *updates)
222
- updates.last.each_key {|k| opposite.delete(k)}
223
- orig.replace(updates.last)
227
+ private
228
+
229
+ def set_standalone_filter(updated)
230
+ return true if standalone?
231
+
232
+ if is_standalone_filter?(updated)
233
+ replace_filters(updated)
234
+ true
235
+ end
224
236
  end
225
237
 
226
- def reverse_merge(orig, opposite, *updates)
227
- updated = updates.last.merge(orig)
228
- opposite.each_pair {|k,v| updated.delete(k) if updated[k] == v}
229
- orig.replace(updated)
238
+ def replace_filters(new_rules)
239
+ @rules.replace(new_rules)
240
+ opposite.clear
230
241
  end
231
242
 
232
- def already_set_standalone_filter?
233
- is_standalone_filter?(inclusions)
243
+ def is_standalone_filter?(rules)
244
+ STANDALONE_FILTERS.any? { |key| rules.has_key?(key) }
234
245
  end
246
+ end
247
+
248
+ # @private
249
+ class ExclusionRules < FilterRules
250
+ CONDITIONAL_FILTERS = {
251
+ :if => lambda { |value| !value },
252
+ :unless => lambda { |value| value }
253
+ }.freeze
235
254
 
236
- def is_standalone_filter?(filter)
237
- self.class.standalone_filters.any? {|key| filter.has_key?(key)}
255
+ def include_example?(example)
256
+ example.any_apply?(@rules) || example.any_apply?(CONDITIONAL_FILTERS)
238
257
  end
239
258
  end
240
259
  end
@@ -0,0 +1,18 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ module FlatMap
5
+ if [].respond_to?(:flat_map)
6
+ def flat_map(array)
7
+ array.flat_map { |item| yield item }
8
+ end
9
+ else # for 1.8.7
10
+ def flat_map(array)
11
+ array.map { |item| yield item }.flatten
12
+ end
13
+ end
14
+
15
+ module_function :flat_map
16
+ end
17
+ end
18
+ end
@@ -1,31 +1,28 @@
1
- require 'rspec/core/formatters/helpers'
1
+ RSpec::Support.require_rspec_core "formatters/helpers"
2
2
  require 'stringio'
3
3
 
4
4
  module RSpec
5
5
  module Core
6
6
  module Formatters
7
7
  # RSpec's built-in formatters are all subclasses of RSpec::Core::Formatters::BaseTextFormatter,
8
- # but the BaseTextFormatter documents all of the methods needed to be implemented by a formatter,
9
- # as they are called from the reporter.
8
+ # but the BaseTextFormatter documents all of the notifications implemented as part of the standard
9
+ # interface. The reporter will issue these during a normal test suite run, but a formatter will
10
+ # only receive those notifications it has registered itself to receive.
10
11
  #
11
12
  # @see RSpec::Core::Formatters::BaseTextFormatter
12
13
  # @see RSpec::Core::Reporter
13
14
  class BaseFormatter
14
- include Helpers
15
+
16
+ # all formatters inheriting from this formatter will receive these notifications
17
+ Formatters.register self, :start, :example_group_started, :close
15
18
  attr_accessor :example_group
16
- attr_reader :duration, :examples, :output
17
- attr_reader :example_count, :pending_count, :failure_count
18
- attr_reader :failed_examples, :pending_examples
19
+ attr_reader :output
19
20
 
20
21
  # @api public
21
22
  #
22
- # @param output
23
+ # @param output [IO] the formatter output
23
24
  def initialize(output)
24
25
  @output = output || StringIO.new
25
- @example_count = @pending_count = @failure_count = 0
26
- @examples = []
27
- @failed_examples = []
28
- @pending_examples = []
29
26
  @example_group = nil
30
27
  end
31
28
 
@@ -38,179 +35,124 @@ module RSpec
38
35
  # This will only be invoked once, and the next one to be invoked
39
36
  # is {#example_group_started}.
40
37
  #
41
- # @param example_count
42
- def start(example_count)
38
+ # @param notification [StartNotification]
39
+ def start(notification)
43
40
  start_sync_output
44
- @example_count = example_count
41
+ @example_count = notification.count
45
42
  end
46
43
 
47
44
  # @api public
48
45
  #
49
46
  # This method is invoked at the beginning of the execution of each example group.
50
47
  #
51
- # @param example_group subclass of `RSpec::Core::ExampleGroup`
52
- #
53
48
  # The next method to be invoked after this is {#example_passed},
54
49
  # {#example_pending}, or {#example_group_finished}.
55
50
  #
56
- # @param example_group
57
- def example_group_started(example_group)
58
- @example_group = example_group
51
+ # @param notification [GroupNotification] containing example_group subclass of `RSpec::Core::ExampleGroup`
52
+ def example_group_started(notification)
53
+ @example_group = notification.group
59
54
  end
60
55
 
56
+ # @method example_group_finished
61
57
  # @api public
62
58
  #
63
59
  # Invoked at the end of the execution of each example group.
64
60
  #
65
- # @param example_group subclass of `RSpec::Core::ExampleGroup`
66
- def example_group_finished(example_group)
67
- end
61
+ # @param notification [GroupNotification] containing example_group subclass of `RSpec::Core::ExampleGroup`
68
62
 
63
+ # @method example_started
69
64
  # @api public
70
65
  #
71
66
  # Invoked at the beginning of the execution of each example.
72
67
  #
73
- # @param example instance of subclass of `RSpec::Core::ExampleGroup`
74
- # @return [Array]
75
- def example_started(example)
76
- examples << example
77
- end
68
+ # @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
78
69
 
70
+ # @method example_passed
79
71
  # @api public
80
72
  #
81
73
  # Invoked when an example passes.
82
74
  #
83
- # @param example instance of subclass of `RSpec::Core::ExampleGroup`
84
- def example_passed(example)
85
- end
75
+ # @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
86
76
 
77
+ # @method example_pending
87
78
  # Invoked when an example is pending.
88
79
  #
89
- # @param example instance of subclass of `RSpec::Core::ExampleGroup`
90
- # @return [Array]
91
- def example_pending(example)
92
- @pending_examples << example
93
- end
80
+ # @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
94
81
 
82
+ # @method example_failed
95
83
  # @api public
96
84
  #
97
85
  # Invoked when an example fails.
98
86
  #
99
- # @param example instance of subclass of `RSpec::Core::ExampleGroup`
100
- # @return [Array]
101
- def example_failed(example)
102
- @failed_examples << example
103
- end
87
+ # @param notification [ExampleNotification] containing example subclass of `RSpec::Core::Example`
104
88
 
89
+ # @method message
105
90
  # @api public
106
91
  #
107
92
  # Used by the reporter to send messages to the output stream.
108
93
  #
109
- # @param [String] message
110
- def message(message)
111
- end
94
+ # @param notification [MessageNotification] containing message
112
95
 
96
+ # @method stop
113
97
  # @api public
114
98
  #
115
99
  # Invoked after all examples have executed, before dumping post-run reports.
116
100
  #
117
- # @return [nil]
118
- def stop
119
- end
101
+ # @param notification [NullNotification]
120
102
 
103
+ # @method start_dump
121
104
  # @api public
122
105
  #
123
106
  # This method is invoked after all of the examples have executed. The next method
124
107
  # to be invoked after this one is {#dump_failures}
125
108
  # (BaseTextFormatter then calls {#dump_failure} once for each failed example.)
126
109
  #
127
- # @return [nil]
128
- def start_dump
129
- end
110
+ # @param notification [NullNotification]
130
111
 
112
+ # @method dump_failures
131
113
  # @api public
132
114
  #
133
115
  # Dumps detailed information about each example failure.
134
116
  #
135
- # @return [nil]
136
- def dump_failures
137
- end
117
+ # @param notification [NullNotification]
138
118
 
119
+ # @method dump_summary
139
120
  # @api public
140
121
  #
141
122
  # This method is invoked after the dumping of examples and failures. Each parameter
142
123
  # is assigned to a corresponding attribute.
143
124
  #
144
- # @param duration
145
- # @param example_count
146
- # @param failure_count
147
- # @param pending_count
148
- def dump_summary(duration, example_count, failure_count, pending_count)
149
- @duration = duration
150
- @example_count = example_count
151
- @failure_count = failure_count
152
- @pending_count = pending_count
153
- end
125
+ # @param summary [SummaryNotification] containing duration, example_count,
126
+ # failure_count and pending_count
154
127
 
128
+ # @method dump_profile
129
+ # @api public
130
+ #
131
+ # This method is invoked after the dumping the summary if profiling is
132
+ # enabled.
133
+ #
134
+ # @param profile [ProfileNotification] containing duration, slowest_examples
135
+ # and slowest_example_groups
136
+
137
+ # @method dump_pending
155
138
  # @api public
156
139
  #
157
140
  # Outputs a report of pending examples. This gets invoked
158
141
  # after the summary if option is set to do so.
159
142
  #
160
- # @return [nil]
161
- def dump_pending
162
- end
163
-
164
- # @private not intended for use outside RSpec.
165
- def seed(number)
166
- end
143
+ # @param notification [NullNotification]
167
144
 
168
145
  # @api public
169
146
  #
170
147
  # Invoked at the very end, `close` allows the formatter to clean
171
148
  # up resources, e.g. open streams, etc.
172
- def close
173
- restore_sync_output
174
- end
175
-
176
- # @api public
177
149
  #
178
- # Formats the given backtrace based on configuration and
179
- # the metadata of the given example.
180
- def format_backtrace(backtrace, example)
181
- super(backtrace, example.metadata)
182
- end
183
-
184
- protected
185
-
186
- def configuration
187
- RSpec.configuration
188
- end
189
-
190
- def read_failed_line(exception, example)
191
- unless matching_line = find_failed_line(exception.backtrace, example.file_path)
192
- return "Unable to find matching line from backtrace"
193
- end
194
-
195
- file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
196
-
197
- if File.exist?(file_path)
198
- File.readlines(file_path)[line_number.to_i - 1] ||
199
- "Unable to find matching line in #{file_path}"
200
- else
201
- "Unable to find #{file_path} to read failed line"
202
- end
203
- rescue SecurityError
204
- "Unable to read failed line"
150
+ # @param notification [NullNotification]
151
+ def close(notification)
152
+ restore_sync_output
205
153
  end
206
154
 
207
- def find_failed_line(backtrace, path)
208
- path = File.expand_path(path)
209
- backtrace.detect { |line|
210
- match = line.match(/(.+?):(\d+)(|:\d+)/)
211
- match && match[1].downcase == path.downcase
212
- }
213
- end
155
+ private
214
156
 
215
157
  def start_sync_output
216
158
  @old_sync, output.sync = output.sync, true if output_supports_sync
@@ -224,22 +166,6 @@ module RSpec
224
166
  output.respond_to?(:sync=)
225
167
  end
226
168
 
227
- def profile_examples?
228
- configuration.profile_examples
229
- end
230
-
231
- def fail_fast?
232
- configuration.fail_fast
233
- end
234
-
235
- def color_enabled?
236
- configuration.color_enabled?(output)
237
- end
238
-
239
- def mute_profile_output?(failure_count)
240
- # Don't print out profiled info if there are failures and `--fail-fast` is used, it just clutters the output
241
- !profile_examples? || (fail_fast? && failure_count != 0)
242
- end
243
169
  end
244
170
  end
245
171
  end