tapout 0.1.0 → 0.2.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 +41 -41
- data/.yardopts +7 -0
- data/COPYING.rdoc +54 -0
- data/HISTORY.rdoc +18 -3
- data/LICENSE.txt +25 -0
- data/PROFILE +33 -0
- data/README.rdoc +20 -29
- data/TAP-YJ.md +346 -0
- data/TODO +5 -0
- data/lib/tapout.rb +15 -12
- data/lib/tapout/{tap_legacy_adapter.rb → adapters/perl.rb} +21 -20
- data/lib/tapout/parsers.rb +4 -0
- data/lib/tapout/parsers/json.rb +38 -0
- data/lib/tapout/{tap_legacy_parser.rb → parsers/perl.rb} +3 -3
- data/lib/tapout/{tapy_parser.rb → parsers/yaml.rb} +2 -3
- data/lib/tapout/reporters.rb +4 -3
- data/lib/tapout/reporters/abstract.rb +21 -18
- data/lib/tapout/reporters/breakdown.rb +4 -3
- data/lib/tapout/reporters/dotprogress.rb +6 -6
- data/lib/tapout/reporters/html.rb +152 -0
- data/lib/tapout/reporters/{verbose.rb → outline.rb} +9 -6
- data/lib/tapout/reporters/progressbar.rb +11 -7
- data/lib/tapout/reporters/tap.rb +15 -8
- data/lib/tapout/version.rb +4 -4
- data/qed/{tap_adapter.rdoc → perl_adapter.rdoc} +3 -3
- metadata +70 -87
- data/APACHE2.txt +0 -204
- data/NOTICE.rdoc +0 -38
- data/TAP-YJ.rdoc +0 -296
data/TODO
ADDED
data/lib/tapout.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'tapout/tapy_parser'
|
2
|
-
require 'tapout/tap_legacy_parser'
|
3
|
-
|
4
1
|
require 'optparse'
|
2
|
+
require 'tapout/parsers'
|
5
3
|
|
6
4
|
module TapOut
|
7
5
|
|
8
|
-
#
|
9
|
-
|
6
|
+
# Usable formats.
|
7
|
+
FORMATS = %w{breakdown dotprogress html outline progressbar tap}
|
10
8
|
|
11
9
|
#
|
12
10
|
def self.cli(*argv)
|
@@ -34,7 +32,7 @@ module TapOut
|
|
34
32
|
$DEBUG = true
|
35
33
|
end
|
36
34
|
|
37
|
-
opt.separator("\nFORMATS:\n " +
|
35
|
+
opt.separator("\nFORMATS:\n " + FORMATS.join("\n "))
|
38
36
|
end
|
39
37
|
|
40
38
|
parser.parse!(argv)
|
@@ -51,19 +49,24 @@ module TapOut
|
|
51
49
|
|
52
50
|
case stdin.line1
|
53
51
|
when /^\d/
|
54
|
-
type = :
|
52
|
+
type = :perl
|
55
53
|
when /^\-/
|
56
|
-
type = :
|
54
|
+
type = :yaml
|
55
|
+
when /^\{/
|
56
|
+
type = :json
|
57
57
|
else
|
58
58
|
raise "Not a recognized TAP stream!"
|
59
59
|
end
|
60
60
|
|
61
61
|
case type
|
62
|
-
when :
|
63
|
-
stream_parser =
|
62
|
+
when :perl
|
63
|
+
stream_parser = PerlParser.new(options)
|
64
64
|
stream_parser.consume(stdin)
|
65
|
-
|
66
|
-
stream_parser =
|
65
|
+
when :yaml
|
66
|
+
stream_parser = YamlParser.new(options)
|
67
|
+
stream_parser.consume(stdin)
|
68
|
+
when :json
|
69
|
+
stream_parser = JsonParser.new(options)
|
67
70
|
stream_parser.consume(stdin)
|
68
71
|
end
|
69
72
|
end
|
@@ -5,11 +5,9 @@ module TapOut
|
|
5
5
|
# The TAP Legacy Adapter transforms traditional TAP format to
|
6
6
|
# modern TAP-Y format.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# TODO: Add support for TAP-J.
|
8
|
+
# IMPORTANT: This is still very much a work in progress.
|
11
9
|
|
12
|
-
class
|
10
|
+
class PerlAdapter
|
13
11
|
|
14
12
|
#
|
15
13
|
def initialize(input)
|
@@ -89,7 +87,7 @@ module TapOut
|
|
89
87
|
line = cache[0]
|
90
88
|
md = /^(\d+)\.\.(\d+)\s*$/.match(line)
|
91
89
|
count = md[2].to_i - md[1].to_i + 1
|
92
|
-
entry = {'count'=>
|
90
|
+
entry = {'count'=>count, 'type'=>'suite', 'rev'=>REVISION}
|
93
91
|
when :ok
|
94
92
|
line = cache[0]
|
95
93
|
md = /^ok\s+(\d+)\s*\-?\s*(.*?)($|#)/.match(line)
|
@@ -102,7 +100,7 @@ module TapOut
|
|
102
100
|
entry = convert_not_ok(md[1], md[2], data)
|
103
101
|
when :comment
|
104
102
|
desc = cache.map{ |c| c.sub(/^\#\s{0,1}/, '') }.join("\n")
|
105
|
-
entry = {'type'=>'note', '
|
103
|
+
entry = {'type'=>'note', 'text'=>desc.rstrip}
|
106
104
|
end
|
107
105
|
output(entry)
|
108
106
|
@cache = []
|
@@ -131,20 +129,23 @@ module TapOut
|
|
131
129
|
private
|
132
130
|
|
133
131
|
#
|
134
|
-
|
132
|
+
# TODO: Any way to distinguish fail vs error?
|
133
|
+
def convert_not_ok(number, label, data)
|
135
134
|
entry = {}
|
136
135
|
entry['type'] = 'test'
|
137
136
|
entry['status'] = 'fail'
|
138
137
|
entry['index'] = number.to_i
|
139
138
|
entry['label'] = label
|
140
|
-
if
|
141
|
-
entry['
|
142
|
-
entry['
|
143
|
-
entry['
|
144
|
-
entry['
|
145
|
-
|
146
|
-
entry['
|
147
|
-
entry['
|
139
|
+
if data
|
140
|
+
entry['exception'] = {}
|
141
|
+
entry['exception']['file'] = data['file']
|
142
|
+
entry['exception']['line'] = data['line']
|
143
|
+
entry['exception']['message'] = data['description']
|
144
|
+
|
145
|
+
entry['expected'] = data['wanted']
|
146
|
+
entry['returned'] = data['found']
|
147
|
+
entry['source'] = data['raw_test']
|
148
|
+
entry['extra'] = data['extensions']
|
148
149
|
end
|
149
150
|
entry
|
150
151
|
end
|
@@ -154,11 +155,11 @@ module TapOut
|
|
154
155
|
groups = @entries.group_by{ |e| e['status'] }
|
155
156
|
|
156
157
|
entry = {}
|
157
|
-
entry['
|
158
|
-
entry['
|
159
|
-
|
160
|
-
'pass'
|
161
|
-
'fail'
|
158
|
+
entry['type'] = 'tally'
|
159
|
+
entry['counts'] = {
|
160
|
+
'total' => @count,
|
161
|
+
'pass' => (groups['pass'] || []).size,
|
162
|
+
'fail' => (groups['fail'] || []).size
|
162
163
|
}
|
163
164
|
entry
|
164
165
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'tapout/reporters'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module TapOut
|
5
|
+
|
6
|
+
# The TAP-J Parser takes a TAP-J stream and routes it through
|
7
|
+
# a TapOut report format.
|
8
|
+
#
|
9
|
+
class JsonParser
|
10
|
+
|
11
|
+
#
|
12
|
+
def initialize(options={})
|
13
|
+
format = options[:format] || 'dotprogress'
|
14
|
+
@reporter = Reporters.factory(format).new
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
def consume(input)
|
19
|
+
while line = input.gets
|
20
|
+
self << line
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
def <<(line)
|
26
|
+
handle(line)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
def handle(doc)
|
31
|
+
return if doc == ''
|
32
|
+
entry = JSON.load(doc)
|
33
|
+
@reporter << entry
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'tapout/version'
|
2
|
-
require 'tapout/
|
2
|
+
require 'tapout/perl_adapter'
|
3
3
|
require 'tapout/reporters'
|
4
4
|
|
5
5
|
module TapOut
|
6
6
|
|
7
7
|
# The TAPLegacy Parser takes a traditional TAP stream and routes
|
8
8
|
# it through a Tap Out report format.
|
9
|
-
class
|
9
|
+
class perlParser
|
10
10
|
|
11
11
|
# options[:format] - the report format to use
|
12
12
|
def initialize(options={})
|
@@ -16,7 +16,7 @@ module TapOut
|
|
16
16
|
|
17
17
|
# input - any object that responds to #gets
|
18
18
|
def consume(input)
|
19
|
-
parser =
|
19
|
+
parser = PerlAdapter.new(input)
|
20
20
|
parser | @reporter
|
21
21
|
end
|
22
22
|
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'tapout/reporters'
|
2
|
-
|
3
2
|
require 'yaml'
|
4
3
|
|
5
4
|
module TapOut
|
6
5
|
|
7
6
|
# The TAP-Y Parser takes a TAP-Y stream and routes it through
|
8
|
-
# a
|
9
|
-
class
|
7
|
+
# a TapOut report format.
|
8
|
+
class YamlParser
|
10
9
|
|
11
10
|
#
|
12
11
|
def initialize(options={})
|
data/lib/tapout/reporters.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'tapout/reporters/abstract'
|
2
|
+
require 'tapout/reporters/breakdown'
|
2
3
|
require 'tapout/reporters/dotprogress'
|
3
|
-
require 'tapout/reporters/
|
4
|
-
require 'tapout/reporters/
|
4
|
+
require 'tapout/reporters/html'
|
5
|
+
require 'tapout/reporters/outline'
|
5
6
|
require 'tapout/reporters/progressbar'
|
6
|
-
require 'tapout/reporters/
|
7
|
+
require 'tapout/reporters/tap'
|
@@ -49,7 +49,7 @@ module TapOut
|
|
49
49
|
# report methods.
|
50
50
|
def handle(entry)
|
51
51
|
case entry['type']
|
52
|
-
when '
|
52
|
+
when 'suite'
|
53
53
|
start_suite(entry)
|
54
54
|
when 'case'
|
55
55
|
finish_case(@previous_case) if @previous_case
|
@@ -68,10 +68,10 @@ module TapOut
|
|
68
68
|
err(entry)
|
69
69
|
when 'omit'
|
70
70
|
omit(entry)
|
71
|
-
when '
|
71
|
+
when 'todo', 'skip', 'pending'
|
72
72
|
skip(entry)
|
73
73
|
end
|
74
|
-
when '
|
74
|
+
when 'tally'
|
75
75
|
finish_case(@previous_case) if @previous_case
|
76
76
|
finish_suite(entry)
|
77
77
|
end
|
@@ -128,30 +128,32 @@ module TapOut
|
|
128
128
|
|
129
129
|
# TODO: get the tally's from the footer entry ?
|
130
130
|
def tally(entry)
|
131
|
-
total =
|
131
|
+
total = @passed.size + @failed.size + @raised.size #+ @skipped.size + @omitted.size
|
132
132
|
|
133
|
-
if entry['
|
134
|
-
|
135
|
-
|
133
|
+
if entry['counts']
|
134
|
+
total = entry['counts']['total'] || total
|
135
|
+
count_fail = entry['counts']['fail'] || 0
|
136
|
+
count_error = entry['counts']['error'] || 0
|
136
137
|
else
|
137
138
|
count_fail = @failed.size
|
138
139
|
count_error = @raised.size
|
139
140
|
end
|
140
141
|
|
141
|
-
if tally = entry['
|
142
|
-
sums = %w{pass fail error
|
142
|
+
if tally = entry['counts']
|
143
|
+
sums = %w{pass fail error todo omit}.map{ |e| tally[e] || 0 }
|
143
144
|
else
|
144
|
-
sums = [@passed, @failed, @raised, @skipped].map{ |e| e.size }
|
145
|
+
sums = [@passed, @failed, @raised, @skipped, @omitted].map{ |e| e.size }
|
145
146
|
end
|
146
147
|
|
148
|
+
# ???
|
147
149
|
assertions = entry['assertions']
|
148
150
|
failures = entry['failures']
|
149
151
|
|
150
152
|
if assertions
|
151
|
-
text = "%s tests: %s pass, %s fail, %s err, %s
|
153
|
+
text = "%s tests: %s pass, %s fail, %s err, %s todo, %omit (%s/%s assertions)"
|
152
154
|
text = text % [total, *sums] + [assertions - failures, assertions]
|
153
155
|
else
|
154
|
-
text = "%s tests: %s pass, %s fail, %s err, %s
|
156
|
+
text = "%s tests: %s pass, %s fail, %s err, %s todo, %s omit"
|
155
157
|
text = text % [total, *sums]
|
156
158
|
end
|
157
159
|
|
@@ -165,7 +167,7 @@ module TapOut
|
|
165
167
|
end
|
166
168
|
|
167
169
|
#
|
168
|
-
INTERNALS = /(lib|bin)#{Regexp.escape(File::SEPARATOR)}
|
170
|
+
INTERNALS = /(lib|bin)#{Regexp.escape(File::SEPARATOR)}tapout/
|
169
171
|
|
170
172
|
# Clean the backtrace of any reference to ko/ paths and code.
|
171
173
|
def clean_backtrace(backtrace)
|
@@ -200,7 +202,7 @@ module TapOut
|
|
200
202
|
end
|
201
203
|
when Array
|
202
204
|
snippet.each do |h|
|
203
|
-
s << [h.
|
205
|
+
s << [h.keys.first, h.values.first]
|
204
206
|
end
|
205
207
|
else
|
206
208
|
##backtrace = exception.backtrace.reject{ |bt| bt =~ INTERNALS }
|
@@ -208,17 +210,18 @@ module TapOut
|
|
208
210
|
#caller =~ /(.+?):(\d+(?=:|\z))/ or return ""
|
209
211
|
#source_file, source_line = $1, $2.to_i
|
210
212
|
|
211
|
-
if File.file?(file)
|
213
|
+
if file && File.file?(file)
|
212
214
|
source = source(file)
|
213
215
|
|
214
216
|
radius = 3 # number of surrounding lines to show
|
215
|
-
region = [
|
216
|
-
[
|
217
|
+
region = [line - radius, 1].max ..
|
218
|
+
[line + radius, source.length].min
|
217
219
|
|
218
220
|
#len = region.last.to_s.length
|
219
221
|
|
220
222
|
s = region.map do |n|
|
221
|
-
format % [n, source[n-1].chomp]
|
223
|
+
#format % [n, source[n-1].chomp]
|
224
|
+
[n, source[n-1].chomp]
|
222
225
|
end
|
223
226
|
end
|
224
227
|
end
|
@@ -98,12 +98,13 @@ module TapOut
|
|
98
98
|
#puts "\n-- Failures and Errors --\n"
|
99
99
|
puts
|
100
100
|
bad.each do |e|
|
101
|
-
|
101
|
+
x = e['exception']
|
102
|
+
message = x['message'].strip
|
102
103
|
message = message.ansi(:red)
|
103
104
|
puts(message)
|
104
|
-
puts "#{
|
105
|
+
puts "#{x['file']}:#{x['line']}"
|
105
106
|
puts
|
106
|
-
puts code_snippet(
|
107
|
+
puts code_snippet(x)
|
107
108
|
end
|
108
109
|
puts
|
109
110
|
end
|
@@ -42,9 +42,9 @@ module TapOut::Reporters
|
|
42
42
|
#backtrace = clean_backtrace(exception.backtrace)
|
43
43
|
$stdout.puts "#{i}. " + (e['label']).ansi(:red)
|
44
44
|
$stdout.puts
|
45
|
-
$stdout.puts " #{e['message']}"
|
46
|
-
$stdout.puts " #{e['file']}:#{e['line']}" #+ backtrace[0]
|
47
|
-
$stdout.puts code_snippet(e)
|
45
|
+
$stdout.puts " #{e['exception']['message']}"
|
46
|
+
$stdout.puts " #{e['exception']['file']}:#{e['exception']['line']}" #+ backtrace[0]
|
47
|
+
$stdout.puts code_snippet(e['exception'])
|
48
48
|
$stdout.puts
|
49
49
|
i += 1
|
50
50
|
end
|
@@ -53,9 +53,9 @@ module TapOut::Reporters
|
|
53
53
|
#backtrace = clean_backtrace(exception.backtrace)
|
54
54
|
$stdout.puts "#{i}. " + (e['label']).ansi(:yellow)
|
55
55
|
$stdout.puts
|
56
|
-
$stdout.puts " #{e['message']}"
|
57
|
-
$stdout.puts " #{e['file']}:#{e['line']}" #+ backtrace[0..2].join(" \n")
|
58
|
-
$stdout.puts code_snippet(e)
|
56
|
+
$stdout.puts " #{e['exception']['message']}"
|
57
|
+
$stdout.puts " #{e['exception']['file']}:#{e['exception']['line']}" #+ backtrace[0..2].join(" \n")
|
58
|
+
$stdout.puts code_snippet(e['exception'])
|
59
59
|
$stdout.puts
|
60
60
|
i += 1
|
61
61
|
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'test/reporters/abstract'
|
2
|
+
|
3
|
+
module TapOut::Reporters
|
4
|
+
|
5
|
+
# HTML Test Reporter
|
6
|
+
#
|
7
|
+
# This reporter is rather simplistic and rough at this point --in needs
|
8
|
+
# of some TLC.
|
9
|
+
#--
|
10
|
+
# TODO: Make this more like a microformat and add timer info.
|
11
|
+
#++
|
12
|
+
class Html < Abstract
|
13
|
+
|
14
|
+
#
|
15
|
+
def start_suite(entry)
|
16
|
+
timer_reset
|
17
|
+
|
18
|
+
puts %[<html>]
|
19
|
+
puts %[<head>]
|
20
|
+
puts %[<title>Test Report</title>]
|
21
|
+
puts %[ <style>]
|
22
|
+
puts %[ html{ background: #fff; margin: 0; padding: 0; font-family: helvetica; }]
|
23
|
+
puts %[ body{ margin: 0; padding: 0;}]
|
24
|
+
puts %[ h3{color:#555;}]
|
25
|
+
puts %[ #main{ margin: 0 auto; color: #110; width: 600px; ]
|
26
|
+
puts %[ border-right: 1px solid #ddd; border-left: 1px solid #ddd; ]
|
27
|
+
puts %[ padding: 10px 30px; width: 500px; } ]
|
28
|
+
puts %[ .title{ color: gold; font-size: 22px; font-weight: bold; ]
|
29
|
+
puts %[ font-family: courier; margin-bottom: -15px;}]
|
30
|
+
puts %[ .tally{ font-weight: bold; margin-bottom: 10px; }]
|
31
|
+
puts %[ .omit{ color: cyan; }]
|
32
|
+
puts %[ .pass{ color: green; }]
|
33
|
+
puts %[ .fail{ color: red; }]
|
34
|
+
puts %[ .footer{ font-size: 0.7em; color: #666; margin: 20px 0; }]
|
35
|
+
puts %[ </style>]
|
36
|
+
puts %[</head>]
|
37
|
+
puts %[<body>]
|
38
|
+
puts %[<div id="main">]
|
39
|
+
puts %[<div class="title">R U B Y - T E S T</div>]
|
40
|
+
puts %[<h1>Test Report</h1>]
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
def start_case(entry)
|
45
|
+
body = []
|
46
|
+
|
47
|
+
puts "<h2>"
|
48
|
+
puts entry['label']
|
49
|
+
puts "</h2>"
|
50
|
+
|
51
|
+
puts body.join("\n")
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
def start_test(entry)
|
56
|
+
if subtext = entry['subtext']
|
57
|
+
if @subtext != subtext
|
58
|
+
@subtext = subtext
|
59
|
+
puts "<h3>#{subtext}</h3>"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
def pass(entry)
|
66
|
+
puts %[<li class="pass">]
|
67
|
+
puts "%s %s" % [ "PASS", entry['label'] ]
|
68
|
+
puts %[</li>]
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
def fail(entry)
|
73
|
+
e = entry['exception']
|
74
|
+
|
75
|
+
puts %[<li class="fail">]
|
76
|
+
puts "FAIL #{e['message']}"
|
77
|
+
puts "<pre>"
|
78
|
+
puts clean_backtrace(e['backtrace']).join("\n")
|
79
|
+
puts "</pre>"
|
80
|
+
puts %[</li>]
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
def err(entry)
|
85
|
+
e = entry['exception']
|
86
|
+
|
87
|
+
puts %[<li class="error">]
|
88
|
+
puts "ERROR "
|
89
|
+
puts e['message'].to_s
|
90
|
+
puts "<pre>"
|
91
|
+
puts clean_backtrace(e['backtrace']).join("\n")
|
92
|
+
puts "</pre>"
|
93
|
+
puts %[</li>]
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
def todo(entry)
|
98
|
+
e = entry['exception']
|
99
|
+
|
100
|
+
puts %[<li class="pending">]
|
101
|
+
puts "TODO "
|
102
|
+
puts e['message'].to_s
|
103
|
+
puts %[</li>]
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
def omit(entry)
|
108
|
+
e = entry['exception']
|
109
|
+
|
110
|
+
puts %[<li class="omit">]
|
111
|
+
puts "OMIT "
|
112
|
+
puts e['message'].to_s
|
113
|
+
puts %[</li>]
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
def finish_suite(entry)
|
118
|
+
puts ""
|
119
|
+
puts %[<div class="tally">]
|
120
|
+
puts tally(entry)
|
121
|
+
puts %[</div>]
|
122
|
+
puts ""
|
123
|
+
puts ""
|
124
|
+
puts %[<div class="footer">]
|
125
|
+
puts %[Generated by <a href="http://rubyworks.github.com/tapout">TAPOUT</a>]
|
126
|
+
puts %[on #{Time.now}.]
|
127
|
+
puts %[</div>]
|
128
|
+
puts ""
|
129
|
+
puts %[</div>]
|
130
|
+
puts %[</div>]
|
131
|
+
puts ""
|
132
|
+
puts %[</body>]
|
133
|
+
puts %[</html>]
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
#
|
139
|
+
def timer
|
140
|
+
secs = Time.now - @time
|
141
|
+
@time = Time.now
|
142
|
+
return "%0.5fs" % [secs.to_s]
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
def timer_reset
|
147
|
+
@time = Time.now
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|