rspec-core 2.11.1 → 2.12.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 (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