pretty_test 0.0.3 → 0.0.4
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/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
|