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
@@ -0,0 +1,511 @@
1
+ RSpec::Support.require_rspec_core "formatters/helpers"
2
+
3
+ module RSpec::Core
4
+ # Notifications are value objects passed to formatters to provide them
5
+ # with information about a particular event of interest.
6
+ module Notifications
7
+
8
+ # The `StartNotification` represents a notification sent by the reporter
9
+ # when the suite is started. It contains the expected amount of examples
10
+ # to be executed, and the load time of RSpec.
11
+ #
12
+ # @attr count [Fixnum] the number counted
13
+ # @attr load_time [Float] the number of seconds taken to boot RSpec
14
+ # and load the spec files
15
+ StartNotification = Struct.new(:count, :load_time)
16
+
17
+ # The `ExampleNotification` represents notifications sent by the reporter
18
+ # which contain information about the current (or soon to be) example.
19
+ # It is used by formatters to access information about that example.
20
+ #
21
+ # @example
22
+ # def example_started(notification)
23
+ # puts "Hey I started #{notification.example.description}"
24
+ # end
25
+ #
26
+ # @attr example [RSpec::Core::Example] the current example
27
+ ExampleNotification = Struct.new(:example) do
28
+ # @private
29
+ def self.for(example)
30
+ if example.execution_result.pending_fixed?
31
+ PendingExampleFixedNotification.new(example)
32
+ elsif example.execution_result.status == :failed
33
+ FailedExampleNotification.new(example)
34
+ else
35
+ new(example)
36
+ end
37
+ end
38
+ private_class_method :new
39
+ end
40
+
41
+ # The `ExamplesNotification` represents notifications sent by the reporter
42
+ # which contain information about the suites examples.
43
+ #
44
+ # @example
45
+ # def stop(notification)
46
+ # puts "Hey I ran #{notification.examples.size}"
47
+ # end
48
+ #
49
+ class ExamplesNotification
50
+
51
+ def initialize(reporter)
52
+ @reporter = reporter
53
+ end
54
+
55
+ # @return [Array(RSpec::Core::Example)] list of examples
56
+ def examples
57
+ @reporter.examples
58
+ end
59
+
60
+ # @return [Array(RSpec::Core::Example)] list of failed examples
61
+ def failed_examples
62
+ @reporter.failed_examples
63
+ end
64
+
65
+ # @return [Array(RSpec::Core::Example)] list of pending examples
66
+ def pending_examples
67
+ @reporter.pending_examples
68
+ end
69
+
70
+ # @return [Array(Rspec::Core::Notifications::ExampleNotification]
71
+ # returns examples as notifications
72
+ def notifications
73
+ @notifications ||= format(examples)
74
+ end
75
+
76
+ # @return [Array(Rspec::Core::Notifications::FailedExampleNotification]
77
+ # returns failed examples as notifications
78
+ def failure_notifications
79
+ @failed_notifications ||= format(failed_examples)
80
+ end
81
+
82
+ # @return [String] The list of failed examples, fully formatted in the way that
83
+ # RSpec's built-in formatters emit.
84
+ def fully_formatted_failed_examples(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
85
+ formatted = "\nFailures:\n"
86
+
87
+ failure_notifications.each_with_index do |failure, index|
88
+ formatted << failure.fully_formatted(index.next, colorizer)
89
+ end
90
+
91
+ formatted
92
+ end
93
+
94
+ # @return [String] The list of pending examples, fully formatted in the way that
95
+ # RSpec's built-in formatters emit.
96
+ def fully_formatted_pending_examples(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
97
+ formatted = "\nPending:\n"
98
+
99
+ pending_examples.each do |example|
100
+ formatted_caller = RSpec.configuration.backtrace_formatter.backtrace_line(example.location)
101
+
102
+ formatted <<
103
+ " #{colorizer.wrap(example.full_description, :pending)}\n" <<
104
+ " # #{colorizer.wrap(example.execution_result.pending_message, :detail)}\n" <<
105
+ " # #{colorizer.wrap(formatted_caller, :detail)}\n"
106
+ end
107
+
108
+ formatted
109
+ end
110
+
111
+ private
112
+
113
+ def format(examples)
114
+ examples.map do |example|
115
+ ExampleNotification.for(example)
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ # The `FailedExampleNotification` extends `ExampleNotification` with
122
+ # things useful for failed specs.
123
+ #
124
+ # @example
125
+ # def example_failed(notification)
126
+ # puts "Hey I failed :("
127
+ # puts "Here's my stack trace"
128
+ # puts notification.exception.backtrace.join("\n")
129
+ # end
130
+ #
131
+ # @attr [RSpec::Core::Example] example the current example
132
+ # @see ExampleNotification
133
+ class FailedExampleNotification < ExampleNotification
134
+ public_class_method :new
135
+
136
+ # @return [Exception] The example failure
137
+ def exception
138
+ example.execution_result.exception
139
+ end
140
+
141
+ # @return [String] The example description
142
+ def description
143
+ example.full_description
144
+ end
145
+
146
+ # Returns the message generated for this failure line by line.
147
+ #
148
+ # @return [Array(String)] The example failure message
149
+ def message_lines
150
+ @lines ||=
151
+ begin
152
+ lines = ["Failure/Error: #{read_failed_line.strip}"]
153
+ lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
154
+ exception.message.to_s.split("\n").each do |line|
155
+ lines << " #{line}" if exception.message
156
+ end
157
+ if shared_group
158
+ lines << "Shared Example Group: \"#{shared_group.metadata[:shared_group_name]}\"" +
159
+ " called from #{backtrace_formatter.backtrace_line(shared_group.location)}"
160
+ end
161
+ lines
162
+ end
163
+ end
164
+
165
+ # Returns the message generated for this failure colorized line by line.
166
+ #
167
+ # @param colorizer [#wrap] An object to colorize the message_lines by
168
+ # @return [Array(String)] The example failure message colorized
169
+ def colorized_message_lines(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
170
+ message_lines.map do |line|
171
+ colorizer.wrap line, RSpec.configuration.failure_color
172
+ end
173
+ end
174
+
175
+ # Returns the failures formatted backtrace.
176
+ #
177
+ # @return [Array(String)] the examples backtrace lines
178
+ def formatted_backtrace
179
+ backtrace_formatter.format_backtrace(exception.backtrace, example.metadata)
180
+ end
181
+
182
+ # Returns the failures colorized formatted backtrace.
183
+ #
184
+ # @param colorizer [#wrap] An object to colorize the message_lines by
185
+ # @return [Array(String)] the examples colorized backtrace lines
186
+ def colorized_formatted_backtrace(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
187
+ formatted_backtrace.map do |backtrace_info|
188
+ colorizer.wrap "# #{backtrace_info}", RSpec.configuration.detail_color
189
+ end
190
+ end
191
+
192
+ # @return [String] The failure information fully formatted in the way that
193
+ # RSpec's built-in formatters emit.
194
+ def fully_formatted(failure_number, colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
195
+ formatted = "\n #{failure_number}) #{description}\n"
196
+
197
+ colorized_message_lines(colorizer).each do |line|
198
+ formatted << " #{line}\n"
199
+ end
200
+
201
+ colorized_formatted_backtrace(colorizer).each do |line|
202
+ formatted << " #{line}\n"
203
+ end
204
+
205
+ formatted
206
+ end
207
+
208
+ private
209
+
210
+ def backtrace_formatter
211
+ RSpec.configuration.backtrace_formatter
212
+ end
213
+
214
+ def exception_class_name
215
+ name = exception.class.name.to_s
216
+ name ="(anonymous error class)" if name == ''
217
+ name
218
+ end
219
+
220
+ def shared_group
221
+ @shared_group ||= group_and_parent_groups.find { |group| group.metadata[:shared_group_name] }
222
+ end
223
+
224
+ def group_and_parent_groups
225
+ example.example_group.parent_groups + [example.example_group]
226
+ end
227
+
228
+ def read_failed_line
229
+ unless matching_line = find_failed_line
230
+ return "Unable to find matching line from backtrace"
231
+ end
232
+
233
+ file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
234
+
235
+ if File.exist?(file_path)
236
+ File.readlines(file_path)[line_number.to_i - 1] ||
237
+ "Unable to find matching line in #{file_path}"
238
+ else
239
+ "Unable to find #{file_path} to read failed line"
240
+ end
241
+ rescue SecurityError
242
+ "Unable to read failed line"
243
+ end
244
+
245
+ def find_failed_line
246
+ path = File.expand_path(example.file_path)
247
+ exception.backtrace.detect do |line|
248
+ match = line.match(/(.+?):(\d+)(|:\d+)/)
249
+ match && match[1].downcase == path.downcase
250
+ end
251
+ end
252
+ end
253
+
254
+ # The `PendingExampleFixedNotification` extends `ExampleNotification` with
255
+ # things useful for specs that pass when they are expected to fail.
256
+ #
257
+ # @attr [RSpec::Core::Example] example the current example
258
+ # @see ExampleNotification
259
+ class PendingExampleFixedNotification < FailedExampleNotification
260
+ public_class_method :new
261
+
262
+ # Returns the examples description
263
+ #
264
+ # @return [String] The example description
265
+ def description
266
+ "#{example.full_description} FIXED"
267
+ end
268
+
269
+ # Returns the message generated for this failure line by line.
270
+ #
271
+ # @return [Array(String)] The example failure message
272
+ def message_lines
273
+ ["Expected pending '#{example.execution_result.pending_message}' to fail. No Error was raised."]
274
+ end
275
+
276
+ # Returns the message generated for this failure colorized line by line.
277
+ #
278
+ # @param colorizer [#wrap] An object to colorize the message_lines by
279
+ # @return [Array(String)] The example failure message colorized
280
+ def colorized_message_lines(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
281
+ message_lines.map { |line| colorizer.wrap(line, RSpec.configuration.fixed_color) }
282
+ end
283
+ end
284
+
285
+ # The `GroupNotification` represents notifications sent by the reporter which
286
+ # contain information about the currently running (or soon to be) example group
287
+ # It is used by formatters to access information about that group.
288
+ #
289
+ # @example
290
+ # def example_group_started(notification)
291
+ # puts "Hey I started #{notification.group.description}"
292
+ # end
293
+ # @attr group [RSpec::Core::ExampleGroup] the current group
294
+ GroupNotification = Struct.new(:group)
295
+
296
+ # The `MessageNotification` encapsulates generic messages that the reporter
297
+ # sends to formatters.
298
+ #
299
+ # @attr message [String] the message
300
+ MessageNotification = Struct.new(:message)
301
+
302
+ # The `SeedNotification` holds the seed used to randomize examples and
303
+ # wether that seed has been used or not.
304
+ #
305
+ # @attr seed [Fixnum] the seed used to randomize ordering
306
+ # @attr used [Boolean] wether the seed has been used or not
307
+ SeedNotification = Struct.new(:seed, :used) do
308
+ # @api
309
+ # @return [Boolean] has the seed been used?
310
+ def seed_used?
311
+ !!used
312
+ end
313
+ private :used
314
+
315
+ # @return [String] The seed information fully formatted in the way that
316
+ # RSpec's built-in formatters emit.
317
+ def fully_formatted
318
+ "\nRandomized with seed #{seed}\n\n"
319
+ end
320
+ end
321
+
322
+ # The `SummaryNotification` holds information about the results of running
323
+ # a test suite. It is used by formatters to provide information at the end
324
+ # of the test run.
325
+ #
326
+ # @attr duration [Float] the time taken (in seconds) to run the suite
327
+ # @attr examples [Array(RSpec::Core::Example)] the examples run
328
+ # @attr failed_examples [Array(RSpec::Core::Example)] the failed examples
329
+ # @attr pending_examples [Array(RSpec::Core::Example)] the pending examples
330
+ # @attr load_time [Float] the number of seconds taken to boot RSpec
331
+ # and load the spec files
332
+ SummaryNotification = Struct.new(:duration, :examples, :failed_examples, :pending_examples, :load_time) do
333
+
334
+ # @api
335
+ # @return [Fixnum] the number of examples run
336
+ def example_count
337
+ @example_count ||= examples.size
338
+ end
339
+
340
+ # @api
341
+ # @return [Fixnum] the number of failed examples
342
+ def failure_count
343
+ @failure_count ||= failed_examples.size
344
+ end
345
+
346
+ # @api
347
+ # @return [Fixnum] the number of pending examples
348
+ def pending_count
349
+ @pending_count ||= pending_examples.size
350
+ end
351
+
352
+ # @api
353
+ # @return [String] A line summarising the result totals of the spec run.
354
+ def totals_line
355
+ summary = Formatters::Helpers.pluralize(example_count, "example")
356
+ summary << ", " << Formatters::Helpers.pluralize(failure_count, "failure")
357
+ summary << ", #{pending_count} pending" if pending_count > 0
358
+ summary
359
+ end
360
+
361
+ # @api public
362
+ #
363
+ # Wraps the results line with colors based on the configured
364
+ # colors for failure, pending, and success. Defaults to red,
365
+ # yellow, green accordingly.
366
+ #
367
+ # @param colorizer [#wrap] An object which supports wrapping text with
368
+ # specific colors.
369
+ # @return [String] A colorized results line.
370
+ def colorized_totals_line(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
371
+ if failure_count > 0
372
+ colorizer.wrap(totals_line, RSpec.configuration.failure_color)
373
+ elsif pending_count > 0
374
+ colorizer.wrap(totals_line, RSpec.configuration.pending_color)
375
+ else
376
+ colorizer.wrap(totals_line, RSpec.configuration.success_color)
377
+ end
378
+ end
379
+
380
+ # @api public
381
+ #
382
+ # Formats failures into a rerunable command format.
383
+ #
384
+ # @param colorizer [#wrap] An object which supports wrapping text with
385
+ # specific colors.
386
+ # @return [String] A colorized summary line.
387
+ def colorized_rerun_commands(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
388
+ "\nFailed examples:\n\n" +
389
+ failed_examples.map do |example|
390
+ colorizer.wrap("rspec #{example.location}", RSpec.configuration.failure_color) + " " +
391
+ colorizer.wrap("# #{example.full_description}", RSpec.configuration.detail_color)
392
+ end.join("\n")
393
+ end
394
+
395
+ # @return [String] a formatted version of the time it took to run the suite
396
+ def formatted_duration
397
+ Formatters::Helpers.format_duration(duration)
398
+ end
399
+
400
+ # @return [String] a formatted version of the time it took to boot RSpec and
401
+ # load the spec files
402
+ def formatted_load_time
403
+ Formatters::Helpers.format_duration(load_time)
404
+ end
405
+
406
+ # @return [String] The summary information fully formatted in the way that
407
+ # RSpec's built-in formatters emit.
408
+ def fully_formatted(colorizer = ::RSpec::Core::Formatters::ConsoleCodes)
409
+ formatted = "\nFinished in #{formatted_duration} " \
410
+ "(files took #{formatted_load_time} to load)\n" \
411
+ "#{colorized_totals_line(colorizer)}\n"
412
+
413
+ unless failed_examples.empty?
414
+ formatted << colorized_rerun_commands(colorizer) << "\n"
415
+ end
416
+
417
+ formatted
418
+ end
419
+ end
420
+
421
+ # The `ProfileNotification` holds information about the results of running
422
+ # a test suite when profiling is enabled. It is used by formatters to provide
423
+ # information at the end of the test run for profiling information.
424
+ #
425
+ # @attr duration [Float] the time taken (in seconds) to run the suite
426
+ # @attr examples [Array(RSpec::Core::Example)] the examples run
427
+ # @attr number_of_examples [Fixnum] the number of examples to profile
428
+ ProfileNotification = Struct.new(:duration, :examples, :number_of_examples) do
429
+
430
+ # @return [Array(RSpec::Core::Example)] the slowest examples
431
+ def slowest_examples
432
+ @slowest_examples ||=
433
+ examples.sort_by do |example|
434
+ -example.execution_result.run_time
435
+ end.first(number_of_examples)
436
+ end
437
+
438
+ # @return [Float] the time taken (in seconds) to run the slowest examples
439
+ def slow_duration
440
+ @slow_duration ||=
441
+ slowest_examples.inject(0.0) do |i, e|
442
+ i + e.execution_result.run_time
443
+ end
444
+ end
445
+
446
+ # @return [String] the percentage of total time taken
447
+ def percentage
448
+ @percentage ||=
449
+ begin
450
+ time_taken = slow_duration / duration
451
+ '%.1f' % ((time_taken.nan? ? 0.0 : time_taken) * 100)
452
+ end
453
+ end
454
+
455
+ # @return [Array(RSpec::Core::Example)] the slowest example groups
456
+ def slowest_groups
457
+ @slowest_groups ||= calculate_slowest_groups
458
+ end
459
+
460
+ private
461
+
462
+ def calculate_slowest_groups
463
+ example_groups = {}
464
+
465
+ examples.each do |example|
466
+ location = example.example_group.parent_groups.last.metadata[:location]
467
+
468
+ location_hash = example_groups[location] ||= Hash.new(0)
469
+ location_hash[:total_time] += example.execution_result.run_time
470
+ location_hash[:count] += 1
471
+ unless location_hash.has_key?(:description)
472
+ location_hash[:description] = example.example_group.top_level_description
473
+ end
474
+ end
475
+
476
+ # stop if we've only one example group
477
+ return {} if example_groups.keys.length <= 1
478
+
479
+ example_groups.each_value do |hash|
480
+ hash[:average] = hash[:total_time].to_f / hash[:count]
481
+ end
482
+
483
+ example_groups.sort_by { |_, hash| -hash[:average] }.first(number_of_examples)
484
+ end
485
+ end
486
+
487
+ # The `DeprecationNotification` is issued by the reporter when a deprecated
488
+ # part of RSpec is encountered. It represents information about the deprecated
489
+ # call site.
490
+ #
491
+ # @attr message [String] A custom message about the deprecation
492
+ # @attr deprecated [String] A custom message about the deprecation (alias of message)
493
+ # @attr replacement [String] An optional replacement for the deprecation
494
+ # @attr call_site [String] An optional call site from which the deprecation was issued
495
+ DeprecationNotification = Struct.new(:deprecated, :message, :replacement, :call_site) do
496
+ private_class_method :new
497
+
498
+ # @api
499
+ # Convenience way to initialize the notification
500
+ def self.from_hash(data)
501
+ new data[:deprecated], data[:message], data[:replacement], data[:call_site]
502
+ end
503
+ end
504
+
505
+ # `NullNotification` represents a placeholder value for notifications that
506
+ # currently require no information, but we may wish to extend in future.
507
+ class NullNotification
508
+ end
509
+
510
+ end
511
+ end