rspec-core 2.99.2 → 3.0.0.beta1

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 (165) hide show
  1. checksums.yaml +14 -6
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +0 -0
  4. data/Changelog.md +103 -191
  5. data/License.txt +1 -0
  6. data/README.md +4 -25
  7. data/features/Upgrade.md +2 -14
  8. data/features/command_line/dry_run.feature +29 -0
  9. data/features/command_line/example_name_option.feature +1 -1
  10. data/features/command_line/fail_fast.feature +26 -0
  11. data/features/command_line/format_option.feature +3 -3
  12. data/features/command_line/line_number_option.feature +16 -11
  13. data/features/command_line/order.feature +2 -3
  14. data/features/command_line/pattern_option.feature +3 -3
  15. data/features/command_line/randomization.feature +63 -0
  16. data/features/command_line/require_option.feature +2 -2
  17. data/features/command_line/ruby.feature +1 -1
  18. data/features/configuration/alias_example_to.feature +13 -22
  19. data/features/configuration/{backtrace_clean_patterns.feature → backtrace_exclusion_patterns.feature} +17 -14
  20. data/features/configuration/custom_settings.feature +11 -11
  21. data/features/configuration/overriding_global_ordering.feature +93 -0
  22. data/features/configuration/profile.feature +13 -13
  23. data/features/configuration/read_options_from_file.feature +7 -7
  24. data/features/example_groups/basic_structure.feature +1 -1
  25. data/features/example_groups/shared_context.feature +8 -8
  26. data/features/example_groups/shared_examples.feature +6 -14
  27. data/features/expectation_framework_integration/configure_expectation_framework.feature +27 -122
  28. data/features/filtering/exclusion_filters.feature +2 -5
  29. data/features/filtering/inclusion_filters.feature +1 -5
  30. data/features/formatters/json_formatter.feature +2 -2
  31. data/features/formatters/text_formatter.feature +4 -4
  32. data/features/helper_methods/arbitrary_methods.feature +2 -2
  33. data/features/helper_methods/let.feature +5 -5
  34. data/features/helper_methods/modules.feature +5 -8
  35. data/features/hooks/around_hooks.feature +2 -2
  36. data/features/hooks/before_and_after_hooks.feature +14 -14
  37. data/features/hooks/filtering.feature +12 -14
  38. data/features/metadata/described_class.feature +1 -1
  39. data/features/metadata/user_defined.feature +16 -29
  40. data/features/mock_framework_integration/use_flexmock.feature +1 -1
  41. data/features/mock_framework_integration/use_mocha.feature +1 -1
  42. data/features/mock_framework_integration/use_rr.feature +1 -1
  43. data/features/mock_framework_integration/use_rspec.feature +5 -5
  44. data/features/pending/pending_examples.feature +5 -5
  45. data/features/spec_files/arbitrary_file_suffix.feature +1 -1
  46. data/features/step_definitions/additional_cli_steps.rb +3 -3
  47. data/features/subject/explicit_subject.feature +8 -8
  48. data/features/subject/implicit_receiver.feature +29 -0
  49. data/features/subject/implicit_subject.feature +4 -4
  50. data/features/support/env.rb +10 -3
  51. data/features/support/require_expect_syntax_in_aruba_specs.rb +16 -0
  52. data/lib/rspec/core.rb +11 -48
  53. data/lib/rspec/core/backport_random.rb +302 -0
  54. data/lib/rspec/core/backtrace_formatter.rb +65 -0
  55. data/lib/rspec/core/command_line.rb +7 -18
  56. data/lib/rspec/core/configuration.rb +202 -507
  57. data/lib/rspec/core/configuration_options.rb +17 -30
  58. data/lib/rspec/core/example.rb +29 -39
  59. data/lib/rspec/core/example_group.rb +166 -259
  60. data/lib/rspec/core/filter_manager.rb +30 -47
  61. data/lib/rspec/core/flat_map.rb +17 -0
  62. data/lib/rspec/core/formatters.rb +0 -138
  63. data/lib/rspec/core/formatters/base_formatter.rb +46 -1
  64. data/lib/rspec/core/formatters/base_text_formatter.rb +38 -61
  65. data/lib/rspec/core/formatters/deprecation_formatter.rb +21 -52
  66. data/lib/rspec/core/formatters/helpers.rb +0 -28
  67. data/lib/rspec/core/formatters/html_formatter.rb +1 -1
  68. data/lib/rspec/core/formatters/json_formatter.rb +38 -9
  69. data/lib/rspec/core/formatters/snippet_extractor.rb +14 -5
  70. data/lib/rspec/core/hooks.rb +55 -39
  71. data/lib/rspec/core/memoized_helpers.rb +17 -167
  72. data/lib/rspec/core/metadata.rb +16 -64
  73. data/lib/rspec/core/option_parser.rb +30 -39
  74. data/lib/rspec/core/ordering.rb +154 -0
  75. data/lib/rspec/core/pending.rb +12 -69
  76. data/lib/rspec/core/project_initializer.rb +12 -10
  77. data/lib/rspec/core/rake_task.rb +5 -108
  78. data/lib/rspec/core/reporter.rb +15 -18
  79. data/lib/rspec/core/runner.rb +16 -30
  80. data/lib/rspec/core/shared_context.rb +3 -5
  81. data/lib/rspec/core/shared_example_group.rb +3 -51
  82. data/lib/rspec/core/shared_example_group/collection.rb +1 -19
  83. data/lib/rspec/core/version.rb +1 -1
  84. data/lib/rspec/core/warnings.rb +22 -0
  85. data/lib/rspec/core/world.rb +12 -8
  86. data/spec/command_line/order_spec.rb +20 -23
  87. data/spec/rspec/core/backtrace_formatter_spec.rb +216 -0
  88. data/spec/rspec/core/command_line_spec.rb +32 -48
  89. data/spec/rspec/core/configuration_options_spec.rb +19 -50
  90. data/spec/rspec/core/configuration_spec.rb +142 -713
  91. data/spec/rspec/core/drb_command_line_spec.rb +2 -0
  92. data/spec/rspec/core/dsl_spec.rb +0 -1
  93. data/spec/rspec/core/example_group_spec.rb +192 -223
  94. data/spec/rspec/core/example_spec.rb +40 -16
  95. data/spec/rspec/core/filter_manager_spec.rb +2 -2
  96. data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -41
  97. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +5 -123
  98. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +2 -87
  99. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +2 -3
  100. data/spec/rspec/core/formatters/{text_mate_formatted.html → html_formatted-1.8.7-jruby.html} +44 -25
  101. data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +477 -0
  102. data/spec/rspec/core/formatters/{html_formatted.html → html_formatted-1.8.7.html} +42 -25
  103. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +425 -0
  104. data/spec/rspec/core/formatters/html_formatted-1.9.3-jruby.html +416 -0
  105. data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +477 -0
  106. data/spec/rspec/core/formatters/html_formatted-1.9.3.html +419 -0
  107. data/spec/rspec/core/formatters/html_formatted-2.0.0.html +425 -0
  108. data/spec/rspec/core/formatters/html_formatter_spec.rb +21 -46
  109. data/spec/rspec/core/formatters/json_formatter_spec.rb +97 -8
  110. data/spec/rspec/core/hooks_filtering_spec.rb +5 -5
  111. data/spec/rspec/core/hooks_spec.rb +61 -47
  112. data/spec/rspec/core/memoized_helpers_spec.rb +20 -322
  113. data/spec/rspec/core/metadata_spec.rb +1 -24
  114. data/spec/rspec/core/option_parser_spec.rb +20 -62
  115. data/spec/rspec/core/ordering_spec.rb +102 -0
  116. data/spec/rspec/core/pending_example_spec.rb +0 -40
  117. data/spec/rspec/core/project_initializer_spec.rb +1 -25
  118. data/spec/rspec/core/rake_task_spec.rb +5 -72
  119. data/spec/rspec/core/random_spec.rb +47 -0
  120. data/spec/rspec/core/reporter_spec.rb +23 -48
  121. data/spec/rspec/core/runner_spec.rb +31 -39
  122. data/spec/rspec/core/shared_context_spec.rb +3 -15
  123. data/spec/rspec/core/shared_example_group/collection_spec.rb +4 -17
  124. data/spec/rspec/core/shared_example_group_spec.rb +12 -45
  125. data/spec/rspec/core/{deprecation_spec.rb → warnings_spec.rb} +3 -1
  126. data/spec/rspec/core_spec.rb +4 -21
  127. data/spec/spec_helper.rb +41 -5
  128. data/spec/support/helper_methods.rb +0 -29
  129. data/spec/support/sandboxed_mock_space.rb +0 -16
  130. data/spec/support/shared_example_groups.rb +7 -36
  131. data/spec/support/stderr_splitter.rb +36 -0
  132. metadata +163 -157
  133. metadata.gz.sig +1 -0
  134. data/exe/autospec +0 -13
  135. data/features/Autotest.md +0 -38
  136. data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +0 -52
  137. data/features/subject/attribute_of_subject.feature +0 -124
  138. data/features/subject/one_liner_syntax.feature +0 -71
  139. data/lib/autotest/discover.rb +0 -10
  140. data/lib/autotest/rspec2.rb +0 -77
  141. data/lib/rspec/core/backtrace_cleaner.rb +0 -46
  142. data/lib/rspec/core/backward_compatibility.rb +0 -55
  143. data/lib/rspec/core/caller_filter.rb +0 -60
  144. data/lib/rspec/core/deprecated_mutable_array_proxy.rb +0 -32
  145. data/lib/rspec/core/deprecation.rb +0 -26
  146. data/lib/rspec/core/extensions/instance_eval_with_args.rb +0 -44
  147. data/lib/rspec/core/extensions/kernel.rb +0 -9
  148. data/lib/rspec/core/extensions/module_eval_with_args.rb +0 -38
  149. data/lib/rspec/core/extensions/ordered.rb +0 -27
  150. data/lib/rspec/core/formatters/console_codes.rb +0 -42
  151. data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -34
  152. data/lib/rspec/core/metadata_hash_builder.rb +0 -97
  153. data/lib/rspec/core/minitest_assertions_adapter.rb +0 -28
  154. data/lib/rspec/core/test_unit_assertions_adapter.rb +0 -30
  155. data/spec/autotest/discover_spec.rb +0 -49
  156. data/spec/autotest/failed_results_re_spec.rb +0 -45
  157. data/spec/autotest/rspec_spec.rb +0 -133
  158. data/spec/rspec/core/backtrace_cleaner_spec.rb +0 -68
  159. data/spec/rspec/core/caller_filter_spec.rb +0 -58
  160. data/spec/rspec/core/deprecations_spec.rb +0 -59
  161. data/spec/rspec/core/formatters/console_codes_spec.rb +0 -50
  162. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +0 -107
  163. data/spec/rspec/core/kernel_extensions_spec.rb +0 -9
  164. data/spec/rspec/core/pending_spec.rb +0 -27
  165. data/spec/support/silence_dsl_deprecations.rb +0 -32
