rspec-core 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +9 -4
  3. data/Guardfile +3 -3
  4. data/README.md +1 -1
  5. data/features/.nav +7 -2
  6. data/features/{README.markdown → Autotest.md} +17 -20
  7. data/features/Changelog.md +57 -2
  8. data/features/README.md +17 -0
  9. data/features/Upgrade.md +8 -66
  10. data/features/command_line/configure.feature +2 -2
  11. data/features/command_line/example_name_option.feature +10 -10
  12. data/features/command_line/exit_status.feature +4 -4
  13. data/features/command_line/line_number_appended_to_path.feature +11 -11
  14. data/features/command_line/line_number_option.feature +9 -9
  15. data/features/command_line/tag.feature +9 -9
  16. data/features/configuration/custom_settings.feature +3 -3
  17. data/features/configuration/fail_fast.feature +3 -3
  18. data/features/configuration/read_options_from_file.feature +4 -4
  19. data/features/example_groups/shared_example_group.feature +4 -4
  20. data/features/expectation_framework_integration/configure_expectation_framework.feature +8 -9
  21. data/features/filtering/exclusion_filters.feature +1 -1
  22. data/features/filtering/run_all_when_everything_filtered.feature +1 -1
  23. data/features/formatters/custom_formatter.feature +17 -13
  24. data/features/helper_methods/arbitrary_methods.feature +40 -0
  25. data/features/helper_methods/let.feature +50 -0
  26. data/features/hooks/before_and_after_hooks.feature +10 -10
  27. data/features/hooks/filtering.feature +37 -20
  28. data/features/metadata/described_class.feature +1 -1
  29. data/features/mock_framework_integration/use_flexmock.feature +1 -1
  30. data/features/mock_framework_integration/use_mocha.feature +1 -1
  31. data/features/mock_framework_integration/use_rr.feature +1 -1
  32. data/features/mock_framework_integration/use_rspec.feature +1 -1
  33. data/features/spec_files/arbitrary_file_suffix.feature +1 -1
  34. data/features/step_definitions/additional_cli_steps.rb +1 -1
  35. data/features/subject/attribute_of_subject.feature +2 -2
  36. data/features/subject/explicit_subject.feature +5 -5
  37. data/features/subject/implicit_receiver.feature +2 -2
  38. data/features/subject/implicit_subject.feature +2 -2
  39. data/lib/autotest/rspec2.rb +63 -13
  40. data/lib/rspec/core/configuration.rb +0 -1
  41. data/lib/rspec/core/configuration_options.rb +15 -12
  42. data/lib/rspec/core/example.rb +14 -6
  43. data/lib/rspec/core/example_group.rb +5 -4
  44. data/lib/rspec/core/formatters/base_formatter.rb +1 -1
  45. data/lib/rspec/core/formatters/documentation_formatter.rb +1 -1
  46. data/lib/rspec/core/formatters/html_formatter.rb +131 -32
  47. data/lib/rspec/core/formatters/snippet_extractor.rb +1 -1
  48. data/lib/rspec/core/hooks.rb +16 -1
  49. data/lib/rspec/core/option_parser.rb +6 -6
  50. data/lib/rspec/core/rake_task.rb +1 -1
  51. data/lib/rspec/core/subject.rb +7 -7
  52. data/lib/rspec/core/version.rb +1 -1
  53. data/rspec-core.gemspec +0 -12
  54. data/script/FullBuildRakeFile +63 -0
  55. data/script/cucumber +1 -0
  56. data/script/full_build +1 -0
  57. data/script/spec +1 -0
  58. data/spec/autotest/failed_results_re_spec.rb +22 -5
  59. data/spec/autotest/rspec_spec.rb +132 -16
  60. data/spec/rspec/core/configuration_options_spec.rb +38 -6
  61. data/spec/rspec/core/example_group_spec.rb +15 -64
  62. data/spec/rspec/core/formatters/base_formatter_spec.rb +23 -0
  63. data/spec/rspec/core/formatters/html_formatted-1.8.6.html +150 -48
  64. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +151 -49
  65. data/spec/rspec/core/formatters/html_formatted-1.8.7.html +150 -48
  66. data/spec/rspec/core/formatters/html_formatted-1.9.1.html +150 -48
  67. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +150 -48
  68. data/spec/rspec/core/formatters/text_mate_formatted-1.8.6.html +150 -48
  69. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +151 -49
  70. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +150 -48
  71. data/spec/rspec/core/formatters/text_mate_formatted-1.9.1.html +150 -48
  72. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +150 -48
  73. data/spec/rspec/core/hooks_filtering_spec.rb +49 -0
  74. data/spec/rspec/core/rake_task_spec.rb +3 -3
  75. data/spec/rspec/core/subject_spec.rb +81 -0
  76. metadata +20 -22
  77. data/History.markdown +0 -186
  78. data/Upgrade.markdown +0 -345
