pretty_test 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/pretty_test.rb +3 -1
- data/lib/pretty_test/tap.rb +122 -0
- data/lib/pretty_test/version.rb +1 -1
- data/pretty_test.gemspec +3 -0
- metadata +26 -4
- data/lib/pretty_test/mini_test.rb +0 -137
data/lib/pretty_test.rb
CHANGED
@@ -0,0 +1,122 @@
|
|
1
|
+
require "minitap"
|
2
|
+
module PrettyTest
|
3
|
+
|
4
|
+
class Tap < ::MiniTest::MiniTap
|
5
|
+
|
6
|
+
SKIP_FORMAT = "\e[33m[SKIPPED] %s: %s\e[0m\n%s\n%s"
|
7
|
+
FAILURE_FORMAT = "\e[31m\e[1m[FAILURE] %s: %s\e[0m\n%s\n%s"
|
8
|
+
ERROR_FORMAT = "\e[31m\e[1m[ERROR] %s: %s\e[0m\n\e[31m%s: %s\e[0m\n%s"
|
9
|
+
STATUS_FORMAT = "\e[2K\r\e[?7l\e[1m\e[37m(%.1fs) \e[32m%d/%d tests\e[37m, \e[36m%d assertions\e[37m, \e[31m%d errors\e[37m, \e[31m%d failures\e[37m, \e[33m%d skips \e[37m%s\e[?7h\e[0m"
|
10
|
+
|
11
|
+
attr_accessor :started_at, :progress, :suite_name, :test_name
|
12
|
+
|
13
|
+
def tapout_before_suites(suites, type)
|
14
|
+
@started_at = Time.now
|
15
|
+
@progress = 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def tapout_before_suite(suite)
|
19
|
+
@suite_name = pretty_suite_name(suite.name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def tapout_before_test(suite, test)
|
23
|
+
@test_name = pretty_test_name(test)
|
24
|
+
remove_status
|
25
|
+
update_status("#{suite_name}: #{test_name}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def tapout_pass(suite, test, test_runner)
|
29
|
+
@progress += 1
|
30
|
+
update_status("")
|
31
|
+
end
|
32
|
+
|
33
|
+
def tapout_skip(suite, test, test_runner)
|
34
|
+
@progress += 1
|
35
|
+
error = test_runner.exception
|
36
|
+
test_name = pretty_test_name(test)
|
37
|
+
location = pretty_location(error)
|
38
|
+
message = error.message.strip
|
39
|
+
print_error SKIP_FORMAT, suite_name, test_name, message, location
|
40
|
+
end
|
41
|
+
|
42
|
+
def tapout_failure(suite, test, test_runner)
|
43
|
+
@progress += 1
|
44
|
+
error = test_runner.exception
|
45
|
+
test_name = pretty_test_name(test)
|
46
|
+
location = pretty_location(error)
|
47
|
+
message = error.message.strip
|
48
|
+
print_error FAILURE_FORMAT, suite_name, test_name, message, location
|
49
|
+
end
|
50
|
+
|
51
|
+
def tapout_error(suite, test, test_runner)
|
52
|
+
@progress += 1
|
53
|
+
error = test_runner.exception
|
54
|
+
test_name = pretty_test_name(test)
|
55
|
+
trace = pretty_trace(error)
|
56
|
+
print_error ERROR_FORMAT, suite_name, test_name, error.class, error.message, trace
|
57
|
+
end
|
58
|
+
|
59
|
+
def tapout_after_suites(suites, type)
|
60
|
+
update_status
|
61
|
+
puts "\n\nSuite seed: #{options[:seed]}\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def pretty_suite_name(suite)
|
67
|
+
suite = suite.dup
|
68
|
+
suite.gsub!(/(::|_)/, " ")
|
69
|
+
suite.gsub!(/\btest/i, "")
|
70
|
+
suite.gsub!(/test\b/i, "")
|
71
|
+
suite.gsub!(/\b([a-z])/i) { $1.upcase }
|
72
|
+
suite.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1 \2')
|
73
|
+
suite.gsub!(/([a-z\d])([A-Z])/, '\1 \2')
|
74
|
+
suite
|
75
|
+
end
|
76
|
+
|
77
|
+
def pretty_test_name(test)
|
78
|
+
test = test.dup
|
79
|
+
test.gsub!(/^test_/, "")
|
80
|
+
test.gsub!(/_+/, " ")
|
81
|
+
test
|
82
|
+
end
|
83
|
+
|
84
|
+
def pretty_location(e)
|
85
|
+
path, line = location(e)
|
86
|
+
clean_trace_line("\e[1m-> ", path, line)
|
87
|
+
end
|
88
|
+
|
89
|
+
def pretty_trace(e)
|
90
|
+
path, line = location(e)
|
91
|
+
e.backtrace.map { |trace_line|
|
92
|
+
prefix = trace_line.index("#{path}:#{line}") ? "\e[1m-> " : " "
|
93
|
+
file, line = trace_line.sub(/:in .*$/, "").split(":")
|
94
|
+
clean_trace_line(prefix, file, line)
|
95
|
+
}.compact.join("\n")
|
96
|
+
end
|
97
|
+
|
98
|
+
def clean_trace_line(prefix, path, line)
|
99
|
+
case path
|
100
|
+
when %r{^#{Dir.pwd}/(.+?)/(.+)$} then "\e[37m#{prefix}[#{$1}] #{$2}:#{line}\e[0m"
|
101
|
+
when %r{^.*/gems/(minitap|minitest)-.+/(.+)$} then nil
|
102
|
+
when %r{^.*/gems/(.+?)/(.+)$} then "\e[36m#{prefix}[#{$1}] #{$2}:#{line}\e[0m"
|
103
|
+
when %r{^.*/rubies/(.+?)/(.+)$} then "\e[35m#{prefix}[#{$1}] #{$2}:#{line}\e[0m"
|
104
|
+
else "#{prefix}#{path}:#{line}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def print_error(format, *args)
|
109
|
+
remove_status
|
110
|
+
puts format % args
|
111
|
+
puts
|
112
|
+
end
|
113
|
+
|
114
|
+
def update_status(message = "")
|
115
|
+
print STATUS_FORMAT % [Time.now - started_at, progress, test_count, assertion_count, errors, failures, skips, message]
|
116
|
+
end
|
117
|
+
|
118
|
+
def remove_status
|
119
|
+
print "\e[2K\r"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/pretty_test/version.rb
CHANGED
data/pretty_test.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pretty_test
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,30 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
13
|
-
dependencies:
|
12
|
+
date: 2011-10-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: &70094970515380 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.6'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70094970515380
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: minitap
|
27
|
+
requirement: &70094970513840 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.3'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70094970513840
|
14
36
|
description: Minitest patch for pretty (and useful) output.
|
15
37
|
email:
|
16
38
|
- vladimir@tuzinsky.com
|
@@ -21,7 +43,7 @@ files:
|
|
21
43
|
- .gitignore
|
22
44
|
- Gemfile
|
23
45
|
- lib/pretty_test.rb
|
24
|
-
- lib/pretty_test/
|
46
|
+
- lib/pretty_test/tap.rb
|
25
47
|
- lib/pretty_test/version.rb
|
26
48
|
- pretty_test.gemspec
|
27
49
|
homepage: https://github.com/bobes/pretty_test
|
@@ -1,137 +0,0 @@
|
|
1
|
-
class MiniTest::Unit
|
2
|
-
|
3
|
-
STATUS_FORMAT = "\e[?7l\e[1m\e[37m(%.1fs) \e[32m%d/%d tests\e[37m, \e[36m%d assertions\e[37m, \e[31m%d errors\e[37m, \e[31m%d failures\e[37m, \e[33m%d skips \e[37m%s\e[?7h\e[0m"
|
4
|
-
|
5
|
-
def run(args = [])
|
6
|
-
options = process_args args
|
7
|
-
|
8
|
-
@verbose = options[:verbose]
|
9
|
-
|
10
|
-
filter = options[:filter] || '/./'
|
11
|
-
filter = Regexp.new $1 if filter and filter =~ /\/(.*)\//
|
12
|
-
|
13
|
-
seed = options[:seed]
|
14
|
-
unless seed then
|
15
|
-
srand
|
16
|
-
seed = srand % 0xFFFF
|
17
|
-
end
|
18
|
-
|
19
|
-
srand seed
|
20
|
-
|
21
|
-
@@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
|
22
|
-
|
23
|
-
@started_at = Time.now
|
24
|
-
run_test_suites filter
|
25
|
-
|
26
|
-
help = ["--seed", seed]
|
27
|
-
help.push "--verbose" if @verbose
|
28
|
-
help.push("--name", options[:filter].inspect) if options[:filter]
|
29
|
-
|
30
|
-
@@out.puts "\n\nTest run options: #{help.join(" ")}\n"
|
31
|
-
|
32
|
-
failures + errors if @test_count > 0
|
33
|
-
rescue Interrupt
|
34
|
-
abort "Interrupted"
|
35
|
-
end
|
36
|
-
|
37
|
-
def run_test_suites(filter = /./)
|
38
|
-
@test_count, @assertion_count = 0, 0
|
39
|
-
old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
|
40
|
-
tests = {}
|
41
|
-
TestCase.test_suites.each do |suite|
|
42
|
-
suite_name = suite.name.split("::").map { |token|
|
43
|
-
token =~ /^(test)?(.*?)(test)?$/i && $2.underscore.humanize
|
44
|
-
}.join(" ")
|
45
|
-
suite.test_methods.grep(filter).each do |test|
|
46
|
-
test_name = test =~ /^(test_)?(.*)$/ && $2.underscore.humanize.downcase
|
47
|
-
tests["#{suite_name}: #{test_name}"] = [suite, test]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
@test_count = tests.size
|
51
|
-
tests.keys.each_with_index do |name, index|
|
52
|
-
update_status(index, name)
|
53
|
-
suite, test = tests[name]
|
54
|
-
inst = suite.new(test)
|
55
|
-
inst._assertions = 0
|
56
|
-
klass, method, error = inst.run(self)
|
57
|
-
@assertion_count += inst._assertions
|
58
|
-
remove_status
|
59
|
-
print_error(klass, method, error) if error
|
60
|
-
end
|
61
|
-
update_status(@test_count)
|
62
|
-
@@out.sync = old_sync if @@out.respond_to? :sync=
|
63
|
-
[@test_count, @assertion_count]
|
64
|
-
end
|
65
|
-
|
66
|
-
def puke(klass, method, error)
|
67
|
-
[klass, method, error]
|
68
|
-
end
|
69
|
-
|
70
|
-
def print_error(klass, method, error)
|
71
|
-
report = case error
|
72
|
-
when MiniTest::Skip then
|
73
|
-
@skips += 1
|
74
|
-
"\e[30m\e[43m[SKIPPED] #{pretty_test_name(klass, method)}\e[0m\n#{pretty_skipped_location(error)}\n\e[31m#{error.message}\e[0m"
|
75
|
-
when MiniTest::Assertion then
|
76
|
-
@failures += 1
|
77
|
-
"\e[37m\e[41m\e[1m[FAILURE] #{pretty_test_name(klass, method)}\e[0m\n#{pretty_failure_location(error)}\n#{error.message}"
|
78
|
-
else
|
79
|
-
@errors += 1
|
80
|
-
"\e[37m\e[41m\e[1m[ERROR] #{pretty_test_name(klass, method)}\e[0m\n#{pretty_error_trace(error)}"
|
81
|
-
end
|
82
|
-
@@out.puts "#{report}\n\n"
|
83
|
-
end
|
84
|
-
|
85
|
-
def pretty_test_name(klass, test)
|
86
|
-
suite_name = klass.name.split("::").map { |token|
|
87
|
-
token =~ /^(test)?(.*?)(test)?$/i && $2.underscore.humanize
|
88
|
-
}.join(" ")
|
89
|
-
test_name = test =~ /^(test_)?(.*)$/i && $2.underscore.humanize.downcase
|
90
|
-
"#{suite_name}: #{test_name}"
|
91
|
-
end
|
92
|
-
|
93
|
-
def pretty_skipped_location(error)
|
94
|
-
location = error.backtrace.detect do |line|
|
95
|
-
line =~ %r{^#{Dir.pwd}/}
|
96
|
-
end
|
97
|
-
clean_trace_line("\e[1m-> ", location)
|
98
|
-
end
|
99
|
-
|
100
|
-
def pretty_failure_location(error)
|
101
|
-
location = nil
|
102
|
-
error.backtrace.reverse.each do |line|
|
103
|
-
break if line =~ /in .(assert|refute)_/
|
104
|
-
location = line if line =~ %r{^#{Dir.pwd}/}
|
105
|
-
end
|
106
|
-
clean_trace_line("\e[1m-> ", location)
|
107
|
-
end
|
108
|
-
|
109
|
-
def pretty_error_trace(error)
|
110
|
-
location = error.backtrace.detect do |line|
|
111
|
-
line =~ %r{^#{Dir.pwd}/}
|
112
|
-
end
|
113
|
-
trace = error.backtrace.map do |line|
|
114
|
-
prefix = line == location ? "\e[1m-> " : " "
|
115
|
-
clean_trace_line(prefix, line)
|
116
|
-
end
|
117
|
-
"\e[31m#{error.class}: #{error.message}\e[0m\n#{trace.join("\n")}"
|
118
|
-
end
|
119
|
-
|
120
|
-
def clean_trace_line(prefix, line)
|
121
|
-
case line
|
122
|
-
when %r{^#{Dir.pwd}/(.+?)/(.+)$} then "\e[37m#{prefix}[#{$1}] #{$2}\e[0m"
|
123
|
-
when %r{^.*/gems/(.+?)/(.+)$} then "\e[36m#{prefix}[#{$1}] #{$2}\e[0m"
|
124
|
-
when %r{^.*/rubies/(.+?)/(.+)$} then "\e[35m#{prefix}[#{$1}] #{$2}\e[0m"
|
125
|
-
else "#{prefix}#{line}"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def update_status(index, test_name = nil)
|
130
|
-
status = STATUS_FORMAT % [Time.now - @started_at, index, @test_count, @assertion_count, @errors, @failures, @skips, test_name]
|
131
|
-
@@out.print status
|
132
|
-
end
|
133
|
-
|
134
|
-
def remove_status
|
135
|
-
@@out.print "\e[2K\r"
|
136
|
-
end
|
137
|
-
end
|