@@ -16,9 +16,7 @@ module RSpec
16
16
 
17
17
  def printer
18
18
  @printer ||= case deprecation_stream
19
- when File
20
- ImmediatePrinter.new(FileStream.new(deprecation_stream), summary_stream, self)
21
- when RaiseErrorStream
19
+ when File, RaiseErrorStream
22
20
  ImmediatePrinter.new(deprecation_stream, summary_stream, self)
23
21
  else
24
22
  DelayedPrinter.new(deprecation_stream, summary_stream, self)
@@ -37,10 +35,6 @@ module RSpec
37
35
  printer.deprecation_summary
38
36
  end
39
37
 
40
- def start(example_count=nil)
41
- #no-op to fix #966
42
- end
43
-
44
38
  def deprecation_message_for(data)
45
39
  if data[:message]
46
40
  SpecifiedDeprecationMessage.new(data)
@@ -57,9 +51,6 @@ module RSpec
57
51
  |deprecation warnings into errors, giving you the full backtrace.
58
52
  EOS
59
53
 
60
- DEPRECATION_STREAM_NOTICE = "Pass `--deprecation-out` or set " +
61
- "`config.deprecation_stream` to a file for full output."
62
-
63
54
  SpecifiedDeprecationMessage = Struct.new(:type) do
