rspec-core 2.13.1 → 2.14.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/Changelog.md +80 -0
  2. data/exe/autospec +1 -1
  3. data/features/README.md +2 -2
  4. data/features/command_line/format_option.feature +8 -14
  5. data/features/command_line/line_number_appended_to_path.feature +4 -4
  6. data/features/command_line/line_number_option.feature +1 -1
  7. data/features/command_line/rake_task.feature +2 -2
  8. data/features/command_line/require_option.feature +43 -0
  9. data/features/command_line/ruby.feature +2 -2
  10. data/features/command_line/warnings_option.feature +27 -0
  11. data/features/configuration/backtrace_clean_patterns.feature +2 -2
  12. data/features/configuration/deprecation_stream.feature +58 -0
  13. data/features/configuration/pattern.feature +8 -0
  14. data/features/configuration/profile.feature +59 -2
  15. data/features/configuration/read_options_from_file.feature +8 -5
  16. data/features/configuration/run_all_when_everything_filtered.feature +20 -4
  17. data/features/example_groups/basic_structure.feature +1 -1
  18. data/features/example_groups/shared_context.feature +1 -1
  19. data/features/example_groups/shared_examples.feature +72 -0
  20. data/features/filtering/exclusion_filters.feature +10 -10
  21. data/features/formatters/custom_formatter.feature +1 -1
  22. data/features/hooks/before_and_after_hooks.feature +19 -19
  23. data/features/mock_framework_integration/use_any_framework.feature +6 -6
  24. data/features/mock_framework_integration/use_flexmock.feature +3 -3
  25. data/features/mock_framework_integration/use_mocha.feature +3 -3
  26. data/features/mock_framework_integration/use_rr.feature +3 -3
  27. data/features/mock_framework_integration/use_rspec.feature +3 -3
  28. data/features/subject/implicit_subject.feature +1 -1
  29. data/lib/rspec/core.rb +20 -3
  30. data/lib/rspec/core/backtrace_cleaner.rb +46 -0
  31. data/lib/rspec/core/backward_compatibility.rb +3 -13
  32. data/lib/rspec/core/configuration.rb +136 -49
  33. data/lib/rspec/core/configuration_options.rb +19 -8
  34. data/lib/rspec/core/deprecation.rb +18 -30
  35. data/lib/rspec/core/example.rb +3 -3
  36. data/lib/rspec/core/example_group.rb +4 -3
  37. data/lib/rspec/core/extensions/kernel.rb +1 -1
  38. data/lib/rspec/core/filter_manager.rb +1 -1
  39. data/lib/rspec/core/formatters.rb +1 -1
  40. data/lib/rspec/core/formatters/base_formatter.rb +10 -1
  41. data/lib/rspec/core/formatters/base_text_formatter.rb +47 -10
  42. data/lib/rspec/core/formatters/deprecation_formatter.rb +35 -0
  43. data/lib/rspec/core/formatters/helpers.rb +12 -5
  44. data/lib/rspec/core/formatters/html_formatter.rb +7 -6
  45. data/lib/rspec/core/formatters/html_printer.rb +13 -12
  46. data/lib/rspec/core/formatters/json_formatter.rb +1 -2
  47. data/lib/rspec/core/formatters/text_mate_formatter.rb +1 -1
  48. data/lib/rspec/core/hooks.rb +9 -0
  49. data/lib/rspec/core/memoized_helpers.rb +19 -8
  50. data/lib/rspec/core/metadata.rb +3 -1
  51. data/lib/rspec/core/mocking/with_flexmock.rb +1 -1
  52. data/lib/rspec/core/mocking/with_rr.rb +1 -1
  53. data/lib/rspec/core/option_parser.rb +6 -2
  54. data/lib/rspec/core/pending.rb +1 -0
  55. data/lib/rspec/core/rake_task.rb +11 -19
  56. data/lib/rspec/core/reporter.rb +33 -4
  57. data/lib/rspec/core/shared_example_group.rb +56 -16
  58. data/lib/rspec/core/shared_example_group/collection.rb +42 -0
  59. data/lib/rspec/core/version.rb +1 -1
  60. data/lib/rspec/core/world.rb +2 -3
  61. data/spec/autotest/rspec_spec.rb +2 -2
  62. data/spec/rspec/core/backtrace_cleaner_spec.rb +68 -0
  63. data/spec/rspec/core/configuration_options_spec.rb +15 -4
  64. data/spec/rspec/core/configuration_spec.rb +202 -19
  65. data/spec/rspec/core/deprecation_spec.rb +41 -0
  66. data/spec/rspec/core/deprecations_spec.rb +10 -12
  67. data/spec/rspec/core/drb_command_line_spec.rb +1 -1
  68. data/spec/rspec/core/example_group_spec.rb +37 -36
  69. data/spec/rspec/core/example_spec.rb +25 -4
  70. data/spec/rspec/core/filter_manager_spec.rb +6 -6
  71. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +101 -36
  72. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +78 -0
  73. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +2 -2
  74. data/spec/rspec/core/formatters/helpers_spec.rb +23 -7
  75. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +20 -14
  76. data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +69 -169
  77. data/spec/rspec/core/formatters/html_formatted-1.8.7.html +28 -23
  78. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +42 -33
  79. data/spec/rspec/core/formatters/html_formatted-1.9.3-jruby.html +17 -23
  80. data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +57 -157
  81. data/spec/rspec/core/formatters/html_formatted-1.9.3.html +42 -33
  82. data/spec/rspec/core/formatters/html_formatted-2.0.0.html +42 -33
  83. data/spec/rspec/core/formatters/html_formatter_spec.rb +1 -0
  84. data/spec/rspec/core/formatters/progress_formatter_spec.rb +3 -3
  85. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +11 -14
  86. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-rbx.html +103 -203
  87. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +30 -25
  88. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +42 -33
  89. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-jruby.html +20 -14
  90. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-rbx.html +103 -203
  91. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3.html +42 -33
  92. data/spec/rspec/core/formatters/text_mate_formatted-2.0.0.html +42 -33
  93. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -0
  94. data/spec/rspec/core/memoized_helpers_spec.rb +28 -0
  95. data/spec/rspec/core/metadata_spec.rb +8 -3
  96. data/spec/rspec/core/option_parser_spec.rb +8 -0
  97. data/spec/rspec/core/project_initializer_spec.rb +2 -2
  98. data/spec/rspec/core/rake_task_spec.rb +8 -8
  99. data/spec/rspec/core/reporter_spec.rb +26 -6
  100. data/spec/rspec/core/resources/formatter_specs.rb +3 -3
  101. data/spec/rspec/core/shared_context_spec.rb +20 -0
  102. data/spec/rspec/core/shared_example_group/collection_spec.rb +70 -0
  103. data/spec/rspec/core/shared_example_group_spec.rb +4 -4
  104. data/spec/rspec/core/world_spec.rb +1 -3
  105. data/spec/rspec/core_spec.rb +20 -0
  106. data/spec/spec_helper.rb +29 -29
  107. data/spec/support/helper_methods.rb +9 -1
  108. data/spec/support/isolate_load_path_mutation.rb +6 -0
  109. data/spec/support/sandboxed_mock_space.rb +100 -0
  110. metadata +28 -13
  111. data/features/filtering/run_all_when_everything_filtered.feature +0 -46
  112. data/lib/rspec/core/load_path.rb +0 -3
