rspec-core 2.11.1 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/Changelog.md +59 -0
  2. data/README.md +22 -0
  3. data/features/command_line/example_name_option.feature +5 -5
  4. data/features/command_line/exit_status.feature +6 -6
  5. data/features/command_line/format_option.feature +2 -2
  6. data/features/command_line/line_number_appended_to_path.feature +2 -2
  7. data/features/command_line/line_number_option.feature +2 -2
  8. data/features/command_line/pattern_option.feature +2 -2
  9. data/features/command_line/rake_task.feature +62 -8
  10. data/features/command_line/ruby.feature +1 -1
  11. data/features/command_line/tag.feature +1 -1
  12. data/features/configuration/alias_example_to.feature +2 -2
  13. data/features/configuration/custom_settings.feature +3 -3
  14. data/features/configuration/default_path.feature +3 -3
  15. data/features/configuration/fail_fast.feature +5 -5
  16. data/features/configuration/read_options_from_file.feature +4 -4
  17. data/features/example_groups/basic_structure.feature +2 -2
  18. data/features/example_groups/shared_context.feature +3 -3
  19. data/features/example_groups/shared_examples.feature +25 -7
  20. data/features/expectation_framework_integration/configure_expectation_framework.feature +6 -6
  21. data/features/filtering/exclusion_filters.feature +5 -5
  22. data/features/filtering/if_and_unless.feature +5 -5
  23. data/features/filtering/inclusion_filters.feature +5 -5
  24. data/features/filtering/run_all_when_everything_filtered.feature +3 -3
  25. data/features/formatters/custom_formatter.feature +2 -2
  26. data/features/formatters/json_formatter.feature +30 -0
  27. data/features/formatters/text_formatter.feature +5 -5
  28. data/features/helper_methods/arbitrary_methods.feature +2 -2
  29. data/features/helper_methods/let.feature +2 -2
  30. data/features/helper_methods/modules.feature +6 -6
  31. data/features/hooks/around_hooks.feature +11 -11
  32. data/features/hooks/before_and_after_hooks.feature +15 -11
  33. data/features/hooks/filtering.feature +6 -6
  34. data/features/metadata/current_example.feature +1 -1
  35. data/features/metadata/described_class.feature +1 -1
  36. data/features/metadata/user_defined.feature +4 -4
  37. data/features/mock_framework_integration/use_any_framework.feature +6 -6
  38. data/features/mock_framework_integration/use_flexmock.feature +5 -5
  39. data/features/mock_framework_integration/use_mocha.feature +5 -5
  40. data/features/mock_framework_integration/use_rr.feature +5 -5
  41. data/features/mock_framework_integration/use_rspec.feature +5 -5
  42. data/features/pending/pending_examples.feature +11 -11
  43. data/features/spec_files/arbitrary_file_suffix.feature +1 -1
  44. data/features/step_definitions/additional_cli_steps.rb +2 -0
  45. data/features/subject/attribute_of_subject.feature +5 -5
  46. data/features/subject/explicit_subject.feature +5 -5
  47. data/features/subject/implicit_receiver.feature +2 -2
  48. data/features/subject/implicit_subject.feature +3 -3
  49. data/lib/autotest/rspec2.rb +1 -1
  50. data/lib/rspec/core.rb +53 -32
  51. data/lib/rspec/core/configuration.rb +123 -15
  52. data/lib/rspec/core/configuration_options.rb +17 -2
  53. data/lib/rspec/core/example.rb +5 -4
  54. data/lib/rspec/core/example_group.rb +19 -9
  55. data/lib/rspec/core/extensions/ordered.rb +12 -6
  56. data/lib/rspec/core/formatters.rb +55 -0
  57. data/lib/rspec/core/formatters/base_formatter.rb +43 -38
  58. data/lib/rspec/core/formatters/base_text_formatter.rb +9 -5
  59. data/lib/rspec/core/formatters/documentation_formatter.rb +1 -1
  60. data/lib/rspec/core/formatters/helpers.rb +30 -5
  61. data/lib/rspec/core/formatters/html_formatter.rb +58 -368
  62. data/lib/rspec/core/formatters/html_printer.rb +407 -0
  63. data/lib/rspec/core/formatters/json_formatter.rb +73 -0
  64. data/lib/rspec/core/formatters/snippet_extractor.rb +3 -1
  65. data/lib/rspec/core/hooks.rb +4 -4
  66. data/lib/rspec/core/metadata.rb +14 -6
  67. data/lib/rspec/core/mocking/with_mocha.rb +25 -2
  68. data/lib/rspec/core/mocking/with_rspec.rb +6 -2
  69. data/lib/rspec/core/option_parser.rb +28 -7
  70. data/lib/rspec/core/project_initializer.rb +0 -1
  71. data/lib/rspec/core/rake_task.rb +49 -38
  72. data/lib/rspec/core/reporter.rb +2 -2
  73. data/lib/rspec/core/shared_example_group.rb +89 -41
  74. data/lib/rspec/core/subject.rb +6 -2
  75. data/lib/rspec/core/version.rb +1 -1
  76. data/lib/rspec/core/world.rb +2 -2
  77. data/spec/autotest/rspec_spec.rb +6 -1
  78. data/spec/command_line/order_spec.rb +67 -0
  79. data/spec/rspec/core/configuration_options_spec.rb +45 -38
  80. data/spec/rspec/core/configuration_spec.rb +219 -44
  81. data/spec/rspec/core/deprecations_spec.rb +9 -0
  82. data/spec/rspec/core/drb_command_line_spec.rb +1 -7
  83. data/spec/rspec/core/drb_options_spec.rb +1 -1
  84. data/spec/rspec/core/dsl_spec.rb +17 -9
  85. data/spec/rspec/core/example_group_spec.rb +51 -5
  86. data/spec/rspec/core/example_spec.rb +39 -7
  87. data/spec/rspec/core/filter_manager_spec.rb +20 -30
  88. data/spec/rspec/core/formatters/base_formatter_spec.rb +29 -1
  89. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +6 -2
  90. data/spec/rspec/core/formatters/helpers_spec.rb +12 -0
  91. data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +462 -0
  92. data/spec/rspec/core/formatters/html_formatted-1.9.2-jruby.html +410 -0
  93. data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +462 -0
  94. data/spec/rspec/core/formatters/html_formatter_spec.rb +11 -3
  95. data/spec/rspec/core/formatters/json_formatter_spec.rb +110 -0
  96. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +8 -0
  97. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-rbx.html +462 -0
  98. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2-jruby.html +410 -0
  99. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-rbx.html +462 -0
  100. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +11 -3
  101. data/spec/rspec/core/hooks_filtering_spec.rb +6 -6
  102. data/spec/rspec/core/metadata_spec.rb +29 -0
  103. data/spec/rspec/core/option_parser_spec.rb +42 -0
  104. data/spec/rspec/core/project_initializer_spec.rb +2 -2
  105. data/spec/rspec/core/rake_task_spec.rb +60 -17
  106. data/spec/rspec/core/reporter_spec.rb +17 -0
  107. data/spec/rspec/core/runner_spec.rb +1 -0
  108. data/spec/rspec/core/shared_example_group_spec.rb +17 -5
  109. data/spec/rspec/core/subject_spec.rb +11 -0
  110. data/spec/spec_helper.rb +32 -2
  111. data/spec/support/config_options_helper.rb +1 -10
  112. data/spec/support/helper_methods.rb +13 -0
  113. data/spec/support/isolated_directory.rb +10 -0
  114. data/spec/support/isolated_home_directory.rb +16 -0
  115. metadata +145 -148
  116. data/lib/rspec/core/extensions.rb +0 -4