64
55
  def initialize(data)
65
56
  @message = data[:message]
@@ -67,23 +58,17 @@ module RSpec
67
58
  end
68
59
 
69
60
  def to_s
70
- output_formatted @message
61
+ @message
71
62
  end
72
63
 
73
64
  def too_many_warnings_message
74
- msg = "Too many similar deprecation messages reported, disregarding further reports. "
75
- msg << DEPRECATION_STREAM_NOTICE
65
+ msg = "Too many similar deprecation messages reported, disregarding further reports."
66
+ msg << " Set config.deprecation_stream to a File for full output."
76
67
  msg
77
68
  end
78
69
 
79
70
  private
80
71
 
81
- def output_formatted(str)
82
- return str unless str.lines.count > 1
83
- separator = "#{'-' * 80}"
84
- "#{separator}\n#{str.chomp}\n#{separator}"
85
- end
86
-
87
72
  def deprecation_type_for(data)
88
73
  data[:message].gsub(/(\w+\/)+\w+\.rb:\d+/, '')
89
74
  end
@@ -92,7 +77,7 @@ module RSpec
92
77
  GeneratedDeprecationMessage = Struct.new(:type) do
93
78
  def initialize(data)
94
79
  @data = data
95
- super data.fetch(:type, data[:deprecated])
80
+ super data[:deprecated]
96
81
  end