@@ -19,15 +19,12 @@ module RSpec
19
19
  end
20
20
 
21
21
  def configure(config)
22
- formatters = options.delete(:formatters)
23
-
24
22
  config.filter_manager = filter_manager
23
+ process_options_into config
25
24
 
26
- order(options.keys, :libs, :requires, :default_path, :pattern).each do |key|
27
- force?(key) ? config.force(key => options[key]) : config.send("#{key}=", options[key])
28
- end
25
+ config.setup_load_path_and_require(options[:requires] || [])
29
26
 
30
- formatters.each {|pair| config.add_formatter(*pair) } if formatters
27
+ load_formatters_into config
31
28
  end
32
29
 
33
30
  def parse_options
@@ -55,6 +52,8 @@ module RSpec
55
52
 
56
53
  MERGED_OPTIONS = [:requires, :libs].to_set
57
54
 
55
+ UNPROCESSABLE_OPTIONS = [:formatters, :requires].to_set
56
+
58
57
  def force?(key)
59
58
  !NON_FORCED_OPTIONS.include?(key)
60
59
  end
@@ -66,6 +65,18 @@ module RSpec
66
65
  keys
67
66
  end
68
67
 
68
+ def process_options_into(config)
69
+ opts = options.reject { |k, _| UNPROCESSABLE_OPTIONS.include? k }
70
+
71
+ order(opts.keys, :libs, :default_path, :pattern).each do |key|
72
+ force?(key) ? config.force(key => opts[key]) : config.send("#{key}=", opts[key])
73
+ end
74
+ end
75
+
76
+ def load_formatters_into(config)
77
+ options[:formatters].each { |pair| config.add_formatter(*pair) } if options[:formatters]
78
+ end
79
+
69
80
  def extract_filters_from(*configs)
