pretty_test 0.2.3 → 1.0.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.
- checksums.yaml +4 -4
- data/lib/pretty_test.rb +3 -3
- data/lib/pretty_test/reporter.rb +145 -0
- data/pretty_test.gemspec +2 -2
- data/test/test_reporter.rb +40 -0
- metadata +8 -6
- data/lib/pretty_test/runner.rb +0 -183
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99fcfccadd470fa6e50f1fe9947fd4ceaa42a646
|
4
|
+
data.tar.gz: 6f8cc428dde9fdea68dd75fea69262074f263b4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26cf7172794a146c034e151639db6f193518d735ef329e432527966a38244aef64f401fff3cc60191436c5d6e398df1b717bfd108b2de25c78122d3854ae816c
|
7
|
+
data.tar.gz: 6e45fa16eafc958c076a3059eb29fca0678dc9329ce14798d8fdac03bae15ad44dfd9d02650c8c9088392ffcc735822d0da589f71d63db6c8d9e638fa89c057e
|
data/lib/pretty_test.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
if STDOUT.tty?
|
2
|
+
require "pretty_test/reporter"
|
3
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require "minitest"
|
2
|
+
|
3
|
+
module Minitest
|
4
|
+
|
5
|
+
class ProgressReporter
|
6
|
+
|
7
|
+
SKIP_FORMAT = "\e[33m[SKIPPED] %s\e[0m\n%s\n%s"
|
8
|
+
FAILURE_FORMAT = "\e[31m[FAILURE] %s\e[0m\n\e[31m%s: %s\e[0m\n%s"
|
9
|
+
ERROR_FORMAT = "\e[31m[ERROR] %s\e[0m\n\e[31m%s: %s\e[0m\n%s"
|
10
|
+
STATUS_FORMAT = "\e[2K\r\e[?7l\e[37m(%.1fs) \e[32m%d/%d tests (%d%%)\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[?7h\e[0m"
|
11
|
+
|
12
|
+
attr_accessor :started_at, :tests, :assertions, :completed, :failures, :errors, :skips
|
13
|
+
|
14
|
+
def initialize(io = $stdout, options = {})
|
15
|
+
super
|
16
|
+
|
17
|
+
self.started_at = nil
|
18
|
+
self.completed = 0
|
19
|
+
self.assertions = 0
|
20
|
+
self.failures = 0
|
21
|
+
self.errors = 0
|
22
|
+
self.skips = 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def start
|
26
|
+
self.started_at = Time.now
|
27
|
+
suites = ::Minitest::Runnable.runnables
|
28
|
+
self.tests = 0
|
29
|
+
suites.each do |suite|
|
30
|
+
self.tests += suite.runnable_methods.count
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def record(result)
|
35
|
+
super
|
36
|
+
test_name = "#{result.class.name}##{result.name}"
|
37
|
+
@completed += 1
|
38
|
+
@assertions += result.assertions
|
39
|
+
case exception = result.failure
|
40
|
+
when nil then pass
|
41
|
+
when ::MiniTest::Skip then skip(test_name, exception)
|
42
|
+
when ::MiniTest::Assertion then failure(test_name, exception)
|
43
|
+
else error(test_name, exception)
|
44
|
+
end
|
45
|
+
update_status
|
46
|
+
end
|
47
|
+
|
48
|
+
def report
|
49
|
+
if tests > 0
|
50
|
+
update_status
|
51
|
+
end
|
52
|
+
if errors + failures == 0
|
53
|
+
io.puts " \e[32m----- PASSED! -----\e[0m"
|
54
|
+
else
|
55
|
+
io.puts " \e[31m----- FAILED! -----\e[0m"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def passed?
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def pass
|
64
|
+
end
|
65
|
+
|
66
|
+
def skip(test_name, exception)
|
67
|
+
self.skips += 1
|
68
|
+
location = pretty_location(exception)
|
69
|
+
message = exception.message.strip
|
70
|
+
print_error SKIP_FORMAT, test_name, message, location
|
71
|
+
end
|
72
|
+
|
73
|
+
def failure(test_name, exception)
|
74
|
+
self.failures += 1
|
75
|
+
index = find_assertion_index(exception)
|
76
|
+
trace = pretty_trace(exception, index)
|
77
|
+
print_error FAILURE_FORMAT, test_name, exception.class, exception.message, trace
|
78
|
+
end
|
79
|
+
|
80
|
+
def error(test_name, exception)
|
81
|
+
self.errors += 1
|
82
|
+
index = find_exception_index(exception)
|
83
|
+
trace = pretty_trace(exception, index)
|
84
|
+
print_error ERROR_FORMAT, test_name, exception.class, exception.message, trace
|
85
|
+
end
|
86
|
+
|
87
|
+
def pretty_location(e)
|
88
|
+
path, line = location(e)
|
89
|
+
clean_trace_line("\e[1m-> ", path, line)
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_assertion_index(error)
|
93
|
+
index = error.backtrace.rindex { |trace| trace =~ /:in .(assert|refute|flunk|pass|fail|raise|must|wont)/ }
|
94
|
+
index ? index + 1 : find_exception_index(error)
|
95
|
+
end
|
96
|
+
|
97
|
+
def find_exception_index(error)
|
98
|
+
error.backtrace.index { |trace| trace.index(Dir.pwd) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def pretty_trace(error, location_index)
|
102
|
+
lines = []
|
103
|
+
backtrace = error.backtrace
|
104
|
+
entry_point = backtrace.reverse.detect { |trace| trace.starts_with?(Dir.pwd) }
|
105
|
+
backtrace.each_with_index do |trace, index|
|
106
|
+
prefix = index == location_index ? "\e[1m-> " : " "
|
107
|
+
trace_file, trace_line, trace_method = trace.split(":", 3)
|
108
|
+
lines << clean_trace_line(prefix, trace_file, trace_line, trace_method)
|
109
|
+
break if trace == entry_point
|
110
|
+
end
|
111
|
+
lines.compact.join("\n")
|
112
|
+
end
|
113
|
+
|
114
|
+
def clean_trace_line(prefix, path, line, method = nil)
|
115
|
+
case path
|
116
|
+
when %r{^#{Dir.pwd}/([^/]+)/(.+)$} then "\e[37m#{prefix}[#{$1}] #{$2}:#{line} #{method}\e[0m"
|
117
|
+
when %r{^.*/(ruby-[^/]+)/(bin/.+)$} then "\e[35m#{prefix}[#{$1}] #{$2}:#{line} #{method}\e[0m"
|
118
|
+
when %r{^.*/gems/(minitap|minitest)-.+/(.+)$} then nil
|
119
|
+
when %r{^.*/gems/([^/]+)/(.+)$} then "\e[36m#{prefix}[#{$1}] #{$2}:#{line} #{method}\e[0m"
|
120
|
+
else "#{prefix}#{path}:#{line}\e[0m"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def print_error(format, *args)
|
125
|
+
remove_status
|
126
|
+
io.puts format % args
|
127
|
+
io.puts
|
128
|
+
end
|
129
|
+
|
130
|
+
def update_status
|
131
|
+
running_time = Time.now - started_at
|
132
|
+
progress = 100.0 * completed / tests
|
133
|
+
io.print STATUS_FORMAT % [running_time, completed, tests, progress, assertions, errors, failures, skips]
|
134
|
+
end
|
135
|
+
|
136
|
+
def remove_status
|
137
|
+
io.print "\e[2K\r"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class SummaryReporter
|
142
|
+
def report
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/pretty_test.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
12
12
|
gem.name = "pretty_test"
|
13
13
|
gem.require_paths = ["lib"]
|
14
|
-
gem.version = "0.
|
14
|
+
gem.version = "1.0.0"
|
15
15
|
|
16
|
-
gem.add_dependency "minitest", "~>
|
16
|
+
gem.add_dependency "minitest", "~> 5"
|
17
17
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "stringio"
|
2
|
+
require "pretty_test/reporter"
|
3
|
+
|
4
|
+
class TestReporter
|
5
|
+
|
6
|
+
def self.run
|
7
|
+
new.run
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
output = StringIO.new("")
|
12
|
+
reporter = PrettyTest::Reporter.new(output)
|
13
|
+
|
14
|
+
klass = Class.new(::Minitest::Test) do
|
15
|
+
|
16
|
+
def self.name
|
17
|
+
"SomeTest"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_pass
|
21
|
+
assert true
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_fail
|
25
|
+
assert false
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_error
|
29
|
+
raise "qwe"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
reporter.start
|
34
|
+
klass.run reporter, {}
|
35
|
+
reporter.report
|
36
|
+
puts output.string
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
TestReporter.run
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pretty_test
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Bobes Tuzinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5'
|
27
27
|
description: Minitest patch for pretty (and useful) output.
|
28
28
|
email:
|
29
29
|
- vladimir@tuzinsky.com
|
@@ -35,8 +35,9 @@ files:
|
|
35
35
|
- Gemfile
|
36
36
|
- README.md
|
37
37
|
- lib/pretty_test.rb
|
38
|
-
- lib/pretty_test/
|
38
|
+
- lib/pretty_test/reporter.rb
|
39
39
|
- pretty_test.gemspec
|
40
|
+
- test/test_reporter.rb
|
40
41
|
homepage: https://github.com/bobes/pretty_test
|
41
42
|
licenses:
|
42
43
|
- MIT
|
@@ -61,4 +62,5 @@ rubygems_version: 2.2.2
|
|
61
62
|
signing_key:
|
62
63
|
specification_version: 4
|
63
64
|
summary: Minitest patch for pretty output
|
64
|
-
test_files:
|
65
|
+
test_files:
|
66
|
+
- test/test_reporter.rb
|
data/lib/pretty_test/runner.rb
DELETED
@@ -1,183 +0,0 @@
|
|
1
|
-
require "minitest/unit"
|
2
|
-
|
3
|
-
module PrettyTest
|
4
|
-
|
5
|
-
class Runner < ::MiniTest::Unit
|
6
|
-
|
7
|
-
SKIP_FORMAT = "\e[33m[SKIPPED] %s: %s\e[0m\n%s\n%s"
|
8
|
-
FAILURE_FORMAT = "\e[31m[FAILURE] %s: %s\e[0m\n\e[31m%s: %s\e[0m\n%s"
|
9
|
-
ERROR_FORMAT = "\e[31m[ERROR] %s: %s\e[0m\n\e[31m%s: %s\e[0m\n%s"
|
10
|
-
STATUS_FORMAT = "\e[2K\r\e[?7l\e[37m(%.1fs) \e[32m%d/%d tests (%d%%)\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"
|
11
|
-
|
12
|
-
attr_accessor :started_at, :test_count, :assertion_count, :completed, :suite_name, :test_name, :test_record
|
13
|
-
|
14
|
-
def _run_anything(type)
|
15
|
-
suites = TestCase.send("#{type}_suites")
|
16
|
-
_run_suites(suites, type)
|
17
|
-
end
|
18
|
-
|
19
|
-
def _run_suites(suites, type)
|
20
|
-
before_suites(suites, type)
|
21
|
-
super
|
22
|
-
ensure
|
23
|
-
after_suites(suites, type)
|
24
|
-
end
|
25
|
-
|
26
|
-
def _run_suite(suite, type)
|
27
|
-
tests = suite.send("#{type}_methods")
|
28
|
-
if tests.any?
|
29
|
-
before_suite(suite)
|
30
|
-
tests.each do |test|
|
31
|
-
run_test(suite, test)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def record(suite, test, assertions, time, exception)
|
37
|
-
@test_record = TestRecord.new(suite, test, assertions, time, exception)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def before_suites(suites, type)
|
43
|
-
@started_at = Time.now
|
44
|
-
@test_count = suites.map { |suite| suite.send("#{type}_methods").count }.sum
|
45
|
-
@completed = 0
|
46
|
-
@assertion_count = 0
|
47
|
-
end
|
48
|
-
|
49
|
-
def before_suite(suite)
|
50
|
-
@suite_name = pretty_suite_name(suite.name || suite.to_s)
|
51
|
-
end
|
52
|
-
|
53
|
-
def run_test(suite, test)
|
54
|
-
before_test(test)
|
55
|
-
instance = suite.new(test)
|
56
|
-
instance._assertions = 0
|
57
|
-
instance.run(self)
|
58
|
-
@assertion_count += instance._assertions
|
59
|
-
ensure
|
60
|
-
after_test
|
61
|
-
end
|
62
|
-
|
63
|
-
def before_test(test)
|
64
|
-
@test_name = pretty_test_name(test)
|
65
|
-
remove_status
|
66
|
-
update_status("#{suite_name}: #{test_name}")
|
67
|
-
end
|
68
|
-
|
69
|
-
def after_test
|
70
|
-
@completed += 1
|
71
|
-
case exception = test_record && test_record.exception
|
72
|
-
when nil then pass
|
73
|
-
when ::MiniTest::Skip then skip(exception)
|
74
|
-
when ::MiniTest::Assertion then failure(exception)
|
75
|
-
else error(exception)
|
76
|
-
end
|
77
|
-
update_status("")
|
78
|
-
end
|
79
|
-
|
80
|
-
def pass
|
81
|
-
end
|
82
|
-
|
83
|
-
def skip(exception)
|
84
|
-
location = pretty_location(exception)
|
85
|
-
message = exception.message.strip
|
86
|
-
print_error SKIP_FORMAT, suite_name, test_name, message, location
|
87
|
-
end
|
88
|
-
|
89
|
-
def failure(exception)
|
90
|
-
index = find_assertion_index(exception)
|
91
|
-
trace = pretty_trace(exception, index)
|
92
|
-
print_error FAILURE_FORMAT, suite_name, test_name, exception.class, exception.message, trace
|
93
|
-
end
|
94
|
-
|
95
|
-
def error(exception)
|
96
|
-
index = find_exception_index(exception)
|
97
|
-
trace = pretty_trace(exception, index)
|
98
|
-
print_error ERROR_FORMAT, suite_name, test_name, exception.class, exception.message, trace
|
99
|
-
end
|
100
|
-
|
101
|
-
def after_suites(suites, type)
|
102
|
-
if test_count > 0
|
103
|
-
update_status
|
104
|
-
end
|
105
|
-
if errors + failures == 0
|
106
|
-
puts " \e[32m----- PASSED! -----\e[0m"
|
107
|
-
else
|
108
|
-
puts " \e[31m----- FAILED! -----\e[0m"
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def pretty_suite_name(suite)
|
113
|
-
suite = suite.dup
|
114
|
-
suite.gsub!(/(::|_)/, " ")
|
115
|
-
suite.gsub!(/\btest/i, "")
|
116
|
-
suite.gsub!(/test\b/i, "")
|
117
|
-
suite.gsub!(/\b([a-z])/i) { $1.upcase }
|
118
|
-
suite.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1 \2')
|
119
|
-
suite.gsub!(/([a-z\d])([A-Z])/, '\1 \2')
|
120
|
-
suite
|
121
|
-
end
|
122
|
-
|
123
|
-
def pretty_test_name(test)
|
124
|
-
test = test.dup
|
125
|
-
test.gsub!(/^test_/, "")
|
126
|
-
test.gsub!(/_+/, " ")
|
127
|
-
test
|
128
|
-
end
|
129
|
-
|
130
|
-
def pretty_location(e)
|
131
|
-
path, line = location(e)
|
132
|
-
clean_trace_line("\e[1m-> ", path, line)
|
133
|
-
end
|
134
|
-
|
135
|
-
def find_assertion_index(error)
|
136
|
-
index = error.backtrace.rindex { |trace| trace =~ /:in .(assert|refute|flunk|pass|fail|raise|must|wont)/ }
|
137
|
-
index ? index + 1 : find_exception_index(error)
|
138
|
-
end
|
139
|
-
|
140
|
-
def find_exception_index(error)
|
141
|
-
error.backtrace.index { |trace| trace.index(Dir.pwd) }
|
142
|
-
end
|
143
|
-
|
144
|
-
def pretty_trace(error, location_index)
|
145
|
-
lines = []
|
146
|
-
error.backtrace.each_with_index do |trace, index|
|
147
|
-
prefix = index == location_index ? "\e[1m-> " : " "
|
148
|
-
trace_file, trace_line, trace_method = trace.split(":", 3)
|
149
|
-
lines << clean_trace_line(prefix, trace_file, trace_line, trace_method)
|
150
|
-
end
|
151
|
-
lines.compact.join("\n")
|
152
|
-
end
|
153
|
-
|
154
|
-
def clean_trace_line(prefix, path, line, method = nil)
|
155
|
-
case path
|
156
|
-
when %r{^#{Dir.pwd}/([^/]+)/(.+)$} then "\e[37m#{prefix}[#{$1}] #{$2}:#{line} #{method}\e[0m"
|
157
|
-
when %r{^.*/(ruby-[^/]+)/(bin/.+)$} then "\e[35m#{prefix}[#{$1}] #{$2}:#{line} #{method}\e[0m"
|
158
|
-
when %r{^.*/gems/(minitap|minitest)-.+/(.+)$} then nil
|
159
|
-
when %r{^.*/gems/([^/]+)/(.+)$} then "\e[36m#{prefix}[#{$1}] #{$2}:#{line} #{method}\e[0m"
|
160
|
-
else "#{prefix}#{path}:#{line}\e[0m"
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def print_error(format, *args)
|
165
|
-
remove_status
|
166
|
-
puts format % args
|
167
|
-
puts
|
168
|
-
end
|
169
|
-
|
170
|
-
def update_status(message = "")
|
171
|
-
running_time = Time.now - started_at
|
172
|
-
progress = 100.0 * completed / test_count
|
173
|
-
print STATUS_FORMAT % [running_time, completed, test_count, progress, assertion_count, errors, failures, skips, message]
|
174
|
-
end
|
175
|
-
|
176
|
-
def remove_status
|
177
|
-
print "\e[2K\r"
|
178
|
-
end
|
179
|
-
|
180
|
-
class TestRecord < Struct.new(:suite, :test, :assertions, :time, :exception)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|