97
82
 
98
83
  def to_s
@@ -103,18 +88,26 @@ module RSpec
103
88
  end
104
89
 
105
90
  def too_many_warnings_message
106
- msg = "Too many uses of deprecated '#{type}'. "
107
- msg << DEPRECATION_STREAM_NOTICE
91
+ msg = "Too many uses of deprecated '#{type}'."
92
+ msg << " Set config.deprecation_stream to a File for full output."
108
93
  msg
109
94
  end
110
95
  end
111
96
 
112
97
  class ImmediatePrinter
98
+ include ::RSpec::Core::Formatters::Helpers
99
+
113
100
  attr_reader :deprecation_stream, :summary_stream, :deprecation_formatter
114
101
 
115
102
  def initialize(deprecation_stream, summary_stream, deprecation_formatter)
116
103
  @deprecation_stream = deprecation_stream
117
104
 
105
+ # In one of my test suites, I got lots of duplicate output in the
106
+ # deprecation file (e.g. 200 of the same deprecation, even though
107
+ # the `puts` below was only called 6 times). Setting `sync = true`
108
+ # fixes this (but we really have no idea why!).
109
+ @deprecation_stream.sync = true
110
+
118
111
  @summary_stream = summary_stream
119
112
  @deprecation_formatter = deprecation_formatter
120
113
  end
@@ -125,8 +118,10 @@ module RSpec
125
118
  end
126
119
 
127
120
  def deprecation_summary
128
- return if deprecation_formatter.count.zero?
129
- deprecation_stream.summarize(summary_stream, deprecation_formatter.count)
121
+ if deprecation_formatter.count > 0
122
+ summary_stream.puts "\n#{pluralize(deprecation_formatter.count, 'deprecation')} logged to #{deprecation_stream.path}"
123
+ deprecation_stream.puts RAISE_ERROR_CONFIG_NOTICE
124
+ end
130
125
  end
131
126
  end
132
127
 
@@ -181,38 +176,12 @@ module RSpec
181
176
 
182
177
  # Not really a stream, but is usable in place of one.
183
178
  class RaiseErrorStream
184
- include ::RSpec::Core::Formatters::Helpers
185
-
186
179
  def puts(message)
187
180
  raise DeprecationError, message
188
181
  end
189
182
 
190
- def summarize(summary_stream, deprecation_count)
191
- summary_stream.puts "\n#{pluralize(deprecation_count, 'deprecation')} found."
192
- end
193
- end
194
-
195
- # Wraps a File object and provides file-specific operations.
196
- class FileStream
197
- include ::RSpec::Core::Formatters::Helpers
198
-
199
- def initialize(file)
200
- @file = file
201
-
202
- # In one of my test suites, I got lots of duplicate output in the
203
- # deprecation file (e.g. 200 of the same deprecation, even though
204
- # the `puts` below was only called 6 times). Setting `sync = true`
205
- # fixes this (but we really have no idea why!).
206
- @file.sync = true
207
- end
208
-
209
- def puts(*args)
210
- @file.puts(*args)
211
- end
212
-
213
- def summarize(summary_stream, deprecation_count)
214
- summary_stream.puts "\n#{pluralize(deprecation_count, 'deprecation')} logged to #{@file.path}"
215
- puts RAISE_ERROR_CONFIG_NOTICE
183
+ def sync=(value)
184
+ # no-op
216
185
  end
217
186
  end
218
187
 
@@ -1,34 +1,7 @@
1
1
  module RSpec
2
2
  module Core