70
81
  configs.compact.each do |config|
71
82
  filter_manager.include config.delete(:inclusion_filter) if config.has_key?(:inclusion_filter)
@@ -112,11 +123,11 @@ module RSpec
112
123
  def args_from_options_file(path)
113
124
  return [] unless path && File.exist?(path)
114
125
  config_string = options_file_as_erb_string(path)
115
- config_string.split(/\n+/).map {|l| l.shellsplit}.flatten
126
+ config_string.split(/\n+/).map {|l| Shellwords.shellwords(l) }.flatten
116
127
  end
117
128
 
118
129
  def options_file_as_erb_string(path)
119
- ERB.new(File.read(path)).result(binding)
130
+ ERB.new(File.read(path), nil, '-').result(binding)
120
131
  end
121
132
 
122
133
  def custom_options_file
@@ -1,36 +1,24 @@
1
1
  module RSpec
2
- class << self
3
- # @private
4
- #
5
- # Used internally to print deprecation warnings
6
- def deprecate(method, alternate_method=nil, version=nil)
7
- version_string = version ? "rspec-#{version}" : "a future version of RSpec"
8
-
9
- message = <<-NOTICE
10
-
11
- *****************************************************************
12
- DEPRECATION WARNING: you are using deprecated behaviour that will
13
- be removed from #{version_string}.
14
-
15
- #{caller(0)[2]}
16
-
17
- * #{method} is deprecated.
18
- NOTICE
19
- if alternate_method
20
- message << <<-ADDITIONAL
21
- * please use #{alternate_method} instead.
22
- ADDITIONAL
2
+ module Core
3
+ module Deprecation
4
+ # @private
5
+ #
6
+ # Used internally to print deprecation warnings
7
+ def deprecate(deprecated, replacement_or_hash={}, ignore_version=nil)
8
+ # Temporarily support old and new APIs while we transition the other
9
+ # rspec libs to use a hash for the 2nd arg and no version arg
10
+ data = Hash === replacement_or_hash ? replacement_or_hash : { :replacement => replacement_or_hash }
11
+ RSpec.configuration.reporter.deprecation data.merge(:deprecated => deprecated, :call_site => caller(0)[2])
23
12
  end
24
13
 
25
- message << "*****************************************************************"
26
- warn_deprecation(message)
27
- end
28
-
29
- # @private
30
- #
31
- # Used internally to print deprecation warnings
32
- def warn_deprecation(message)
33
- warn message
14
+ # @private
15
+ #
16
+ # Used internally to print deprecation warnings
17
+ def warn_deprecation(message)
18
+ RSpec.configuration.reporter.deprecation :message => message
19
+ end
34
20
  end
35
21
  end
22
+
23
+ extend(Core::Deprecation)
36
24
  end
@@ -79,7 +79,7 @@ module RSpec
79
79
  def initialize(example_group_class, description, metadata, example_block=nil)
80
80
  @example_group_class, @options, @example_block = example_group_class, metadata, example_block
81
81
  @metadata = @example_group_class.metadata.for_example(description, metadata)
82
- @exception = nil
82
+ @example_group_instance = @exception = nil
83
83
  @pending_declared_in_example = false
84
84
  end
85
85
 
@@ -317,8 +317,8 @@ An error occurred #{context}
317
317
 
318
318
  def assign_generated_description
319
319
  return unless RSpec.configuration.expecting_with_rspec?