@@ -58,7 +58,8 @@ module RSpec
58
58
 
59
59
  alias_example_to :it
60
60
  alias_example_to :specify
61
- alias_example_to :focused, :focused => true
61
+ alias_example_to :focused, :focused => true, :focus => true
62
+ alias_example_to :focus, :focused => true, :focus => true
62
63
  alias_example_to :pending, :pending => true
63
64
  alias_example_to :xit, :pending => true
64
65
 
@@ -172,14 +173,14 @@ module RSpec
172
173
  def self.eval_before_alls(example_group_instance)
173
174
  return if descendant_filtered_examples.empty?
174
175
  assign_before_all_ivars(superclass.before_all_ivars, example_group_instance)
175
- world.run_hook_filtered(:before, :all, self, example_group_instance) if top_level?
176
+ world.run_hook_filtered(:before, :all, self, example_group_instance)
176
177
  run_hook!(:before, :all, example_group_instance)
177
178
  store_before_all_ivars(example_group_instance)
178
179
  end
179
180
 
180
181
  def self.eval_around_eachs(example, initial_procsy)
181
182
  example.around_hooks.reverse.inject(initial_procsy) do |procsy, around_hook|
182
- Example::Procsy.new(procsy.metadata) do
183
+ Example.procsy(procsy.metadata) do
183
184
  example.example_group_instance.instance_eval_with_args(procsy, &around_hook)
184
185
  end
185
186
  end
@@ -212,7 +213,7 @@ An error occurred in an after(:all) hook.
212
213
  EOS
213
214
  end
214
215
 
215
- world.run_hook_filtered(:after, :all, self, example_group_instance) if top_level?
216
+ world.run_hook_filtered(:after, :all, self, example_group_instance)
216
217
  end
217
218
 
218
219
  def self.around_hooks_for(example)
@@ -121,7 +121,7 @@ module RSpec
121
121
  file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
122
122
 
123
123
  if File.exist?(file_path)
124
- open(file_path, 'r') { |f| f.readlines[line_number.to_i - 1] }
124
+ File.readlines(file_path)[line_number.to_i - 1]
125
125
  else
126
126
  "Unable to find #{file_path} to read failed line"
127
127
  end
@@ -15,7 +15,7 @@ module RSpec
15
15
  super(example_group)
16
16
 
17
17
  output.puts if @group_level == 0
18
- output.puts "#{' ' * @group_level}#{example_group.description}"
18
+ output.puts "#{current_indentation}#{example_group.description}"
19
19
 
20
20
  @group_level += 1
21
21
  end
@@ -48,9 +48,9 @@ module RSpec
48
48
  @output.puts " </dl>"
49
49
  @output.puts "</div>"
50
50
  end
51
- @output.puts "<div class=\"example_group\">"
51
+ @output.puts "<div id=\"div_group_#{example_group_number}\" class=\"example_group passed\">"
52
52
  @output.puts " <dl #{current_indentation}>"
