minitap 0.1.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.
- data/.ruby +39 -0
- data/COPYING.rdoc +59 -0
- data/HISTORY.rdoc +10 -0
- data/README.rdoc +46 -0
- data/lib/minitap.rb +534 -0
- data/lib/minitest/tapj.rb +4 -0
- data/lib/minitest/tapy.rb +3 -0
- metadata +89 -0
data/.ruby
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
---
|
2
|
+
authors:
|
3
|
+
- name: Thomas Sawyer
|
4
|
+
email: transfire@gmail.com
|
5
|
+
copyrights:
|
6
|
+
- holder: Thomas Sawyer
|
7
|
+
year: '2011'
|
8
|
+
license: BSD-2-Clause
|
9
|
+
replacements: []
|
10
|
+
conflicts: []
|
11
|
+
requirements:
|
12
|
+
- name: tapout
|
13
|
+
- name: detroit
|
14
|
+
groups:
|
15
|
+
- build
|
16
|
+
development: true
|
17
|
+
- name: reap
|
18
|
+
groups:
|
19
|
+
- build
|
20
|
+
development: true
|
21
|
+
dependencies: []
|
22
|
+
repositories: []
|
23
|
+
resources:
|
24
|
+
home: http://rubyworks.github.com/minitap
|
25
|
+
code: http://github.com/rubyworks/minitap
|
26
|
+
load_path:
|
27
|
+
- lib
|
28
|
+
extra: {}
|
29
|
+
name: minitap
|
30
|
+
title: TAP-Y/J for MiniTest
|
31
|
+
date: '2011-10-06'
|
32
|
+
alternatives: []
|
33
|
+
version: 0.1.0
|
34
|
+
revision: 0
|
35
|
+
source:
|
36
|
+
- ruby.yml
|
37
|
+
summary: MiniTest TAP-Y/J reporter
|
38
|
+
description: MiniTap provides a custom MiniTest reporter that outs TAP-Y or TAP-J
|
39
|
+
formatted output.
|
data/COPYING.rdoc
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
= COPYRIGHT NOTICES
|
2
|
+
|
3
|
+
== MiniTap
|
4
|
+
|
5
|
+
Copyright:: (c) 2010 Thomas Sawyer, Rubyworks
|
6
|
+
License:: BSD-2-Clause
|
7
|
+
Website:: http://rubyworks.github.com/tapout
|
8
|
+
|
9
|
+
Copyright 2011 Thomas Sawyer. All rights reserved.
|
10
|
+
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
12
|
+
modification, are permitted provided that the following conditions are met:
|
13
|
+
|
14
|
+
1. Redistributions of source code must retain the above copyright notice,
|
15
|
+
this list of conditions and the following disclaimer.
|
16
|
+
|
17
|
+
2. Redistributions in binary form must reproduce the above copyright
|
18
|
+
notice, this list of conditions and the following disclaimer in the
|
19
|
+
documentation and/or other materials provided with the distribution.
|
20
|
+
|
21
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
22
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
23
|
+
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
24
|
+
COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
25
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
26
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
27
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
28
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
29
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
30
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
|
32
|
+
|
33
|
+
== MiniTest Reporter
|
34
|
+
|
35
|
+
Copyright:: (c) 2011 Alexander Kern
|
36
|
+
License:: MIT
|
37
|
+
Website:: https://github.com/CapnKernul/minitest-reporters
|
38
|
+
|
39
|
+
Copyright (c) 2011 Alexander Kern
|
40
|
+
|
41
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
42
|
+
a copy of this software and associated documentation files (the
|
43
|
+
"Software"), to deal in the Software without restriction, including
|
44
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
45
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
46
|
+
permit persons to whom the Software is furnished to do so, subject to
|
47
|
+
the following conditions:
|
48
|
+
|
49
|
+
The above copyright notice and this permission notice shall be
|
50
|
+
included in all copies or substantial portions of the Software.
|
51
|
+
|
52
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
53
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
54
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
55
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
56
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
57
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
58
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
59
|
+
|
data/HISTORY.rdoc
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
= MiniTap
|
2
|
+
|
3
|
+
{Website}[http://rubyworks.github.com/minitap]
|
4
|
+
{Development}[http://github.com/rubyworks/minitap]
|
5
|
+
|
6
|
+
|
7
|
+
== Description
|
8
|
+
|
9
|
+
The MiniTap project provides a TAP-Y and TAP-J output reporters for
|
10
|
+
the MiniTest test framework --the test framework that comes standard
|
11
|
+
with Ruby 1.9+.
|
12
|
+
|
13
|
+
See {TAPOUT}[http://rubyworks.github.com/tapout] for more information about
|
14
|
+
TAP-Y/J formats.
|
15
|
+
|
16
|
+
|
17
|
+
== Usage
|
18
|
+
|
19
|
+
Simply require `minitest/tapy` or `minitest/tapj' when running your tests.
|
20
|
+
For example if you use `ruby` on the command line:
|
21
|
+
|
22
|
+
ruby -r'minitest/tapy' test_some_test.rb
|
23
|
+
|
24
|
+
Now to do something intersing with the outout. Make sure `tapout` is installed:
|
25
|
+
|
26
|
+
$ gem install tapout
|
27
|
+
|
28
|
+
Then pipe the output to the `tapout` command.
|
29
|
+
|
30
|
+
$ ruby -r'minitest/tapy' test/some_test.rb | tapout progressbar
|
31
|
+
|
32
|
+
Adjust your Rake task or other means of running tests to suite.
|
33
|
+
|
34
|
+
|
35
|
+
== Copying
|
36
|
+
|
37
|
+
Copyright (c) 2011 Thomas Sawyer
|
38
|
+
|
39
|
+
Made available under the terms of the BSD-2-Clause license.
|
40
|
+
|
41
|
+
Portions of this program were drawn from Alexander Kern's
|
42
|
+
MiniTest Reporter (c) 2011 Alexander Kern. Thanks Alexander
|
43
|
+
for making my endeavor a little bit easier.
|
44
|
+
|
45
|
+
See COPYING.rdoc for copyright and licensing details.
|
46
|
+
|
data/lib/minitap.rb
ADDED
@@ -0,0 +1,534 @@
|
|
1
|
+
# MiniTest adaptor for tapout.
|
2
|
+
|
3
|
+
require 'minitest/unit'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
# Becuase of some wierdness in MiniTest
|
7
|
+
#debug, $DEBUG = $DEBUG, false
|
8
|
+
#require 'minitest/unit'
|
9
|
+
#$DEBUG = debug
|
10
|
+
|
11
|
+
module MiniTest
|
12
|
+
|
13
|
+
# Base class for TapY and TapJ runners.
|
14
|
+
#
|
15
|
+
# This is a heavily refactored version of the built-in MiniTest runner. It's
|
16
|
+
# about the same speed, from what I can tell, but is significantly easier to
|
17
|
+
# extend.
|
18
|
+
#
|
19
|
+
# Based upon Ryan Davis of Seattle.rb's MiniTest (MIT License).
|
20
|
+
#
|
21
|
+
# @see https://github.com/seattlerb/minitest MiniTest
|
22
|
+
#
|
23
|
+
class MiniTap < ::MiniTest::Unit
|
24
|
+
|
25
|
+
# TAP-Y/J Revision
|
26
|
+
REVISION = 2
|
27
|
+
|
28
|
+
attr_accessor :suite_start_time, :test_start_time, :reporters
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
self.report = {}
|
32
|
+
self.errors = 0
|
33
|
+
self.failures = 0
|
34
|
+
self.skips = 0
|
35
|
+
self.test_count = 0
|
36
|
+
self.assertion_count = 0
|
37
|
+
self.verbose = false
|
38
|
+
self.reporters = []
|
39
|
+
|
40
|
+
@_source_cache = {}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Top level driver, controls all output and filtering.
|
44
|
+
def _run args = []
|
45
|
+
self.options = process_args(args)
|
46
|
+
|
47
|
+
self.class.plugins.each do |plugin|
|
48
|
+
send plugin
|
49
|
+
break unless report.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
return failures + errors if @test_count > 0 # or return nil...
|
53
|
+
rescue Interrupt
|
54
|
+
abort 'Interrupted'
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
def _run_anything(type)
|
59
|
+
self.start_time = Time.now
|
60
|
+
|
61
|
+
suites = suites_of_type(type)
|
62
|
+
tests = suites.inject({}) do |acc, suite|
|
63
|
+
acc[suite] = filtered_tests(suite, type)
|
64
|
+
acc
|
65
|
+
end
|
66
|
+
|
67
|
+
self.test_count = tests.inject(0) { |acc, suite| acc + suite[1].length }
|
68
|
+
|
69
|
+
if test_count > 0
|
70
|
+
trigger(:before_suites, suites, type)
|
71
|
+
|
72
|
+
fix_sync do
|
73
|
+
suites.each { |suite| _run_suite(suite, tests[suite]) }
|
74
|
+
end
|
75
|
+
|
76
|
+
trigger(:after_suites, suites, type)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def _run_suite(suite, tests)
|
81
|
+
unless tests.empty?
|
82
|
+
begin
|
83
|
+
self.suite_start_time = Time.now
|
84
|
+
|
85
|
+
trigger(:before_suite, suite)
|
86
|
+
suite.startup if suite.respond_to?(:startup)
|
87
|
+
|
88
|
+
tests.each { |test| _run_test(suite, test) }
|
89
|
+
ensure
|
90
|
+
suite.shutdown if suite.respond_to?(:shutdown)
|
91
|
+
trigger(:after_suite, suite)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
def _run_test(suite, test)
|
98
|
+
self.test_start_time = Time.now
|
99
|
+
|
100
|
+
trigger(:before_test, suite, test)
|
101
|
+
|
102
|
+
test_runner = TestRunner.new(suite, test)
|
103
|
+
test_runner.run
|
104
|
+
add_test_result(suite, test, test_runner)
|
105
|
+
|
106
|
+
trigger(test_runner.result, suite, test, test_runner)
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
def trigger(callback, *args)
|
111
|
+
send("tapout_#{callback}", *args)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
#
|
117
|
+
def filtered_tests(suite, type)
|
118
|
+
filter = options[:filter] || '/./'
|
119
|
+
filter = Regexp.new($1) if filter =~ /\/(.*)\//
|
120
|
+
suite.send("#{type}_methods").grep(filter)
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
def suites_of_type(type)
|
125
|
+
TestCase.send("#{type}_suites")
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
def add_test_result(suite, test, test_runner)
|
130
|
+
self.report[suite] ||= {}
|
131
|
+
self.report[suite][test.to_sym] = test_runner
|
132
|
+
|
133
|
+
self.assertion_count += test_runner.assertions
|
134
|
+
|
135
|
+
case test_runner.result
|
136
|
+
when :skip then self.skips += 1
|
137
|
+
when :failure then self.failures += 1
|
138
|
+
when :error then self.errors += 1
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
def fix_sync
|
144
|
+
sync = output.respond_to?(:'sync=') # stupid emacs
|
145
|
+
old_sync, output.sync = output.sync, true if sync
|
146
|
+
yield
|
147
|
+
output.sync = old_sync if sync
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
def tapout_before_suites(suites, type)
|
152
|
+
doc = {
|
153
|
+
'type' => 'suite',
|
154
|
+
'start' => self.start_time.strftime('%Y-%m-%d %H:%M:%S'),
|
155
|
+
'count' => self.test_count,
|
156
|
+
'seed' => self.options[:seed],
|
157
|
+
'rev' => REVISION
|
158
|
+
}
|
159
|
+
return doc
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
def tapout_after_suites(suites, type)
|
164
|
+
doc = {
|
165
|
+
'type' => 'tally',
|
166
|
+
'time' => Time.now - self.test_start_time,
|
167
|
+
'counts' => {
|
168
|
+
'total' => self.test_count,
|
169
|
+
'pass' => self.test_count - self.failures - self.errors - self.skips,
|
170
|
+
'fail' => self.failures,
|
171
|
+
'error' => self.errors,
|
172
|
+
'omit' => self.skips,
|
173
|
+
'todo' => 0 # TODO: does minitest support pending tests?
|
174
|
+
}
|
175
|
+
}
|
176
|
+
return doc
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
def tapout_before_suite(suite)
|
181
|
+
doc = {
|
182
|
+
'type' => 'case',
|
183
|
+
'subtype' => '',
|
184
|
+
'label' => "#{suite}",
|
185
|
+
'level' => 0
|
186
|
+
}
|
187
|
+
return doc
|
188
|
+
end
|
189
|
+
|
190
|
+
#
|
191
|
+
def tapout_after_suite(suite)
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
def tapout_before_test(suite, test)
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
def tapout_pass(suite, test, test_runner)
|
200
|
+
doc = {
|
201
|
+
'type' => 'test',
|
202
|
+
'subtype' => '',
|
203
|
+
'status' => 'pass',
|
204
|
+
#'setup': foo instance
|
205
|
+
'label' => "#{test}",
|
206
|
+
#'expected' => 2
|
207
|
+
#'returned' => 2
|
208
|
+
#'file' => 'test/test_foo.rb'
|
209
|
+
#'line': 45
|
210
|
+
#'source': ok 1, 2
|
211
|
+
#'snippet':
|
212
|
+
# - 44: ok 0,0
|
213
|
+
# - 45: ok 1,2
|
214
|
+
# - 46: ok 2,4
|
215
|
+
#'coverage':
|
216
|
+
# file: lib/foo.rb
|
217
|
+
# line: 11..13
|
218
|
+
# code: Foo#*
|
219
|
+
'time' => Time.now - self.suite_start_time
|
220
|
+
}
|
221
|
+
return doc
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
def tapout_skip(suite, test, test_runner)
|
226
|
+
e = test_runner.exeception
|
227
|
+
e_file, e_line = location(test_runner.exception)
|
228
|
+
|
229
|
+
doc = {
|
230
|
+
'type' => 'test',
|
231
|
+
'subtype' => '',
|
232
|
+
'status' => 'skip',
|
233
|
+
'label' => "#{test}",
|
234
|
+
#'setup' => "foo instance",
|
235
|
+
#'expected' => 2,
|
236
|
+
#'returned' => 1,
|
237
|
+
#'file' => test/test_foo.rb
|
238
|
+
#'line' => 45
|
239
|
+
#'source' => ok 1, 2
|
240
|
+
#'snippet' =>
|
241
|
+
# - 44: ok 0,0
|
242
|
+
# - 45: ok 1,2
|
243
|
+
# - 46: ok 2,4
|
244
|
+
#'coverage' =>
|
245
|
+
# 'file' => lib/foo.rb
|
246
|
+
# 'line' => 11..13
|
247
|
+
# 'code' => Foo#*
|
248
|
+
'exception' => {
|
249
|
+
'message' => clean_message(e.message),
|
250
|
+
'file' => e_file,
|
251
|
+
'line' => e_line,
|
252
|
+
#'source' => '',
|
253
|
+
'snippet' => code_snippet(e_file, e_line),
|
254
|
+
'backtrace' => filter_backtrace(e.backtrace)
|
255
|
+
},
|
256
|
+
'time' => Time.now - self.suite_start_time
|
257
|
+
}
|
258
|
+
return doc
|
259
|
+
end
|
260
|
+
|
261
|
+
#
|
262
|
+
def tapout_failure(suite, test, test_runner)
|
263
|
+
e = test_runner.exception
|
264
|
+
e_file, e_line = location(test_runner.exception)
|
265
|
+
|
266
|
+
doc = {
|
267
|
+
'type' => 'test',
|
268
|
+
'subtype' => '',
|
269
|
+
'status' => 'fail',
|
270
|
+
'label' => "#{test}",
|
271
|
+
#'setup' => "foo instance",
|
272
|
+
#'expected' => 2,
|
273
|
+
#'returned' => 1,
|
274
|
+
#'file' => test/test_foo.rb
|
275
|
+
#'line' => 45
|
276
|
+
#'source' => ok 1, 2
|
277
|
+
#'snippet' =>
|
278
|
+
# - 44: ok 0,0
|
279
|
+
# - 45: ok 1,2
|
280
|
+
# - 46: ok 2,4
|
281
|
+
#'coverage' =>
|
282
|
+
# 'file' => lib/foo.rb
|
283
|
+
# 'line' => 11..13
|
284
|
+
# 'code' => Foo#*
|
285
|
+
'exception' => {
|
286
|
+
'message' => clean_message(e.message),
|
287
|
+
'file' => e_file,
|
288
|
+
'line' => e_line,
|
289
|
+
#'source' => '',
|
290
|
+
'snippet' => code_snippet(e_file, e_line),
|
291
|
+
'backtrace' => filter_backtrace(e.backtrace)
|
292
|
+
},
|
293
|
+
'time' => Time.now - self.suite_start_time
|
294
|
+
}
|
295
|
+
return doc
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
def tapout_error(suite, test, test_runner)
|
300
|
+
e = test_runner.exception
|
301
|
+
e_file, e_line = location(test_runner.exception)
|
302
|
+
|
303
|
+
doc = {
|
304
|
+
'type' => 'test',
|
305
|
+
'subtype' => '',
|
306
|
+
'status' => 'error',
|
307
|
+
'label' => "#{test}",
|
308
|
+
#'setup' => "foo instance",
|
309
|
+
#'expected' => 2,
|
310
|
+
#'returned' => 1,
|
311
|
+
#'file' => test/test_foo.rb
|
312
|
+
#'line' => 45
|
313
|
+
#'source' => ok 1, 2
|
314
|
+
#'snippet' =>
|
315
|
+
# - 44: ok 0,0
|
316
|
+
# - 45: ok 1,2
|
317
|
+
# - 46: ok 2,4
|
318
|
+
#'coverage' =>
|
319
|
+
# 'file' => lib/foo.rb
|
320
|
+
# 'line' => 11..13
|
321
|
+
# 'code' => Foo#*
|
322
|
+
'exception' => {
|
323
|
+
'message' => clean_message("#{e.class}: #{e.message}"),
|
324
|
+
'file' => e_file,
|
325
|
+
'line' => e_line,
|
326
|
+
#'source' => '',
|
327
|
+
'snippet' => code_snippet(e_file, e_line),
|
328
|
+
'backtrace' => filter_backtrace(e.backtrace)
|
329
|
+
},
|
330
|
+
'time' => Time.now - self.suite_start_time
|
331
|
+
}
|
332
|
+
return doc
|
333
|
+
end
|
334
|
+
|
335
|
+
#
|
336
|
+
INTERNALS = /(lib|bin)#{Regexp.escape(File::SEPARATOR)}tapout/
|
337
|
+
|
338
|
+
#
|
339
|
+
def filter_backtrace(bt)
|
340
|
+
bt = clean_backtrace(bt)
|
341
|
+
bt = MiniTest::filter_backtrace(bt)
|
342
|
+
bt
|
343
|
+
end
|
344
|
+
|
345
|
+
# Clean the backtrace of any reference to ko/ paths and code.
|
346
|
+
def clean_backtrace(backtrace)
|
347
|
+
trace = backtrace.reject{ |bt| bt =~ INTERNALS }
|
348
|
+
trace = trace.map do |bt|
|
349
|
+
if i = bt.index(':in')
|
350
|
+
bt[0...i]
|
351
|
+
else
|
352
|
+
bt
|
353
|
+
end
|
354
|
+
end
|
355
|
+
trace = backtrace if trace.empty?
|
356
|
+
trace = trace.map{ |bt| bt.sub(Dir.pwd+File::SEPARATOR,'') }
|
357
|
+
trace
|
358
|
+
end
|
359
|
+
|
360
|
+
# Returns a String of source code.
|
361
|
+
def code_snippet(file, line)
|
362
|
+
s = []
|
363
|
+
|
364
|
+
#case snippet
|
365
|
+
#when String
|
366
|
+
# lines = snippet.lines.to_a
|
367
|
+
# index = line - ((lines.size - 1) / 2)
|
368
|
+
# lines.each do |line|
|
369
|
+
# s << [index, line]
|
370
|
+
# index += 1
|
371
|
+
# end
|
372
|
+
#when Array
|
373
|
+
# snippet.each do |h|
|
374
|
+
# s << [h.key, h.value]
|
375
|
+
# end
|
376
|
+
#else
|
377
|
+
##backtrace = exception.backtrace.reject{ |bt| bt =~ INTERNALS }
|
378
|
+
##backtrace.first =~ /(.+?):(\d+(?=:|\z))/ or return ""
|
379
|
+
#caller =~ /(.+?):(\d+(?=:|\z))/ or return ""
|
380
|
+
#source_file, source_line = $1, $2.to_i
|
381
|
+
|
382
|
+
if File.file?(file)
|
383
|
+
source = source(file)
|
384
|
+
radius = 2 # TODO: make customizable (number of surrounding lines to show)
|
385
|
+
region = [line - radius, 1].max ..
|
386
|
+
[line + radius, source.length].min
|
387
|
+
|
388
|
+
s = region.map do |n|
|
389
|
+
{n => source[n-1].chomp}
|
390
|
+
end
|
391
|
+
end
|
392
|
+
#end
|
393
|
+
return s
|
394
|
+
end
|
395
|
+
|
396
|
+
# Cache source file text. This is only used if the TAP-Y stream
|
397
|
+
# doesn not provide a snippet and the test file is locatable.
|
398
|
+
def source(file)
|
399
|
+
@_source_cache[file] ||= (
|
400
|
+
File.readlines(file)
|
401
|
+
)
|
402
|
+
end
|
403
|
+
|
404
|
+
# Parse source location from caller, caller[0] or an Exception object.
|
405
|
+
def parse_source_location(caller)
|
406
|
+
case caller
|
407
|
+
when Exception
|
408
|
+
trace = caller.backtrace.reject{ |bt| bt =~ INTERNALS }
|
409
|
+
caller = trace.first
|
410
|
+
when Array
|
411
|
+
caller = caller.first
|
412
|
+
end
|
413
|
+
caller =~ /(.+?):(\d+(?=:|\z))/ or return ""
|
414
|
+
source_file, source_line = $1, $2.to_i
|
415
|
+
returnf source_file, source_line
|
416
|
+
end
|
417
|
+
|
418
|
+
# Get location of exception.
|
419
|
+
def location e # :nodoc:
|
420
|
+
last_before_assertion = ""
|
421
|
+
e.backtrace.reverse_each do |s|
|
422
|
+
break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
|
423
|
+
last_before_assertion = s
|
424
|
+
end
|
425
|
+
file, line = last_before_assertion.sub(/:in .*$/, '').split(':')
|
426
|
+
line = line.to_i if line
|
427
|
+
return file, line
|
428
|
+
end
|
429
|
+
|
430
|
+
#
|
431
|
+
def clean_message(message)
|
432
|
+
message.strip #.gsub(/\s*\n\s*/, "\n")
|
433
|
+
end
|
434
|
+
|
435
|
+
end
|
436
|
+
|
437
|
+
# Runner for individual MiniTest tests.
|
438
|
+
#
|
439
|
+
# You *should not* create instances of this class directly. Instances of
|
440
|
+
# {SuiteRunner} will create these and send them to the reporters.
|
441
|
+
#
|
442
|
+
# Based upon Ryan Davis of Seattle.rb's MiniTest (MIT License).
|
443
|
+
#
|
444
|
+
# @see https://github.com/seattlerb/minitest MiniTest
|
445
|
+
class TestRunner
|
446
|
+
attr_reader :suite, :test, :assertions, :result, :exception
|
447
|
+
|
448
|
+
def initialize(suite, test)
|
449
|
+
@suite = suite
|
450
|
+
@test = test
|
451
|
+
@assertions = 0
|
452
|
+
end
|
453
|
+
|
454
|
+
def run
|
455
|
+
suite_instance = suite.new(test)
|
456
|
+
@result, @exception = fix_result(suite_instance.run(self))
|
457
|
+
@assertions = suite_instance._assertions
|
458
|
+
end
|
459
|
+
|
460
|
+
def puke(suite, test, exception)
|
461
|
+
case exception
|
462
|
+
when MiniTest::Skip then [:skip, exception]
|
463
|
+
when MiniTest::Assertion then [:failure, exception]
|
464
|
+
else [:error, exception]
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
private
|
469
|
+
|
470
|
+
def fix_result(result)
|
471
|
+
result == '.' ? [:pass, nil] : result
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
#
|
476
|
+
class TapY < MiniTap
|
477
|
+
def initialize
|
478
|
+
require 'yaml'
|
479
|
+
super
|
480
|
+
end
|
481
|
+
def tapout_before_suites(suites, type)
|
482
|
+
puts super(suites, type).to_yaml
|
483
|
+
end
|
484
|
+
def tapout_before_suite(suite)
|
485
|
+
puts super(suite).to_yaml
|
486
|
+
end
|
487
|
+
def tapout_pass(suite, test, test_runner)
|
488
|
+
puts super(suite, test, test_runner).to_yaml
|
489
|
+
end
|
490
|
+
def tapout_skip(suite, test, test_runner)
|
491
|
+
puts super(suite, test, test_runner).to_yaml
|
492
|
+
end
|
493
|
+
def tapout_failure(suite, test, test_runner)
|
494
|
+
puts super(suite, test, test_runner).to_yaml
|
495
|
+
end
|
496
|
+
def tapout_error(suite, test, test_runner)
|
497
|
+
puts super(suite, test, test_runner).to_yaml
|
498
|
+
end
|
499
|
+
def tapout_after_suites(suites, type)
|
500
|
+
puts super(suites, type).to_yaml
|
501
|
+
puts "..."
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
#
|
506
|
+
class TapJ < MiniTap
|
507
|
+
def initialize
|
508
|
+
require 'json'
|
509
|
+
super
|
510
|
+
end
|
511
|
+
def tapout_before_suites(suites, type)
|
512
|
+
puts super(suites, type).to_json
|
513
|
+
end
|
514
|
+
def tapout_before_suite(suite)
|
515
|
+
puts super(suite).to_json
|
516
|
+
end
|
517
|
+
def tapout_pass(suite, test, test_runner)
|
518
|
+
puts super(suite, test, test_runner).to_json
|
519
|
+
end
|
520
|
+
def tapout_skip(suite, test, test_runner)
|
521
|
+
puts super(suite, test, test_runner).to_json
|
522
|
+
end
|
523
|
+
def tapout_failure(suite, test, test_runner)
|
524
|
+
puts super(suite, test, test_runner).to_json
|
525
|
+
end
|
526
|
+
def tapout_error(suite, test, test_runner)
|
527
|
+
puts super(suite, test, test_runner).to_json
|
528
|
+
end
|
529
|
+
def tapout_after_suites(suites, type)
|
530
|
+
puts super(suites, type).to_json
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: minitap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thomas Sawyer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-10-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: tapout
|
16
|
+
requirement: &12167740 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *12167740
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: detroit
|
27
|
+
requirement: &12167140 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *12167140
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: reap
|
38
|
+
requirement: &12166280 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *12166280
|
47
|
+
description: MiniTap provides a custom MiniTest reporter that outs TAP-Y or TAP-J
|
48
|
+
formatted output.
|
49
|
+
email:
|
50
|
+
- transfire@gmail.com
|
51
|
+
executables: []
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files:
|
54
|
+
- HISTORY.rdoc
|
55
|
+
- README.rdoc
|
56
|
+
- COPYING.rdoc
|
57
|
+
files:
|
58
|
+
- .ruby
|
59
|
+
- lib/minitap.rb
|
60
|
+
- lib/minitest/tapj.rb
|
61
|
+
- lib/minitest/tapy.rb
|
62
|
+
- HISTORY.rdoc
|
63
|
+
- README.rdoc
|
64
|
+
- COPYING.rdoc
|
65
|
+
homepage: http://rubyworks.github.com/minitap
|
66
|
+
licenses: []
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.8.5
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: MiniTest TAP-Y/J reporter
|
89
|
+
test_files: []
|