320
- if metadata[:description].empty? and !pending?
321
- metadata[:description] = RSpec::Matchers.generated_description
320
+ if metadata[:description_args].empty? and !pending?
321
+ metadata[:description_args] << RSpec::Matchers.generated_description
322
322
  end
323
323
  RSpec::Matchers.clear_generated_description
324
324
  end
@@ -162,7 +162,7 @@ module RSpec
162
162
  # @private
163
163
  def self.find_and_eval_shared(label, name, *args, &customization_block)
164
164
  raise ArgumentError, "Could not find shared #{label} #{name.inspect}" unless
165
- shared_block = world.shared_example_groups[name]
165
+ shared_block = shared_example_groups[name]
166
166
 
167
167
  module_eval_with_args(*args, &shared_block)
168
168
  module_eval(&customization_block) if customization_block
@@ -287,8 +287,8 @@ module RSpec
287
287
  args << build_metadata_hash_from(args)
288
288
  args.unshift(symbol_description) if symbol_description
289
289
  @metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
290
- world.configure_group(self)
291
290
  hooks.register_globals(self, RSpec.configuration.hooks)
291
+ world.configure_group(self)
292
292
  end
293
293
 
294
294
  # @private
@@ -444,7 +444,8 @@ An error occurred in an after(:all) hook.
444
444
 
445
445
  # @deprecated use {ExampleGroup#example}
446
446
  def running_example
447
- RSpec.deprecate("running_example", "example")
447
+ RSpec.deprecate("running_example",
448
+ :replacement => "example")
448
449
  example
449
450
  end
450
451
 
@@ -4,6 +4,6 @@ module Kernel
4
4
  # message to STDERR when ruby-debug is not loaded.
5
5
  def debugger(*args)
6
6
  (RSpec.configuration.error_stream || $stderr).puts "\n***** debugger statement ignored, use -d or --debug option to enable debugging\n#{caller(0)[1]}"
7
- end
7
+ end
8
8
  end
9
9
  end
@@ -107,7 +107,7 @@ module RSpec
107
107
  # Emits a deprecation warning for keys that will not be supported in
108
108
  # the future.
109
109
  def _warn_deprecated_key(key, updates)
110
- RSpec.warn_deprecation("\nDEPRECATION NOTICE: FilterManager#exclude(#{key.inspect} => #{updates[key].inspect}) is deprecated with no replacement, and will be removed from rspec-3.0.")
110
+ RSpec.deprecate("FilterManager#exclude(#{key.inspect} => #{updates[key].inspect})")
111
111
  @exclusions[key] = updates.delete(key)
112
112
  end
113
113
  end
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # rspec --format documentation --format html --out results.html
18
18
  #
19
- # This example sends the output of the documentation formatter to `STDOUT`, and
19
+ # This example sends the output of the documentation formatter to `$stdout`, and
20
20
  # the output of the html formatter to results.html.
21
21
  #
22
22
  # ## Custom Formatters
@@ -105,7 +105,7 @@ module RSpec
105
105
  # @api public
106
106
  #
107
107
  # Used by the reporter to send messages to the output stream.
108
- #
108
+ #
109
109
  # @param [String] message
110
110
  def message(message)
111
111
  end
@@ -228,9 +228,18 @@ module RSpec
228
228
  configuration.profile_examples
229
229
  end
230
230
 
231
+ def fail_fast?
232
+ configuration.fail_fast
233
+ end
234
+
231
235
  def color_enabled?
232
236
  configuration.color_enabled?(output)
233
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
234
243
  end
235
244
  end
236
245
  end
@@ -44,7 +44,7 @@ module RSpec
44
44
 
45
45
  def dump_summary(duration, example_count, failure_count, pending_count)
46
46
  super(duration, example_count, failure_count, pending_count)
47
- dump_profile if profile_examples?
47
+ dump_profile unless mute_profile_output?(failure_count)
48
48
  output.puts "\nFinished in #{format_duration(duration)}\n"
49
49
  output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
50
50
  dump_commands_to_rerun_failed_examples
@@ -67,9 +67,14 @@ module RSpec
67
67
 
68
68
  # @api public
69
69
  #
70
- # Outputs the slowest examples in a report when using `--profile COUNT` (default 10).
71
- #
70
+ # Outputs the slowest examples and example groups in a report when using `--profile COUNT` (default 10).
71
+ #
72
72
  def dump_profile