53
- @output.puts " <dt id=\"example_group_#{example_group_number}\">#{h(example_group.description)}</dt>"
53
+ @output.puts " <dt id=\"example_group_#{example_group_number}\" class=\"passed\">#{h(example_group.description)}</dt>"
54
54
  @output.flush
55
55
  end
56
56
 
@@ -67,24 +67,24 @@ module RSpec
67
67
 
68
68
  def example_passed(example)
69
69
  move_progress
70
- @output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span></dd>"
70
+ @output.puts " <dd class=\"example passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span></dd>"
71
71
  @output.flush
72
72
  end
73
73
 
74
74
  def example_failed(example)
75
- counter = 0
75
+ super(example)
76
76
  exception = example.metadata[:execution_result][:exception]
77
77
  extra = extra_failure_content(exception)
78
- failure_style = 'failed'
79
78
  failure_style = RSpec::Core::PendingExampleFixedError === exception ? 'pending_fixed' : 'failed'
80
79
  @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red
81
80
  @header_red = true
81
+ @output.puts " <script type=\"text/javascript\">makeRed('div_group_#{example_group_number}');</script>" unless @example_group_red
82
82
  @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{example_group_number}');</script>" unless @example_group_red
83
83
  @example_group_red = true
84
84
  move_progress
85
- @output.puts " <dd class=\"spec #{failure_style}\">"
85
+ @output.puts " <dd class=\"example #{failure_style}\">"
86
86
  @output.puts " <span class=\"failed_spec_name\">#{h(example.description)}</span>"
87
- @output.puts " <div class=\"failure\" id=\"failure_#{counter}\">"
87
+ @output.puts " <div class=\"failure\" id=\"failure_#{@failed_examples.size}\">"
88
88
  @output.puts " <div class=\"message\"><pre>#{h(exception.message)}</pre></div>" unless exception.nil?
89
89
  @output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(exception.backtrace, example).join("\n")}</pre></div>" if exception
90
90
  @output.puts extra unless extra == ""
@@ -96,9 +96,10 @@ module RSpec
96
96
  def example_pending(example)
97
97
  message = example.metadata[:execution_result][:pending_message]
98
98
  @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red
99
+ @output.puts " <script type=\"text/javascript\">makeYellow('div_group_#{example_group_number}');</script>" unless @example_group_red
99
100
  @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{example_group_number}');</script>" unless @example_group_red
100
101
  move_progress
101
- @output.puts " <dd class=\"spec not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>"
102
+ @output.puts " <dd class=\"example not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>"
102
103
  @output.flush
103
104
  end
104
105
 
@@ -135,7 +136,8 @@ module RSpec
135
136
  if dry_run?
136
137
  totals = "This was a dry-run"
137
138
  else
138
- totals = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
139
+ totals = "#{example_count} example#{'s' unless example_count == 1}, "
140
+ totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
139
141
  totals << ", #{pending_count} pending" if pending_count > 0
140
142
  end
141
143
  @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
@@ -193,36 +195,97 @@ EOF
193
195
  <h1>RSpec Code Examples</h1>
194
196
  </div>
195
197
 
198
+ <div id="display-filters">
199
+ <input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked onchange="apply_filters()" value="1"> <label for="passed_checkbox">Passed</label>
200
+ <input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked onchange="apply_filters()" value="2"> <label for="failed_checkbox">Failed</label>
201
+ <input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked onchange="apply_filters()" value="3"> <label for="pending_checkbox">Pending</label>
202
+ </div>
203
+
196
204
  <div id="summary">
197
205
  <p id="totals">&nbsp;</p>
198
206
  <p id="duration">&nbsp;</p>
199
207
  </div>
200
208
  </div>
201
209
 
210
+
202
211
  <div class="results">
203
212
  EOF
204
213
  end
205
214
 
