tapout 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 +44 -0
- data/APACHE2.txt +204 -0
- data/HISTORY.rdoc +11 -0
- data/NOTICE.rdoc +38 -0
- data/README.rdoc +73 -0
- data/TAP-YJ.rdoc +296 -0
- data/bin/tapout +3 -0
- data/lib/tapout.rb +88 -0
- data/lib/tapout/reporters.rb +6 -0
- data/lib/tapout/reporters/abstract.rb +266 -0
- data/lib/tapout/reporters/breakdown.rb +120 -0
- data/lib/tapout/reporters/dotprogress.rb +69 -0
- data/lib/tapout/reporters/progressbar.rb +89 -0
- data/lib/tapout/reporters/tap.rb +80 -0
- data/lib/tapout/reporters/verbose.rb +54 -0
- data/lib/tapout/tap_legacy_adapter.rb +168 -0
- data/lib/tapout/tap_legacy_parser.rb +25 -0
- data/lib/tapout/tapy_parser.rb +58 -0
- data/lib/tapout/version.rb +7 -0
- data/qed/applique/env.rb +5 -0
- data/qed/tap_adapter.rdoc +68 -0
- metadata +129 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'tapout/reporters/abstract'
|
2
|
+
|
3
|
+
module TapOut::Reporters
|
4
|
+
|
5
|
+
# Traditional dot progress reporter.
|
6
|
+
class Dotprogress < Abstract
|
7
|
+
|
8
|
+
#
|
9
|
+
def start_suite(entry)
|
10
|
+
@start_time = Time.now
|
11
|
+
$stdout.puts "Started\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
def pass(entry)
|
16
|
+
$stdout.print '.'
|
17
|
+
$stdout.flush
|
18
|
+
super(entry)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
def fail(entry)
|
23
|
+
$stdout.print 'F'.ansi(:red)
|
24
|
+
$stdout.flush
|
25
|
+
super(entry)
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
def err(entry)
|
30
|
+
$stdout.print 'E'.ansi(:yellow)
|
31
|
+
$stdout.flush
|
32
|
+
super(entry)
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
def finish_suite(entry)
|
37
|
+
$stdout.puts "\n\n"
|
38
|
+
|
39
|
+
i = 1
|
40
|
+
|
41
|
+
@failed.each do |e|
|
42
|
+
#backtrace = clean_backtrace(exception.backtrace)
|
43
|
+
$stdout.puts "#{i}. " + (e['label']).ansi(:red)
|
44
|
+
$stdout.puts
|
45
|
+
$stdout.puts " #{e['message']}"
|
46
|
+
$stdout.puts " #{e['file']}:#{e['line']}" #+ backtrace[0]
|
47
|
+
$stdout.puts code_snippet(e)
|
48
|
+
$stdout.puts
|
49
|
+
i += 1
|
50
|
+
end
|
51
|
+
|
52
|
+
@raised.each do |e|
|
53
|
+
#backtrace = clean_backtrace(exception.backtrace)
|
54
|
+
$stdout.puts "#{i}. " + (e['label']).ansi(:yellow)
|
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)
|
59
|
+
$stdout.puts
|
60
|
+
i += 1
|
61
|
+
end
|
62
|
+
|
63
|
+
$stdout.puts "Finished in #{Time.now - @start_time}s"
|
64
|
+
$stdout.puts tally(entry)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'tapout/reporters/abstract'
|
2
|
+
|
3
|
+
require 'ansi/progressbar'
|
4
|
+
|
5
|
+
module TapOut
|
6
|
+
|
7
|
+
module Reporters
|
8
|
+
|
9
|
+
# The progressbar report format utilises a progress bar to indicate
|
10
|
+
# elapsed progress.
|
11
|
+
class Progressbar < Abstract
|
12
|
+
|
13
|
+
def start_suite(entry)
|
14
|
+
@pbar = ::ANSI::Progressbar.new('Testing', entry['count'].to_i + 1)
|
15
|
+
@pbar.style(:bar=>:green)
|
16
|
+
@pbar.inc
|
17
|
+
end
|
18
|
+
|
19
|
+
def start_case(entry)
|
20
|
+
end
|
21
|
+
|
22
|
+
#def test(entry)
|
23
|
+
# #@pbar.inc
|
24
|
+
#end
|
25
|
+
|
26
|
+
def pass(entry)
|
27
|
+
@pbar.inc
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
def fail(entry)
|
32
|
+
@pbar.clear
|
33
|
+
|
34
|
+
puts
|
35
|
+
message = entry['message'].strip
|
36
|
+
message = message.ansi(:red)
|
37
|
+
puts(message)
|
38
|
+
puts "#{entry['file']}:#{entry['line']}"
|
39
|
+
puts
|
40
|
+
puts code_snippet(entry)
|
41
|
+
puts
|
42
|
+
|
43
|
+
@pbar.style(:bar=>:red)
|
44
|
+
@pbar.inc
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
def error(message=nil)
|
49
|
+
@pbar.clear
|
50
|
+
|
51
|
+
puts
|
52
|
+
message = entry['message'].strip
|
53
|
+
message = message.ansi(:red)
|
54
|
+
puts(message)
|
55
|
+
puts "#{entry['file']}:#{entry['line']}"
|
56
|
+
puts
|
57
|
+
puts code_snippet(entry)
|
58
|
+
puts
|
59
|
+
|
60
|
+
@pbar.style(:bar=>:yellow)
|
61
|
+
@pbar.inc
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
def omit(entry)
|
66
|
+
@pbar.inc
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
def skip(entry)
|
71
|
+
@pbar.inc
|
72
|
+
end
|
73
|
+
|
74
|
+
#def finish_case(kase)
|
75
|
+
#end
|
76
|
+
|
77
|
+
def finish_suite(entry)
|
78
|
+
@pbar.finish
|
79
|
+
#post_report(entry)
|
80
|
+
puts
|
81
|
+
puts tally(entry)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'tapout/reporters/abstract'
|
2
|
+
|
3
|
+
module TapOut::Reporters
|
4
|
+
|
5
|
+
# Tap Reporter
|
6
|
+
class Tap < Abstract
|
7
|
+
|
8
|
+
#
|
9
|
+
def start_suite(entry)
|
10
|
+
@start = Time.now
|
11
|
+
@i = 0
|
12
|
+
#n = 0
|
13
|
+
#suite.concerns.each{ |f| f.concerns.each { |s| n += s.ok.size } }
|
14
|
+
puts "1..#{entry['count']}"
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
def start_case(entry)
|
19
|
+
#$stdout.puts concern.label.ansi(:bold)
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
#def start_ok(ok)
|
24
|
+
# @i += 1
|
25
|
+
#end
|
26
|
+
|
27
|
+
#
|
28
|
+
def pass(entry)
|
29
|
+
super(entry)
|
30
|
+
|
31
|
+
#desc = entry['message'] #+ " #{ok.arguments.inspect}"
|
32
|
+
|
33
|
+
puts "ok #{entry['index']} - #{entry['label']}"
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
def fail(entry)
|
38
|
+
super(entry)
|
39
|
+
|
40
|
+
#desc = #ok.concern.label + " #{ok.arguments.inspect}"
|
41
|
+
|
42
|
+
body = []
|
43
|
+
body << "FAIL #{entry['file']}:#{entry['line']}" #clean_backtrace(exception.backtrace)[0]
|
44
|
+
body << "#{entry['message']}"
|
45
|
+
body << code_snippet(entry)
|
46
|
+
body = body.join("\n").gsub(/^/, ' # ')
|
47
|
+
|
48
|
+
puts "not ok #{entry['index']} - #{entry['label']}"
|
49
|
+
puts body
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
def error(entry)
|
54
|
+
super(entry)
|
55
|
+
|
56
|
+
#desc = ok.concern.label + " #{ok.arguments.inspect}"
|
57
|
+
|
58
|
+
body = []
|
59
|
+
body << "ERROR #{entry['file']}:#{entry['line']}" #clean_backtrace(exception.backtrace)[0..2].join(" \n")
|
60
|
+
#body << "#{exception.class}: #{entry['message']}"
|
61
|
+
body << "#{entry['message']}"
|
62
|
+
body << ""
|
63
|
+
body << code_snippet(entry)
|
64
|
+
body << ""
|
65
|
+
body = body.join("\n").gsub(/^/, ' # ')
|
66
|
+
|
67
|
+
puts "not ok #{entry['index']} - #{entry['label']}"
|
68
|
+
puts body
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
#def pending(ok, exception)
|
73
|
+
# puts "not ok #{@i} - #{unit.description}"
|
74
|
+
# puts " PENDING"
|
75
|
+
# puts " #{exception.backtrace[1]}"
|
76
|
+
#end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'tapout/reporters/abstract'
|
2
|
+
|
3
|
+
module TapOut::Reporters
|
4
|
+
|
5
|
+
# Verbose reporter.
|
6
|
+
class Verbose < Abstract
|
7
|
+
|
8
|
+
#
|
9
|
+
def start_suite(entry)
|
10
|
+
@start_time = Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
def start_case(entry)
|
15
|
+
$stdout.puts entry['label'].ansi(:bold)
|
16
|
+
end
|
17
|
+
|
18
|
+
def pass(entry)
|
19
|
+
super(entry)
|
20
|
+
$stdout.puts "* " + entry['label'].ansi(:green) + " #{entry['source']}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def fail(entry)
|
24
|
+
super(entry)
|
25
|
+
$stdout.puts "* " + entry['label'].ansi(:red) + " #{entry['source']}"
|
26
|
+
$stdout.puts
|
27
|
+
$stdout.puts " #{entry['message']}"
|
28
|
+
#$stdout.puts " " + ok.caller #clean_backtrace(exception.backtrace)[0]
|
29
|
+
$stdout.puts
|
30
|
+
$stdout.puts code_snippet(entry)
|
31
|
+
$stdout.puts
|
32
|
+
end
|
33
|
+
|
34
|
+
def err(entry)
|
35
|
+
super(entry)
|
36
|
+
$stdout.puts "* " + entry['label'].ansi(:yellow) + " #{entry['source']}"
|
37
|
+
$stdout.puts
|
38
|
+
$stdout.puts " #{entry['message']}" # error class?
|
39
|
+
#$stdout.puts " " + ok.caller #clean_backtrace(exception.backtrace)[0..2].join(" \n")
|
40
|
+
$stdout.puts
|
41
|
+
$stdout.puts code_snippet(entry)
|
42
|
+
$stdout.puts
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
def finish_suite(entry)
|
47
|
+
#$stderr.puts
|
48
|
+
$stdout.print tally(entry)
|
49
|
+
$stdout.puts " [%0.4fs] " % [Time.now - @start_time]
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'tapout/version'
|
2
|
+
|
3
|
+
module TapOut
|
4
|
+
|
5
|
+
# The TAP Legacy Adapter transforms traditional TAP format to
|
6
|
+
# modern TAP-Y format.
|
7
|
+
#
|
8
|
+
# NOTE: This is still a work in progress.
|
9
|
+
#
|
10
|
+
# TODO: Add support for TAP-J.
|
11
|
+
|
12
|
+
class TAPLegacyAdapter
|
13
|
+
|
14
|
+
#
|
15
|
+
def initialize(input)
|
16
|
+
@input = input
|
17
|
+
reset
|
18
|
+
end
|
19
|
+
|
20
|
+
# Reset state.
|
21
|
+
def reset
|
22
|
+
@head = false
|
23
|
+
@state = nil
|
24
|
+
@entries = []
|
25
|
+
@cache = []
|
26
|
+
end
|
27
|
+
|
28
|
+
# We need to keep an internal list of all entries
|
29
|
+
# in order to create a proper footer.
|
30
|
+
attr :entries
|
31
|
+
|
32
|
+
# Convert input stream to TAP-Y string.
|
33
|
+
def to_s
|
34
|
+
self | ""
|
35
|
+
end
|
36
|
+
|
37
|
+
# Route stream to an array of entires.
|
38
|
+
def to_a
|
39
|
+
self | []
|
40
|
+
end
|
41
|
+
|
42
|
+
# Convert input stream to TAP-Y and *pipe* to +output+ stream.
|
43
|
+
def |(output)
|
44
|
+
@out = output
|
45
|
+
reset
|
46
|
+
while line = @input.gets
|
47
|
+
self << line
|
48
|
+
end
|
49
|
+
self << nil
|
50
|
+
return @out
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
def <<(line)
|
55
|
+
case line
|
56
|
+
when nil
|
57
|
+
parse(@cache)
|
58
|
+
@state = :footer
|
59
|
+
finish
|
60
|
+
when /^\d+\.\.\d+/
|
61
|
+
#parse(@cache) if @state != :plan
|
62
|
+
return if @head
|
63
|
+
@head = true
|
64
|
+
@state = :plan
|
65
|
+
@cache << line
|
66
|
+
when /^ok/
|
67
|
+
parse(@cache) #if @state != :ok
|
68
|
+
@state = :ok
|
69
|
+
@cache << line
|
70
|
+
when /^not\ ok/
|
71
|
+
parse(@cache) #if @state != :not_ok
|
72
|
+
@state = :not_ok
|
73
|
+
@cache << line
|
74
|
+
when /^\#/
|
75
|
+
parse(@cache) if @state != :comment
|
76
|
+
@state = :comment
|
77
|
+
@cache << line
|
78
|
+
else
|
79
|
+
@cache << line
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
def parse(cache)
|
85
|
+
case @state
|
86
|
+
when nil
|
87
|
+
return
|
88
|
+
when :plan
|
89
|
+
line = cache[0]
|
90
|
+
md = /^(\d+)\.\.(\d+)\s*$/.match(line)
|
91
|
+
count = md[2].to_i - md[1].to_i + 1
|
92
|
+
entry = {'count'=> count, 'type'=>'header', 'version'=>TAP_Y_VERSION}
|
93
|
+
when :ok
|
94
|
+
line = cache[0]
|
95
|
+
md = /^ok\s+(\d+)\s*\-?\s*(.*?)($|#)/.match(line)
|
96
|
+
entry = {'type'=>'test','status'=>'pass','index'=>md[1].to_i, 'label'=>md[2]}
|
97
|
+
when :not_ok
|
98
|
+
line = cache[0]
|
99
|
+
yaml = cache[1..-2].join('')
|
100
|
+
data = YAML.load(yaml)
|
101
|
+
md = /^not ok\s+(\d+)\s*\-?\s*(.*?)($|#)/.match(line)
|
102
|
+
entry = convert_not_ok(md[1], md[2], data)
|
103
|
+
when :comment
|
104
|
+
desc = cache.map{ |c| c.sub(/^\#\s{0,1}/, '') }.join("\n")
|
105
|
+
entry = {'type'=>'note', 'description'=>desc.rstrip}
|
106
|
+
end
|
107
|
+
output(entry)
|
108
|
+
@cache = []
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
def output(entry)
|
113
|
+
@entries << entry
|
114
|
+
case @out
|
115
|
+
when String, IO
|
116
|
+
@out << entry.to_yaml
|
117
|
+
else
|
118
|
+
@out << entry
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
def finish
|
124
|
+
output(make_footer)
|
125
|
+
case @out
|
126
|
+
when String, IO
|
127
|
+
@out << '...'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
#
|
134
|
+
def convert_not_ok(number, label, metainfo)
|
135
|
+
entry = {}
|
136
|
+
entry['type'] = 'test'
|
137
|
+
entry['status'] = 'fail'
|
138
|
+
entry['index'] = number.to_i
|
139
|
+
entry['label'] = label
|
140
|
+
if metainfo
|
141
|
+
entry['file'] = metainfo['file']
|
142
|
+
entry['line'] = metainfo['line']
|
143
|
+
entry['expected'] = metainfo['wanted']
|
144
|
+
entry['returned'] = metainfo['found']
|
145
|
+
entry['description'] = metainfo['description']
|
146
|
+
entry['source'] = metainfo['raw_test']
|
147
|
+
entry['extra'] = metainfo['extensions']
|
148
|
+
end
|
149
|
+
entry
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
def make_footer
|
154
|
+
groups = @entries.group_by{ |e| e['status'] }
|
155
|
+
|
156
|
+
entry = {}
|
157
|
+
entry['count'] = @count
|
158
|
+
entry['type'] = 'footer'
|
159
|
+
entry['tally'] = {
|
160
|
+
'pass' => (groups['pass'] || []).size,
|
161
|
+
'fail' => (groups['fail'] || []).size
|
162
|
+
}
|
163
|
+
entry
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|