73
+ dump_profile_slowest_examples
74
+ dump_profile_slowest_example_groups
75
+ end
76
+
77
+ def dump_profile_slowest_examples
73
78
  number_of_examples = RSpec.configuration.profile_examples
74
79
  sorted_examples = examples.sort_by {|example|
75
80
  example.execution_result[:run_time] }.reverse.first(number_of_examples)
@@ -88,6 +93,38 @@ module RSpec
88
93
  end
89
94
  end
90
95
 
96
+ def dump_profile_slowest_example_groups
97
+ number_of_examples = RSpec.configuration.profile_examples
98
+ example_groups = {}
99
+
100
+ examples.each do |example|
101
+ location = example.example_group.parent_groups.last.metadata[:example_group][:location]
102
+
103
+ example_groups[location] ||= Hash.new(0)
104
+ example_groups[location][:total_time] += example.execution_result[:run_time]
105
+ example_groups[location][:count] += 1
106
+ example_groups[location][:description] = example.example_group.top_level_description unless example_groups[location].has_key?(:description)
107
+ end
108
+
109
+ # stop if we've only one example group
110
+ return if example_groups.keys.length <= 1
111
+
112
+ example_groups.each do |loc, hash|
113
+ hash[:average] = hash[:total_time].to_f / hash[:count]
114
+ end
115
+
116
+ sorted_groups = example_groups.sort_by {|_, hash| -hash[:average]}.first(number_of_examples)
117
+
118
+ output.puts "\nTop #{sorted_groups.size} slowest example groups:"
119
+ sorted_groups.each do |loc, hash|
120
+ average = "#{failure_color(format_seconds(hash[:average]))} #{failure_color("seconds")} average"
121
+ total = "#{format_seconds(hash[:total_time])} seconds"
122
+ count = pluralize(hash[:count], "example")
123
+ output.puts " #{hash[:description]}"
124
+ output.puts detail_color(" #{average} (#{total} / #{count}) #{loc}")
125
+ end
126
+ end
127
+
91
128
  # @api public
92
129
  #
93
130
  # Outputs summary with number of examples, failures and pending.
@@ -188,37 +225,37 @@ module RSpec
188
225
  end
189
226
 
190
227
  def red(text)
191
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#red", "#failure_color", "3.0")
228
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#red", :replacement => "#failure_color")
192
229
  color(text, :red)
193
230
  end
194
231
 
195
232
  def green(text)
196
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#green", "#success_color", "3.0")
233
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#green", :replacement => "#success_color")
197
234
  color(text, :green)
198
235
  end
199
236
 
200
237
  def yellow(text)
201
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#yellow", "#pending_color", "3.0")
238
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#yellow", :replacement => "#pending_color")
202
239
  color(text, :yellow)
203
240
  end
204
241
 
205
242
  def blue(text)
206
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#blue", "#fixed_color", "3.0")
243
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#blue", :replacement => "#fixed_color")
207
244
  color(text, :blue)
208
245
  end
209
246
 
210
247
  def magenta(text)
211
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#magenta", nil, "3.0")
248
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#magenta")
212
249
  color(text, :magenta)
213
250
  end
214
251
 
215
252
  def cyan(text)
216
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#cyan", "#detail_color", "3.0")
253
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#cyan", :replacement => "#detail_color")
217
254
  color(text, :cyan)
218
255
  end
219
256
 
220
257
  def white(text)
221
- RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#white", "#default_color", "3.0")
258
+ RSpec.deprecate("RSpec::Core::Formatters::BaseTextFormatter#white", :replacement => "#default_color")
222
259
  color(text, :white)
223
260
  end
224
261
 