3
- module BacktraceFormatter
4
- extend self
5
-
6
- def format_backtrace(backtrace, options = {})
7
- return "" unless backtrace
8
- return backtrace if options[:full_backtrace] == true
9
-
10
- if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE)
11
- backtrace = backtrace[0, at_exit_index]
12
- end
13
-
14
- cleansed = backtrace.map { |line| backtrace_line(line) }.compact
15
- cleansed.empty? ? backtrace : cleansed
16
- end
17
-
18
- protected
19
-
20
- def backtrace_line(line)
21
- return nil if RSpec.configuration.backtrace_formatter.exclude?(line)
22
- RSpec::Core::Metadata::relative_path(line)
23
- rescue SecurityError
24
- nil
25
- end
26
- end
27
-
28
3
  module Formatters
29
4
  module Helpers
30
- include BacktraceFormatter
31
-
32
5
  SUB_SECOND_PRECISION = 5
33
6
  DEFAULT_PRECISION = 2
34
7
 
@@ -104,7 +77,6 @@ module RSpec
104
77
  "#{count} #{string}#{'s' unless count.to_f == 1}"
105
78
  end
106
79
  end
107
-
108
80
  end
109
81
  end
110
82
  end
@@ -119,7 +119,7 @@ module RSpec
119
119
  #
120
120
  def extra_failure_content(exception)
121
121
  require 'rspec/core/formatters/snippet_extractor'
122
- backtrace = exception.backtrace.map {|line| backtrace_line(line)}
122
+ backtrace = exception.backtrace.map {|line| configuration.backtrace_formatter.backtrace_line(line)}
123
123
  backtrace.compact!
124
124
  @snippet_extractor ||= SnippetExtractor.new
125
125
  " <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(backtrace)}</code></pre>"
@@ -27,6 +27,8 @@ module RSpec
27
27
  :pending_count => pending_count
28
28
  }
29
29
  @output_hash[:summary_line] = summary_line(example_count, failure_count, pending_count)
30
+
31
+ dump_profile unless mute_profile_output?(failure_count)
30
32
  end
31
33
 
32
34
  def summary_line(example_count, failure_count, pending_count)
@@ -39,15 +41,7 @@ module RSpec
39
41
  def stop
40
42
  super
41
43
  @output_hash[:examples] = examples.map do |example|
42
- {
43
- :description => example.description,
44
- :full_description => example.full_description,
45
- :status => example.execution_result[:status],
46
- # :example_group,
47
- # :execution_result,
48
- :file_path => example.metadata[:file_path],
49
- :line_number => example.metadata[:line_number],
50
- }.tap do |hash|
44
+ format_example(example).tap do |hash|
51
45
  if e=example.exception