@@ -0,0 +1,407 @@
1
+ require 'erb'
2
+
3
+ module RSpec
4
+ module Core
5
+ module Formatters
6
+ class HtmlPrinter
7
+ include ERB::Util # for the #h method
8
+ def initialize(output)
9
+ @output = output
10
+ end
11
+
12
+ def print_html_start
13
+ @output.puts HTML_HEADER
14
+ @output.puts REPORT_HEADER
15
+ end
16
+
17
+ def print_example_group_end
18
+ @output.puts " </dl>"
19
+ @output.puts "</div>"
20
+ end
21
+
22
+ def print_example_group_start( group_id, description, number_of_parents )
23
+ @output.puts "<div id=\"div_group_#{group_id}\" class=\"example_group passed\">"
24
+ @output.puts " <dl #{indentation_style(number_of_parents)}>"
25
+ @output.puts " <dt id=\"example_group_#{group_id}\" class=\"passed\">#{h(description)}</dt>"
26
+ end
27
+
28
+ def print_example_passed( description, run_time )
29
+ formatted_run_time = sprintf("%.5f", run_time)
30
+ @output.puts " <dd class=\"example passed\"><span class=\"passed_spec_name\">#{h(description)}</span><span class='duration'>#{formatted_run_time}s</span></dd>"
31
+ end
32
+
33
+ def print_example_failed( pending_fixed, description, run_time, failure_id, exception, extra_content )
34
+ formatted_run_time = sprintf("%.5f", run_time)
35
+
36
+ @output.puts " <dd class=\"example #{pending_fixed ? 'pending_fixed' : 'failed'}\">"
37
+ @output.puts " <span class=\"failed_spec_name\">#{h(description)}</span>"
38
+ @output.puts " <span class=\"duration\">#{formatted_run_time}s</span>"
39
+ @output.puts " <div class=\"failure\" id=\"failure_#{failure_id}\">"
40
+ if exception
41
+ @output.puts " <div class=\"message\"><pre>#{h(exception[:message])}</pre></div>"
42
+ @output.puts " <div class=\"backtrace\"><pre>#{exception[:backtrace]}</pre></div>"
43
+ end
44
+ @output.puts extra_content if extra_content
45
+ @output.puts " </div>"
46
+ @output.puts " </dd>"
47
+ end
48
+
49
+ def print_example_pending( description, pending_message )
50
+ @output.puts " <dd class=\"example not_implemented\"><span class=\"not_implemented_spec_name\">#{h(description)} (PENDING: #{h(pending_message)})</span></dd>"
51
+ end
52
+
53
+ def print_summary( was_dry_run, duration, example_count, failure_count, pending_count )
54
+ # TODO - kill dry_run?
55
+ if was_dry_run
56
+ totals = "This was a dry-run"
57
+ else
58
+ totals = "#{example_count} example#{'s' unless example_count == 1}, "
59
+ totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
60
+ totals << ", #{pending_count} pending" if pending_count > 0
61
+ end
62
+
63
+ formatted_duration = sprintf("%.5f", duration)
64
+
65
+ @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{formatted_duration} seconds</strong>\";</script>"
66
+ @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
67
+ @output.puts "</div>"
68
+ @output.puts "</div>"
69
+ @output.puts "</body>"
70
+ @output.puts "</html>"
71
+ end
72
+
73
+ def flush
74
+ @output.flush
75
+ end
76
+
77
+ def move_progress( percent_done )
78
+ @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
79
+ @output.flush
80
+ end
81
+
82
+ def make_header_red
83
+ @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>"
84
+ end
85
+
86
+ def make_header_yellow
87
+ @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>"
88
+ end
89
+
90
+ def make_example_group_header_red(group_id)
91
+ @output.puts " <script type=\"text/javascript\">makeRed('div_group_#{group_id}');</script>"
92
+ @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{group_id}');</script>"
93
+ end
94
+
95
+ def make_example_group_header_yellow(group_id)
96
+ @output.puts " <script type=\"text/javascript\">makeYellow('div_group_#{group_id}');</script>"
97
+ @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{group_id}');</script>"
98
+ end
99
+
100
+
101
+ private
102
+
103
+ def indentation_style( number_of_parents )
104
+ "style=\"margin-left: #{(number_of_parents - 1) * 15}px;\""
105
+ end
106
+
107
+
108
+ REPORT_HEADER = <<-EOF
109
+ <div class="rspec-report">
110
+
111
+ <div id="rspec-header">
112
+ <div id="label">
113
+ <h1>RSpec Code Examples</h1>
114
+ </div>
115
+
116
+ <div id="display-filters">
117
+ <input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked onchange="apply_filters()" value="1"> <label for="passed_checkbox">Passed</label>
118
+ <input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked onchange="apply_filters()" value="2"> <label for="failed_checkbox">Failed</label>
119
+ <input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked onchange="apply_filters()" value="3"> <label for="pending_checkbox">Pending</label>
120
+ </div>
121
+
122
+ <div id="summary">
123
+ <p id="totals">&nbsp;</p>
124
+ <p id="duration">&nbsp;</p>
125
+ </div>
126
+ </div>
127
+
128
+
129
+ <div class="results">
130
+ EOF
131
+
132
+ GLOBAL_SCRIPTS = <<-EOF
133
+
134
+ function addClass(element_id, classname) {
135
+ document.getElementById(element_id).className += (" " + classname);
136
+ }
137
+
138
+ function removeClass(element_id, classname) {
139
+ var elem = document.getElementById(element_id);
140
+ var classlist = elem.className.replace(classname,'');
141
+ elem.className = classlist;
142
+ }
143
+
144
+ function moveProgressBar(percentDone) {
145
+ document.getElementById("rspec-header").style.width = percentDone +"%";
146
+ }
147
+
148
+ function makeRed(element_id) {
149
+ removeClass(element_id, 'passed');
150
+ removeClass(element_id, 'not_implemented');
151
+ addClass(element_id,'failed');
152
+ }
153
+
154
+ function makeYellow(element_id) {
155
+ var elem = document.getElementById(element_id);
156
+ if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed
157
+ if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented
158
+ removeClass(element_id, 'passed');
159
+ addClass(element_id,'not_implemented');
160
+ }
161
+ }
162
+ }
163
+
164
+ function apply_filters() {
165
+ var passed_filter = document.getElementById('passed_checkbox').checked;
166
+ var failed_filter = document.getElementById('failed_checkbox').checked;
167
+ var pending_filter = document.getElementById('pending_checkbox').checked;
168
+
169
+ assign_display_style("example passed", passed_filter);
170
+ assign_display_style("example failed", failed_filter);
171
+ assign_display_style("example not_implemented", pending_filter);
172
+
173
+ assign_display_style_for_group("example_group passed", passed_filter);
174
+ assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter);
175
+ assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter);
176
+ }
177
+
178
+ function get_display_style(display_flag) {
179
+ var style_mode = 'none';
180
+ if (display_flag == true) {
181
+ style_mode = 'block';
182
+ }
183
+ return style_mode;
184
+ }
185
+
186
+ function assign_display_style(classname, display_flag) {
187
+ var style_mode = get_display_style(display_flag);
188
+ var elems = document.getElementsByClassName(classname)
189
+ for (var i=0; i<elems.length;i++) {
190
+ elems[i].style.display = style_mode;
191
+ }
192
+ }
193
+
194
+ function assign_display_style_for_group(classname, display_flag, subgroup_flag) {
195
+ var display_style_mode = get_display_style(display_flag);
196
+ var subgroup_style_mode = get_display_style(subgroup_flag);
197
+ var elems = document.getElementsByClassName(classname)
198
+ for (var i=0; i<elems.length;i++) {
199
+ var style_mode = display_style_mode;
200
+ if ((display_flag != subgroup_flag) && (elems[i].getElementsByTagName('dt')[0].innerHTML.indexOf(", ") != -1)) {
201
+ elems[i].style.display = subgroup_style_mode;
202
+ } else {
203
+ elems[i].style.display = display_style_mode;
204
+ }
205
+ }
206
+ }
207
+ EOF
208
+
209
+ GLOBAL_STYLES = <<-EOF
210
+ #rspec-header {
211
+ background: #65C400; color: #fff; height: 4em;
212
+ }
213
+
214
+ .rspec-report h1 {
215
+ margin: 0px 10px 0px 10px;
216
+ padding: 10px;
217
+ font-family: "Lucida Grande", Helvetica, sans-serif;
218
+ font-size: 1.8em;
219
+ position: absolute;
220
+ }
221
+
222
+ #label {
223
+ float:left;
224
+ }
225
+
226
+ #display-filters {
227
+ float:left;
228
+ padding: 28px 0 0 40%;
229
+ font-family: "Lucida Grande", Helvetica, sans-serif;
230
+ }
231
+
232
+ #summary {
233
+ float:right;
234
+ padding: 5px 10px;
235
+ font-family: "Lucida Grande", Helvetica, sans-serif;
236
+ text-align: right;
237
+ }
238
+
239
+ #summary p {
240
+ margin: 0 0 0 2px;
241
+ }
242
+
243
+ #summary #totals {
244
+ font-size: 1.2em;
245
+ }
246
+
247
+ .example_group {
248
+ margin: 0 10px 5px;
249
+ background: #fff;
250
+ }
251
+
252
+ dl {
253
+ margin: 0; padding: 0 0 5px;
254
+ font: normal 11px "Lucida Grande", Helvetica, sans-serif;
255
+ }
256
+
257
+ dt {
258
+ padding: 3px;
259
+ background: #65C400;
260
+ color: #fff;
261
+ font-weight: bold;
262
+ }
263
+
264
+ dd {
265
+ margin: 5px 0 5px 5px;
266
+ padding: 3px 3px 3px 18px;
267
+ }
268
+
269
+ dd .duration {
270
+ padding-left: 5px;
271
+ text-align: right;
272
+ right: 0px;
273
+ float:right;
274
+ }
275
+
276
+ dd.example.passed {
277
+ border-left: 5px solid #65C400;
278
+ border-bottom: 1px solid #65C400;
279
+ background: #DBFFB4; color: #3D7700;
280
+ }
281
+
282
+ dd.example.not_implemented {
283
+ border-left: 5px solid #FAF834;
284
+ border-bottom: 1px solid #FAF834;
285
+ background: #FCFB98; color: #131313;
286
+ }
287
+
288
+ dd.example.pending_fixed {
289
+ border-left: 5px solid #0000C2;
290
+ border-bottom: 1px solid #0000C2;
291
+ color: #0000C2; background: #D3FBFF;
292
+ }
293
+
294
+ dd.example.failed {
295
+ border-left: 5px solid #C20000;
296
+ border-bottom: 1px solid #C20000;
297
+ color: #C20000; background: #FFFBD3;
298
+ }
299
+
300
+
301
+ dt.not_implemented {
302
+ color: #000000; background: #FAF834;
303
+ }
304
+
305
+ dt.pending_fixed {
306
+ color: #FFFFFF; background: #C40D0D;
307
+ }
308
+
309
+ dt.failed {
310
+ color: #FFFFFF; background: #C40D0D;
311
+ }
312
+
313
+
314
+ #rspec-header.not_implemented {
315
+ color: #000000; background: #FAF834;
316
+ }
317
+
318
+ #rspec-header.pending_fixed {
319
+ color: #FFFFFF; background: #C40D0D;
320
+ }
321
+
322
+ #rspec-header.failed {
323
+ color: #FFFFFF; background: #C40D0D;
324
+ }
325
+
326
+
327
+ .backtrace {
328
+ color: #000;
329
+ font-size: 12px;
330
+ }
331
+
332
+ a {
333
+ color: #BE5C00;
334
+ }
335
+
336
+ /* Ruby code, style similar to vibrant ink */
337
+ .ruby {
338
+ font-size: 12px;
339
+ font-family: monospace;
340
+ color: white;
341
+ background-color: black;
342
+ padding: 0.1em 0 0.2em 0;
343
+ }
344
+
345
+ .ruby .keyword { color: #FF6600; }
346
+ .ruby .constant { color: #339999; }
347
+ .ruby .attribute { color: white; }
348
+ .ruby .global { color: white; }
349
+ .ruby .module { color: white; }
350
+ .ruby .class { color: white; }
351
+ .ruby .string { color: #66FF00; }
352
+ .ruby .ident { color: white; }
353
+ .ruby .method { color: #FFCC00; }
354
+ .ruby .number { color: white; }
355
+ .ruby .char { color: white; }
356
+ .ruby .comment { color: #9933CC; }
357
+ .ruby .symbol { color: white; }
358
+ .ruby .regex { color: #44B4CC; }
359
+ .ruby .punct { color: white; }
360
+ .ruby .escape { color: white; }
361
+ .ruby .interp { color: white; }
362
+ .ruby .expr { color: white; }
363
+
364
+ .ruby .offending { background-color: gray; }
365
+ .ruby .linenum {
366
+ width: 75px;
367
+ padding: 0.1em 1em 0.2em 0;
368
+ color: #000000;
369
+ background-color: #FFFBD3;
370
+ }
371
+ EOF
372
+
373
+ HTML_HEADER = <<-EOF
374
+ <?xml version="1.0" encoding="UTF-8"?>
375
+ <!DOCTYPE html
376
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
377
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
378
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
379
+ <head>
380
+ <title>RSpec results</title>
381
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
382
+ <meta http-equiv="Expires" content="-1" />
383
+ <meta http-equiv="Pragma" content="no-cache" />
384
+ <style type="text/css">
385
+ body {
386
+ margin: 0;
387
+ padding: 0;
388
+ background: #fff;
389
+ font-size: 80%;
390
+ }
391
+ </style>
392
+ <script type="text/javascript">
393
+ // <![CDATA[
394
+ #{GLOBAL_SCRIPTS}
395
+ // ]]>
396
+ </script>
397
+ <style type="text/css">
398
+ #{GLOBAL_STYLES}
399
+ </style>
400
+ </head>
401
+ <body>
402
+ EOF
403
+
404
+ end
405
+ end
406
+ end
407
+ end
@@ -0,0 +1,73 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+ require 'json'
3
+
4
+ module RSpec
5
+ module Core
6
+ module Formatters
7
+
8
+ class JsonFormatter < BaseFormatter
9
+
10
+ attr_reader :output_hash
11
+
12
+ def initialize(output)
13
+ super
14
+ @output_hash = {}
15
+ end
16
+
17
+ def message(message)
18
+ (@output_hash[:messages] ||= []) << message
19
+ end
20
+
21
+ def dump_summary(duration, example_count, failure_count, pending_count)
22
+ super(duration, example_count, failure_count, pending_count)
23
+ @output_hash[:summary] = {
24
+ :duration => duration,
25
+ :example_count => example_count,
26
+ :failure_count => failure_count,
27
+ :pending_count => pending_count
28
+ }
29
+ @output_hash[:summary_line] = summary_line(example_count, failure_count, pending_count)
30
+
31
+ # Don't print out profiled info if there are failures, it just clutters the output
32
+ dump_profile if profile_examples? && failure_count == 0
33
+ end
34
+
35
+ def summary_line(example_count, failure_count, pending_count)
36
+ summary = pluralize(example_count, "example")
37
+ summary << ", " << pluralize(failure_count, "failure")
38
+ summary << ", #{pending_count} pending" if pending_count > 0
39
+ summary
40
+ end
41
+
42
+ def stop
43
+ super
44
+ @output_hash[:examples] = examples.map do |example|
45
+ {
46
+ :description => example.description,
47
+ :full_description => example.full_description,
48
+ :status => example.execution_result[:status],
49
+ # :example_group,
50
+ # :execution_result,
51
+ :file_path => example.metadata[:file_path],
52
+ :line_number => example.metadata[:line_number],
53
+ }.tap do |hash|
54
+ if e=example.exception
55
+ hash[:exception] = {
56
+ :class => e.class.name,
57
+ :message => e.message,
58
+ :backtrace => e.backtrace,
59
+ }
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def close
66
+ output.write @output_hash.to_json
67
+ output.close if IO === output && output != $stdout
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end