206
215
  def global_scripts
207
216
  <<-EOF
217
+
218
+ function addClass(element_id, classname) {
219
+ document.getElementById(element_id).className += (" " + classname);
220
+ }
221
+
222
+ function removeClass(element_id, classname) {
223
+ var elem = document.getElementById(element_id);
224
+ var classlist = elem.className.replace(classname,'');
225
+ elem.className = classlist;
226
+ }
227
+
208
228
  function moveProgressBar(percentDone) {
209
229
  document.getElementById("rspec-header").style.width = percentDone +"%";
210
230
  }
231
+
211
232
  function makeRed(element_id) {
212
- document.getElementById(element_id).style.background = '#C40D0D';
213
- document.getElementById(element_id).style.color = '#FFFFFF';
233
+ removeClass(element_id, 'passed');
234
+ removeClass(element_id, 'not_implemented');
235
+ addClass(element_id,'failed');
214
236
  }
215
237
 
216
238
  function makeYellow(element_id) {
217
- if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
218
- {
219
- document.getElementById(element_id).style.background = '#FAF834';
220
- document.getElementById(element_id).style.color = '#000000';
239
+ var elem = document.getElementById(element_id);
240
+ if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed
241
+ if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented
242
+ removeClass(element_id, 'passed');
243
+ addClass(element_id,'not_implemented');
244
+ }
245
+ }
246
+ }
247
+
248
+ function apply_filters() {
249
+ var passed_filter = document.getElementById('passed_checkbox').checked;
250
+ var failed_filter = document.getElementById('failed_checkbox').checked;
251
+ var pending_filter = document.getElementById('pending_checkbox').checked;
252
+
253
+ assign_display_style("example passed", passed_filter);
254
+ assign_display_style("example failed", failed_filter);
255
+ assign_display_style("example not_implemented", pending_filter);
256
+
257
+ assign_display_style_for_group("example_group passed", passed_filter);
258
+ assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter);
259
+ assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter);
260
+ }
261
+
262
+ function get_display_style(display_flag) {
263
+ var style_mode = 'none';
264
+ if (display_flag == true) {
265
+ style_mode = 'block';
221
266
  }
222
- else
223
- {
224
- document.getElementById(element_id).style.background = '#FAF834';
225
- document.getElementById(element_id).style.color = '#000000';
267
+ return style_mode;
268
+ }
269
+
270
+ function assign_display_style(classname, display_flag) {
271
+ var style_mode = get_display_style(display_flag);
272
+ var elems = document.getElementsByClassName(classname)
273
+ for (var i=0; i<elems.length;i++) {
274
+ elems[i].style.display = style_mode;
275
+ }
276
+ }
277
+
278
+ function assign_display_style_for_group(classname, display_flag, subgroup_flag) {
279
+ var display_style_mode = get_display_style(display_flag);
280
+ var subgroup_style_mode = get_display_style(subgroup_flag);
281
+ var elems = document.getElementsByClassName(classname)
282
+ for (var i=0; i<elems.length;i++) {
283
+ var style_mode = display_style_mode;
284
+ if ((display_flag != subgroup_flag) && (elems[i].getElementsByTagName('dt')[0].innerHTML.indexOf(", ") != -1)) {
285
+ elems[i].style.display = subgroup_style_mode;
286
+ } else {
287
+ elems[i].style.display = display_style_mode;
288
+ }
226
289
  }
227
290
  }
228
291
  EOF
@@ -242,13 +305,21 @@ EOF
242
305
  position: absolute;
243
306
  }
244
307
 
308
+ #label {
309
+ float:left;
310
+ }
311
+
312
+ #display-filters {
313
+ float:left;
314
+ padding: 28px 0 0 40%;
315
+ font-family: "Lucida Grande", Helvetica, sans-serif;
316
+ }
317
+
245
318
  #summary {