52
46
  hash[:exception] = {
53
47
  :class => e.class.name,
@@ -64,6 +58,41 @@ module RSpec
64
58
  output.close if IO === output && output != $stdout
65
59
  end
66
60
 
61
+ def dump_profile
62
+ @output_hash[:profile] = {}
63
+ dump_profile_slowest_examples
64
+ dump_profile_slowest_example_groups
65
+ end
66
+
67
+ def dump_profile_slowest_examples
68
+ @output_hash[:profile] = {}
69
+ sorted_examples = slowest_examples
70
+ @output_hash[:profile][:examples] = sorted_examples[:examples].map do |example|
71
+ format_example(example).tap do |hash|
72
+ hash[:run_time] = example.execution_result[:run_time]
73
+ end
74
+ end
75
+ @output_hash[:profile][:slowest] = sorted_examples[:slows]
76
+ @output_hash[:profile][:total] = sorted_examples[:total]
77
+ end
78
+
79
+ def dump_profile_slowest_example_groups
80
+ @output_hash[:profile] ||= {}
81
+ @output_hash[:profile][:groups] = slowest_groups.map do |loc, hash|
82
+ hash.update(:location => loc)
83
+ end
84
+ end
85
+
86
+ private
87
+ def format_example(example)
88
+ {
89
+ :description => example.description,
90
+ :full_description => example.full_description,
91
+ :status => example.execution_result[:status],
92
+ :file_path => example.metadata[:file_path],
93
+ :line_number => example.metadata[:line_number]
94
+ }
95
+ end
67
96
  end
68
97
  end
69
98
  end
@@ -5,11 +5,21 @@ module RSpec
5
5
  #
6
6
  # Extracts code snippets by looking at the backtrace of the passed error and applies synax highlighting and line numbers using html.
7
7
  class SnippetExtractor
8
- class NullConverter; def convert(code, pre); code; end; end
8
+ class NullConverter
9
+ def convert(code)
10
+ %Q(#{code}\n<span class="comment"># Install the coderay gem to get syntax highlighting</span>)
11
+ end
12
+ end
13
+
14
+ class CoderayConverter
15
+ def convert(code)
16
+ CodeRay.scan(code, :ruby).html(:line_numbers => false)
17
+ end
18
+ end
9
19
 
10
20
  begin
11
- require 'syntax/convertors/html'
12
- @@converter = Syntax::Convertors::HTML.for_syntax "ruby"
21
+ require 'coderay'
22
+ @@converter = CoderayConverter.new
13
23
  rescue LoadError
14
24
  @@converter = NullConverter.new
15
25
  end
@@ -24,8 +34,7 @@ module RSpec
24
34
  # @see #post_process
25
35
  def snippet(backtrace)
26
36
  raw_code, line = snippet_for(backtrace[0])
27
- highlighted = @@converter.convert(raw_code, false)
28
- highlighted << "\n<span class=\"comment\"># gem install syntax to get syntax highlighting</span>" if @@converter.is_a?(NullConverter)
37
+ highlighted = @@converter.convert(raw_code)
29
38
  post_process(highlighted, line)
30
39
  end
31
40
 
@@ -1,8 +1,6 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Hooks
4
- include MetadataHashBuilder::WithConfigWarning
5
-
6
4
  class Hook
7
5
  attr_reader :block, :options
8
6
 
@@ -18,7 +16,7 @@ module RSpec
18
16
 
19
17
  class BeforeHook < Hook
20
18
  def run(example)
21
- example.instance_eval_with_args(example, &block)
19
+ example.instance_exec(example, &block)
22
20
  end
23
21
 
24
22
  def display_name
@@ -28,7 +26,7 @@ module RSpec
28
26
 
29
27
  class AfterHook < Hook
30
28
  def run(example)
31
- example.instance_eval_with_rescue("in an after hook", &block)
29
+ example.instance_exec_with_rescue("in an after hook", &block)
32
30
  end
33
31
 
34
32
  def display_name
@@ -61,18 +59,26 @@ EOS
61
59
  end
62
60
  end
63
61
 
64
- module HookCollectionAliases
65
- def self.included(host)
66
- host.send :alias_method, :prepend, :unshift
67
- host.send :alias_method, :append, :push
62
+ class BaseHookCollection
63
+ Array.public_instance_methods(false).each do |name|
64
+ define_method(name) { |*a, &b| hooks.__send__(name, *a, &b) }
68
65
  end
69
- end
70
66
 
71
- class HookCollection < Array
72
- include HookCollectionAliases
67
+ attr_reader :hooks
68
+ protected :hooks
73
69
 
70
+ alias append push
71
+ alias prepend unshift
72
+
73
+ def initialize(hooks=[])
74
+ @hooks = hooks
75
+ end
76
+ end
77
+
78
+ class HookCollection < BaseHookCollection
74
79
  def for(example_or_group)
75
- self.class.new(select {|hook| hook.options_apply?(example_or_group)}).
80
+ self.class.
81
+ new(hooks.select {|hook| hook.options_apply?(example_or_group)}).
76
82
  with(example_or_group)
77
83
  end
78
84
 
@@ -82,15 +88,13 @@ EOS
82
88
  end
83
89
 
84
90
  def run
85
- each {|h| h.run(@example) } unless empty?
91
+ hooks.each {|h| h.run(@example)}
86
92
  end
87
93
  end
88
94
 
89
- class AroundHookCollection < Array
90
- include HookCollectionAliases
91
-
95
+ class AroundHookCollection < BaseHookCollection
92
96
  def for(example, initial_procsy=nil)
93
- self.class.new(select {|hook| hook.options_apply?(example)}).
97
+ self.class.new(hooks.select {|hook| hook.options_apply?(example)}).
94
98
  with(example, initial_procsy)
95
99
  end
96
100
 
@@ -101,51 +105,61 @@ EOS
101
105
  end
102
106
 
103
107
  def run
104
- inject(@initial_procsy) do |procsy, around_hook|
105
- Example.procsy(procsy.metadata) do
106
- @example.instance_eval_with_args(procsy, &around_hook.block)
108
+ hooks.reduce(@initial_procsy) do |procsy, around_hook|
109
+ procsy.wrap do
110
+ @example.instance_exec(procsy, &around_hook.block)
107
111
  end
108
112
  end.call
109
113
  end
110
114
  end
111
115
 
112
- class GroupHookCollection < Array
116
+ class GroupHookCollection < BaseHookCollection
113
117
  def for(group)
114
118
  @group = group
115
119
  self
116
120
  end
117
121
 
118
122
  def run
119
- shift.run(@group) until empty?
123
+ hooks.shift.run(@group) until hooks.empty?
120
124
  end
121
125
  end
122
126
 
123
- module RegistersGlobals
124
- def register_globals host, globals
125
- [:before, :after, :around].each do |position|
126
- process host, globals, position, :each
127
- next if position == :around # no around(:all) hooks
128
- process host, globals, position, :all
129
- end
127
+ class HookCollections
128
+ def initialize(data)
129
+ @data = data
130
+ end
131
+
132
+ def [](key)
133
+ @data[key]
134
+ end
135
+
136
+ def register_globals(host, globals)
137
+ process(host, globals, :before, :each)
138
+ process(host, globals, :after, :each)
139
+ process(host, globals, :around, :each)
140
+
141
+ process(host, globals, :before, :all)
142
+ process(host, globals, :after, :all)
130
143
  end
131
144
 
132
145
  private
133
- def process host, globals, position, scope
146
+
147
+ def process(host, globals, position, scope)
134
148
  globals[position][scope].each do |hook|
135
- unless host.parent_groups.any? { |a| a.hooks[position][scope].include? hook }
136
- self[position][scope] << hook if scope == :each || hook.options_apply?(host)
137
- end
149
+ next unless scope == :each || hook.options_apply?(host)
150
+ next if host.parent_groups.any? {|a| a.hooks[position][scope].include?(hook)}
151
+ self[position][scope] << hook
138
152
  end
139
153
  end
140
154
  end
141
155
 
142
156
  # @private
143
157
  def hooks
144
- @hooks ||= {
158
+ @hooks ||= HookCollections.new(
145
159
  :around => { :each => AroundHookCollection.new },
146
160
  :before => { :each => HookCollection.new, :all => HookCollection.new, :suite => HookCollection.new },
147
161
  :after => { :each => HookCollection.new, :all => HookCollection.new, :suite => HookCollection.new }
148
- }.extend(RegistersGlobals)
162
+ )
149
163
  end
150
164
 
151
165
  # @api public
@@ -443,12 +457,14 @@ EOS
443
457
  # Runs all of the blocks stored with the hook in the context of the
444
458
  # example. If no example is provided, just calls the hook directly.
445
459
  def run_hook(hook, scope, example_or_group=ExampleGroup.new, initial_procsy=nil)
460
+ return if RSpec.configuration.dry_run?
461
+
446
462
  find_hook(hook, scope, example_or_group, initial_procsy).run
447
463
  end
448
464
 
449
465
  # @private
450
466
  def around_each_hooks_for(example, initial_procsy=nil)
451
- AroundHookCollection.new(parent_groups.map {|a| a.hooks[:around][:each]}.flatten).for(example, initial_procsy)
467
+ AroundHookCollection.new(FlatMap.flat_map(parent_groups) {|a| a.hooks[:around][:each]}).for(example, initial_procsy)
452
468
  end
453
469
 
454
470
  private
@@ -472,11 +488,11 @@ EOS
472
488
  end
473
489
 
474
490
  def before_each_hooks_for(example)
475
- HookCollection.new(parent_groups.reverse.map {|a| a.hooks[:before][:each]}.flatten).for(example)
491
+ HookCollection.new(FlatMap.flat_map(parent_groups.reverse) {|a| a.hooks[:before][:each]}).for(example)
476
492
  end
477
493
 
478
494
  def after_each_hooks_for(example)
479
- HookCollection.new(parent_groups.map {|a| a.hooks[:after][:each]}.flatten).for(example)
495
+ HookCollection.new(FlatMap.flat_map(parent_groups) {|a| a.hooks[:after][:each]}).for(example)
480
496
  end
481
497
 
482
498
  def register_hook prepend_or_append, hook, *args, &block
@@ -502,7 +518,7 @@ EOS
502
518
  end
503
519
 
504
520
  def scope_and_options_from(*args)
505
- return extract_scope_from(args), build_metadata_hash_from(args)
521
+ return extract_scope_from(args), Metadata.build_hash_from(args)
506
522
  end
507
523
 
508
524
  def extract_scope_from(args)