@@ -0,0 +1,35 @@
1
+ module RSpec
2
+ module Core
3
+ module Formatters
4
+ class DeprecationFormatter
5
+ def initialize(deprecation_stream=$stderr, summary_stream=$stdout)
6
+ @deprecation_stream = deprecation_stream
7
+ @summary_stream = summary_stream
8
+ @count = 0
9
+ end
10
+
11
+ def deprecation(data)
12
+ @count += 1
13
+ if data[:message]
14
+ @deprecation_stream.print data[:message]
15
+ else
16
+ @deprecation_stream.print "DEPRECATION: " unless File === @deprecation_stream
17
+ @deprecation_stream.print "#{data[:deprecated]} is deprecated."
18
+ @deprecation_stream.print " Use #{data[:replacement]} instead." if data[:replacement]
19
+ @deprecation_stream.print " Called from #{data[:call_site]}." if data[:call_site]
20
+ @deprecation_stream.puts
21
+ end
22
+ end
23
+
24
+ def deprecation_summary
25
+ if @count > 0 && File === @deprecation_stream
26
+ @summary_stream.print "\n#{@count} deprecation"
27
+ @summary_stream.print "s" if @count > 1
28
+ @summary_stream.print " logged to "
29
+ @summary_stream.puts @deprecation_stream.path
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -18,7 +18,7 @@ module RSpec
18
18
  protected
19
19
 
20
20
  def backtrace_line(line)
21
- return nil if RSpec.configuration.cleaned_from_backtrace?(line)
21
+ return nil if RSpec.configuration.backtrace_cleaner.exclude?(line)
22
22
  RSpec::Core::Metadata::relative_path(line)
23
23
  rescue SecurityError
24
24
  nil
@@ -43,20 +43,27 @@ module RSpec
43
43
  # format_duration(1) #=> "1 minute 1 second"
44
44
  # format_duration(135.14) #=> "2 minutes 15.14 seconds"
45
45
  def format_duration(duration)
46
+ precision = case
47
+ when duration < 1; SUB_SECOND_PRECISION
48
+ when duration < 120; DEFAULT_PRECISION
49
+ when duration < 300; 1
50
+ else 0
51
+ end
52
+
46
53
  if duration > 60
47
54
  minutes = duration.to_i / 60
48
55
  seconds = duration - minutes * 60
49
56
 
50
- "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds), 'second')}"
57
+ "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds, precision), 'second')}"
51
58
  else
52
- pluralize(format_seconds(duration), 'second')
59
+ pluralize(format_seconds(duration, precision), 'second')
53
60
  end
54
61
  end
55
62
 
56
63
  # @api private
57
64
  #
58
65
  # Formats seconds to have 5 digits of precision with trailing zeros removed if the number
59
- # if less than 1 or with 2 digits of precision if the number is greater than zero.
66
+ # is less than 1 or with 2 digits of precision if the number is greater than zero.
60
67
  #
61
68
  # @param [Float] float
62
69
  # @return [String] formatted float
@@ -69,7 +76,7 @@ module RSpec
69
76
  # The precision used is set in {Helpers::SUB_SECOND_PRECISION} and {Helpers::DEFAULT_PRECISION}.
70
77
  #
71
78
  # @see #strip_trailing_zeroes
72
- def format_seconds(float)
79
+ def format_seconds(float, precision = nil)
73
80
  precision ||= (float < 1) ? SUB_SECOND_PRECISION : DEFAULT_PRECISION
74
81
  formatted = sprintf("%.#{precision}f", float)
75
82
  strip_trailing_zeroes(formatted)
@@ -72,7 +72,7 @@ module RSpec
72
72
 
73
73
  unless @header_red
74
74
  @header_red = true
75
- @printer.make_header_red
75
+ @printer.make_header_red
76
76
  end
77
77
 
78
78
  unless @example_group_red
@@ -84,22 +84,23 @@ module RSpec
84
84
 
85
85
  exception = example.metadata[:execution_result][:exception]
86
86
  exception_details = if exception
87
- {
88
- :message => exception.message,
87
+ {
88
+ :message => exception.message,
89
89
  :backtrace => format_backtrace(exception.backtrace, example).join("\n")
90
90
  }
91
91
  else
92
- false
92
+ false
93
93
  end
94
94
  extra = extra_failure_content(exception)
95
95
 
96
- @printer.print_example_failed(
96
+ @printer.print_example_failed(
97
97
  exception.pending_fixed?,
98
98
  example.description,
99
99
  example.execution_result[:run_time],
100
100
  @failed_examples.size,
101
101
  exception_details,
102
- (extra == "") ? false : extra
102
+ (extra == "") ? false : extra,
103
+ true
103
104
  )
104
105
  @printer.flush
105
106
  end