246
- margin: 0; padding: 5px 10px;
319
+ float:right;
320
+ padding: 5px 10px;
247
321
  font-family: "Lucida Grande", Helvetica, sans-serif;
248
322
  text-align: right;
249
- top: 0px;
250
- right: 0px;
251
- float:right;
252
323
  }
253
324
 
254
325
  #summary p {
@@ -281,30 +352,58 @@ dd {
281
352
  padding: 3px 3px 3px 18px;
282
353
  }
283
354
 
284
- dd.spec.passed {
355
+
356
+ dd.example.passed {
285
357
  border-left: 5px solid #65C400;
286
358
  border-bottom: 1px solid #65C400;
287
359
  background: #DBFFB4; color: #3D7700;
288
360
  }
289
361
 
290
- dd.spec.failed {
291
- border-left: 5px solid #C20000;
292
- border-bottom: 1px solid #C20000;
293
- color: #C20000; background: #FFFBD3;
294
- }
295
-
296
- dd.spec.not_implemented {
362
+ dd.example.not_implemented {
297
363
  border-left: 5px solid #FAF834;
298
364
  border-bottom: 1px solid #FAF834;
299
365
  background: #FCFB98; color: #131313;
300
366
  }
301
367
 
302
- dd.spec.pending_fixed {
368
+ dd.example.pending_fixed {
303
369
  border-left: 5px solid #0000C2;
304
370
  border-bottom: 1px solid #0000C2;
305
371
  color: #0000C2; background: #D3FBFF;
306
372
  }
307
373
 
374
+ dd.example.failed {
375
+ border-left: 5px solid #C20000;
376
+ border-bottom: 1px solid #C20000;
377
+ color: #C20000; background: #FFFBD3;
378
+ }
379
+
380
+
381
+ dt.not_implemented {
382
+ color: #000000; background: #FAF834;
383
+ }
384
+
385
+ dt.pending_fixed {
386
+ color: #FFFFFF; background: #C40D0D;
387
+ }
388
+
389
+ dt.failed {
390
+ color: #FFFFFF; background: #C40D0D;
391
+ }
392
+
393
+
394
+ #rspec-header.not_implemented {
395
+ color: #000000; background: #FAF834;
396
+ }
397
+
398
+ #rspec-header.pending_fixed {
399
+ color: #FFFFFF; background: #C40D0D;
400
+ }
401
+
402
+ #rspec-header.failed {
403
+ color: #FFFFFF; background: #C40D0D;
404
+ }
405
+
406
+
308
407
  .backtrace {
309
408
  color: #000;
310
409
  font-size: 12px;
@@ -25,7 +25,7 @@ module RSpec
25
25
 
26
26
  def lines_around(file, line)
27
27
  if File.file?(file)
28
- lines = File.open(file).read.split("\n")
28
+ lines = File.read(file).split("\n")
29
29
  min = [0, line-3].max
30
30
  max = [line+1, lines.length-1].min
31
31
  selected_lines = []
@@ -53,6 +53,10 @@ module RSpec
53
53
  def find_hooks_for(example_or_group)
54
54
  self.class.new(select {|hook| hook.options_apply?(example_or_group)})
55
55
  end
56
+
57
+ def without_hooks_for(example_or_group)
58
+ self.class.new(reject {|hook| hook.options_apply?(example_or_group)})
59
+ end
56
60
  end
57
61
 
58
62
  class BeforeHooks < HookCollection
@@ -117,7 +121,18 @@ module RSpec
117
121
  end
118
122
 
119
123
  def find_hook(hook, scope, example_group_class, example = nil)
120
- hooks[hook][scope].find_hooks_for(example || example_group_class)
124
+ found_hooks = hooks[hook][scope].find_hooks_for(example || example_group_class)
125
+
126
+ # ensure we don't re-run :all hooks that were applied to any of the parent groups
127
+ if scope == :all
128
+ super_klass = example_group_class.superclass
129
+ while super_klass != RSpec::Core::ExampleGroup
130
+ found_hooks = found_hooks.without_hooks_for(super_klass)
131
+ super_klass = super_klass.superclass
132
+ end
133
+ end
134
+
135
+ found_hooks
121
136
  end
122
137
 
123
138
  private
@@ -23,7 +23,7 @@ module RSpec::Core
23
23
 
24
24
  def parser(options)
25
25
  OptionParser.new do |parser|
26
- parser.banner = "Usage: rspec [options] [files or directories]"
26
+ parser.banner = "Usage: rspec [options] [files or directories]\n\n"
27
27
 
28
28
  parser.on('-b', '--backtrace', 'Enable full backtrace') do |o|
29
29
  options[:full_backtrace] = true
@@ -106,11 +106,7 @@ module RSpec::Core
106
106
  options[:drb_port] = o.to_i
107
107
  end
108
108
 
109
- parser.on('--tty') do |o|
110
- options[:tty] = true
111
- end
112
-
113
- parser.on('--fail-fast', 'Use the fail_fast option to tell RSpec to abort the run on first failure.') do |o|
109
+ parser.on('--fail-fast', 'Abort the run on first failure.') do |o|
114
110
  options[:fail_fast] = true
115
111
  end
116
112
 
@@ -126,6 +122,10 @@ module RSpec::Core
126
122
  options[filter_type] ||= {}
127
123
  options[filter_type][name] = value
128
124
  end
125
+
126
+ parser.on('--tty', 'Used internally by rspec when sending commands to other processes') do |o|
127
+ options[:tty] = true
128
+ end
129
129
  end
130
130
  end
131
131
  end
@@ -161,7 +161,7 @@ module RSpec
161
161
  cmd_parts << "bundle exec" if gemfile? unless skip_bundler
162
162
  cmd_parts << runner
163
163
  if rcov
164
- cmd_parts << ["-Ispec:lib", rcov_opts]
164
+ cmd_parts << ["-Ispec#{File::PATH_SEPARATOR}lib", rcov_opts]
165
165
  else
166
166
  cmd_parts << rspec_opts
167
167
  end
@@ -124,13 +124,13 @@ module RSpec
124
124
  example do
125
125
  self.class.class_eval do
126
126
  define_method(:subject) do
127
- if super().is_a?(Hash) && attribute.is_a?(Array)
128
- OpenStruct.new(super()).send(attribute.first)
129
- else
130
- attribute.to_s.split('.').inject(super()) do |target, method|
131
- target.send(method)
132
- end
133
- end
127
+ @_subject ||= if super().is_a?(Hash) && attribute.is_a?(Array)
128
+ OpenStruct.new(super()).send(attribute.first)
129
+ else
130
+ attribute.to_s.split('.').inject(super()) do |target, method|
131
+ target.send(method)
132
+ end
133
+ end
134
134
  end
135
135
  end
136
136
  instance_eval(&block)
@@ -1,7 +1,7 @@
1
1
  module RSpec # :nodoc:
2
2
  module Core # :nodoc:
3
3
  module Version # :nodoc:
4
- STRING = '2.4.0'
4
+ STRING = '2.5.0'
5
5
  end
6
6
  end
7
7
  end
@@ -22,17 +22,5 @@ Gem::Specification.new do |s|
22
22
  s.extra_rdoc_files = [ "README.md" ]
23
23
  s.rdoc_options = ["--charset=UTF-8"]
24
24
  s.require_path = "lib"
25
-
26
- s.post_install_message = %Q{**************************************************
27
-
28
- Thank you for installing #{s.summary}
29
-
30
- Please be sure to look at the upgrade instructions to see what might have
31
- changed since the last release:
32
-
33
- http://github.com/rspec/rspec-core/blob/master/Upgrade.markdown
34
-
35
- **************************************************
36
- }
37
25
  end
38
26