minitest-bender 0.0.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/CHANGELOG.md +15 -1
- data/Gemfile +1 -1
- data/README.md +37 -6
- data/lib/minitest-bender/colorizer.rb +61 -0
- data/lib/minitest-bender/configuration.rb +174 -0
- data/lib/minitest-bender/printers/plain.rb +29 -0
- data/lib/minitest-bender/printers/with_progress_bar.rb +115 -0
- data/lib/minitest-bender/recorders/grouped_icons.rb +36 -0
- data/lib/minitest-bender/recorders/icons.rb +26 -0
- data/lib/minitest-bender/recorders/none.rb +17 -0
- data/lib/minitest-bender/recorders/progress.rb +25 -0
- data/lib/minitest-bender/recorders/progress_groups.rb +48 -0
- data/lib/minitest-bender/recorders/progress_groups_and_issues.rb +55 -0
- data/lib/minitest-bender/recorders/progress_issues.rb +32 -0
- data/lib/minitest-bender/recorders/progress_verbose.rb +34 -0
- data/lib/minitest-bender/result_context.rb +39 -0
- data/lib/minitest-bender/result_factory.rb +5 -0
- data/lib/minitest-bender/results/base.rb +94 -38
- data/lib/minitest-bender/results/expectation.rb +10 -8
- data/lib/minitest-bender/results/test.rb +21 -8
- data/lib/minitest-bender/sections/activity.rb +95 -0
- data/lib/minitest-bender/sections/issues.rb +22 -0
- data/lib/minitest-bender/sections/sorted_overview.rb +115 -0
- data/lib/minitest-bender/sections/suite_status.rb +72 -0
- data/lib/minitest-bender/sections/time_ranking.rb +49 -0
- data/lib/minitest-bender/states/base.rb +76 -19
- data/lib/minitest-bender/states/failing.rb +11 -8
- data/lib/minitest-bender/states/passing.rb +19 -8
- data/lib/minitest-bender/states/raising.rb +42 -20
- data/lib/minitest-bender/states/skipped.rb +12 -9
- data/lib/minitest-bender/utils.rb +26 -0
- data/lib/minitest-bender/version.rb +1 -1
- data/lib/minitest/bender.rb +166 -77
- data/lib/minitest/bender_plugin.rb +49 -3
- data/lib/minitest_bender.rb +23 -5
- data/minitest-bender.gemspec +6 -6
- metadata +39 -22
@@ -0,0 +1,36 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class GroupedIcons
|
4
|
+
def initialize(io)
|
5
|
+
@printer = Printers::Plain.new(io)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_context(result_context)
|
9
|
+
printer.print_line
|
10
|
+
|
11
|
+
context_path = result_context.path
|
12
|
+
context_separator = result_context.separator
|
13
|
+
prefix = result_context.prefix
|
14
|
+
|
15
|
+
path = context_path[0...-1].join(context_separator)
|
16
|
+
path << context_separator unless path.empty?
|
17
|
+
klass = context_path.last
|
18
|
+
|
19
|
+
printer.print("#{prefix}#{path}#{Colorizer.colorize(klass, :normal, :bold)} ")
|
20
|
+
end
|
21
|
+
|
22
|
+
def print_result(result)
|
23
|
+
printer.print(result.to_icon)
|
24
|
+
printer.advance
|
25
|
+
end
|
26
|
+
|
27
|
+
def print_context_with_results(_result_context, _results)
|
28
|
+
# do_nothing
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :printer
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class Icons
|
4
|
+
def initialize(io)
|
5
|
+
@printer = Printers::Plain.new(io)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_context(_result_context)
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_result(result)
|
13
|
+
printer.print(result.to_icon)
|
14
|
+
printer.advance
|
15
|
+
end
|
16
|
+
|
17
|
+
def print_context_with_results(_result_context, _results)
|
18
|
+
# do_nothing
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :printer
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class None
|
4
|
+
def print_context(_result_context)
|
5
|
+
# do nothing
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_result(_result)
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_context_with_results(_result_context, _results)
|
13
|
+
# do_nothing
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class Progress
|
4
|
+
def initialize(io, total_tests_count)
|
5
|
+
@printer = Printers::WithProgressBar.new(io, total_tests_count)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_context(_result_context)
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_result(result)
|
13
|
+
printer.advance
|
14
|
+
end
|
15
|
+
|
16
|
+
def print_context_with_results(_result_context, _results)
|
17
|
+
# do_nothing
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :printer
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class ProgressGroups
|
4
|
+
def initialize(io, total_tests_count)
|
5
|
+
@printer = Printers::WithProgressBar.new(io, total_tests_count)
|
6
|
+
@total_tests_count = total_tests_count
|
7
|
+
end
|
8
|
+
|
9
|
+
def print_context(_result_context)
|
10
|
+
# do nothing
|
11
|
+
end
|
12
|
+
|
13
|
+
def print_result(result)
|
14
|
+
printer.advance
|
15
|
+
end
|
16
|
+
|
17
|
+
def print_context_with_results(result_context, results)
|
18
|
+
context_path = result_context.path
|
19
|
+
context_separator = result_context.separator
|
20
|
+
prefix = result_context.prefix
|
21
|
+
|
22
|
+
path = context_path[0...-1].join(context_separator)
|
23
|
+
path << context_separator unless path.empty?
|
24
|
+
klass = context_path.last
|
25
|
+
|
26
|
+
printer.print_line("#{prefix}#{counters(result_context)} #{path}#{Colorizer.colorize(klass, :normal, :bold)}")
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :printer, :total_tests_count
|
32
|
+
|
33
|
+
def counters(result_context)
|
34
|
+
states.map do |state|
|
35
|
+
state.colored_icon_with_context_count(result_context, counters_padding_right)
|
36
|
+
end.join(' ')
|
37
|
+
end
|
38
|
+
|
39
|
+
def states
|
40
|
+
@states ||= MinitestBender.states.values
|
41
|
+
end
|
42
|
+
|
43
|
+
def counters_padding_right
|
44
|
+
@counters_padding_right ||= total_tests_count.to_s.size + 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class ProgressGroupsAndIssues
|
4
|
+
def initialize(io, total_tests_count)
|
5
|
+
@printer = Printers::WithProgressBar.new(io, total_tests_count)
|
6
|
+
@total_tests_count = total_tests_count
|
7
|
+
end
|
8
|
+
|
9
|
+
def print_context(_result_context)
|
10
|
+
# do nothing
|
11
|
+
end
|
12
|
+
|
13
|
+
def print_result(result)
|
14
|
+
printer.print_line(result_line(result)) unless result.passed?
|
15
|
+
lines = result.state.detail_lines_without_header(result)
|
16
|
+
printer.print_lines(lines)
|
17
|
+
printer.advance
|
18
|
+
end
|
19
|
+
|
20
|
+
def print_context_with_results(result_context, results)
|
21
|
+
context_path = result_context.path
|
22
|
+
context_separator = result_context.separator
|
23
|
+
prefix = result_context.prefix
|
24
|
+
|
25
|
+
path = context_path[0...-1].join(context_separator)
|
26
|
+
path << context_separator unless path.empty?
|
27
|
+
klass = context_path.last
|
28
|
+
|
29
|
+
printer.print_line("#{prefix}#{counters(result_context)} #{path}#{Colorizer.colorize(klass, :normal, :bold)}")
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :printer, :total_tests_count
|
35
|
+
|
36
|
+
def result_line(result)
|
37
|
+
" #{result.formatted_label_and_time}#{result.formatted_number} #{result.formatted_name_with_context}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def counters(result_context)
|
41
|
+
states.map do |state|
|
42
|
+
state.colored_icon_with_context_count(result_context, counters_padding_right)
|
43
|
+
end.join(' ')
|
44
|
+
end
|
45
|
+
|
46
|
+
def states
|
47
|
+
@states ||= MinitestBender.states.values
|
48
|
+
end
|
49
|
+
|
50
|
+
def counters_padding_right
|
51
|
+
@counters_padding_right ||= total_tests_count.to_s.size + 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class ProgressIssues
|
4
|
+
def initialize(io, total_tests_count)
|
5
|
+
@printer = Printers::WithProgressBar.new(io, total_tests_count)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_context(_result_context)
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_result(result)
|
13
|
+
printer.print_line(result_line(result)) unless result.passed?
|
14
|
+
lines = result.state.detail_lines_without_header(result)
|
15
|
+
printer.print_lines(lines)
|
16
|
+
printer.advance
|
17
|
+
end
|
18
|
+
|
19
|
+
def print_context_with_results(_result_context, _results)
|
20
|
+
# do_nothing
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :printer
|
26
|
+
|
27
|
+
def result_line(result)
|
28
|
+
" #{result.formatted_label_and_time}#{result.formatted_number} #{result.formatted_name_with_context}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module MinitestBender
|
2
|
+
module Recorders
|
3
|
+
class ProgressVerbose
|
4
|
+
def initialize(io, total_tests_count)
|
5
|
+
@printer = Printers::WithProgressBar.new(io, total_tests_count)
|
6
|
+
end
|
7
|
+
|
8
|
+
def print_context(result_context)
|
9
|
+
printer.print_line
|
10
|
+
printer.print_line(Colorizer.colorize(result_context.with_prefix, :normal, :bold))
|
11
|
+
end
|
12
|
+
|
13
|
+
def print_result(result)
|
14
|
+
printer.print_line(result_line(result))
|
15
|
+
lines = result.state.detail_lines_without_header(result)
|
16
|
+
padded_lines = lines.map { |line| " #{line}" }
|
17
|
+
printer.print_lines(padded_lines)
|
18
|
+
printer.advance
|
19
|
+
end
|
20
|
+
|
21
|
+
def print_context_with_results(_result_context, _results)
|
22
|
+
# do_nothing
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :printer
|
28
|
+
|
29
|
+
def result_line(result)
|
30
|
+
" #{result.formatted_label_and_time}#{result.formatted_number} #{result.name}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module MinitestBender
|
5
|
+
class ResultContext < String
|
6
|
+
PREFIX = '• '
|
7
|
+
SEPARATOR = ' ▸ '
|
8
|
+
CLASS_SEPARATOR = '::'
|
9
|
+
|
10
|
+
def initialize(class_name)
|
11
|
+
@class_name = class_name
|
12
|
+
super(path.join(separator))
|
13
|
+
end
|
14
|
+
|
15
|
+
def path
|
16
|
+
class_name.split(class_separator)
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_prefix
|
20
|
+
prefix + self
|
21
|
+
end
|
22
|
+
|
23
|
+
def separator
|
24
|
+
SEPARATOR
|
25
|
+
end
|
26
|
+
|
27
|
+
def prefix
|
28
|
+
PREFIX
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :class_name
|
34
|
+
|
35
|
+
def class_separator
|
36
|
+
CLASS_SEPARATOR
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -26,6 +26,11 @@ module MinitestBender
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def parsed_name(minitest_result)
|
29
|
+
if minitest_result.name.is_a?(Class)
|
30
|
+
# something went wrong inside minitest (infinite loop?)
|
31
|
+
raise minitest_result.failures[0].error
|
32
|
+
end
|
33
|
+
|
29
34
|
minitest_result.name.match(RESULT_NAME_REGEXP)
|
30
35
|
end
|
31
36
|
end
|
@@ -1,77 +1,133 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'forwardable'
|
5
|
+
|
1
6
|
module MinitestBender
|
2
7
|
module Results
|
3
8
|
class Base
|
4
9
|
extend Forwardable
|
5
10
|
def_delegators :@minitest_result, :passed?, :skipped?, :assertions, :failures, :time
|
11
|
+
attr_reader :state, :execution_order
|
12
|
+
|
13
|
+
NAME_PREFIX = '♦'
|
6
14
|
|
7
15
|
def initialize(minitest_result)
|
8
16
|
@minitest_result = minitest_result
|
9
17
|
@state = MinitestBender.states.fetch(minitest_result.result_code)
|
18
|
+
@execution_order = state.add_result(self).size
|
10
19
|
end
|
11
20
|
|
12
21
|
def context
|
13
|
-
@context ||=
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end.gsub('::', ' > ')
|
22
|
+
@context ||= ResultContext.new(adjusted_class_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_icon
|
26
|
+
state.colored_icon
|
19
27
|
end
|
20
28
|
|
21
|
-
def
|
22
|
-
|
29
|
+
def name_sort_key
|
30
|
+
name
|
23
31
|
end
|
24
32
|
|
25
|
-
def
|
26
|
-
"
|
33
|
+
def formatted_name_with_context
|
34
|
+
"#{Colorizer.colorize(context, :normal)} #{name_prefix} #{Colorizer.colorize(name, :normal, :bold)}"
|
27
35
|
end
|
28
36
|
|
29
37
|
def rerun_line(padding)
|
30
38
|
unformatted = "Rerun: #{rerun_command}"
|
31
|
-
"#{padding}#{
|
39
|
+
"#{padding}#{Colorizer.colorize(unformatted, :tests)}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def formatted_label
|
43
|
+
state.formatted_label
|
44
|
+
end
|
45
|
+
|
46
|
+
def time_with_unit_and_padding_right
|
47
|
+
time_in_s = time
|
48
|
+
case time_in_s
|
49
|
+
when 0...1
|
50
|
+
sprintf('%.0fms ', time_in_s * 1000)
|
51
|
+
when 1...10
|
52
|
+
sprintf('%.2fs ', time_in_s)
|
53
|
+
when 10...100
|
54
|
+
sprintf('%.1fs ', time_in_s)
|
55
|
+
when 100...10000
|
56
|
+
sprintf('%.0fs ', time_in_s)
|
57
|
+
else
|
58
|
+
sprintf('%.0fs', time_in_s)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def formatted_time
|
63
|
+
Colorizer.colorize(time_with_unit_and_padding_right.rjust(6), :time)
|
64
|
+
end
|
65
|
+
|
66
|
+
def formatted_label_and_time
|
67
|
+
"#{formatted_label} #{formatted_time}"
|
32
68
|
end
|
33
69
|
|
34
|
-
def
|
35
|
-
state.
|
70
|
+
def formatted_message
|
71
|
+
state.formatted_message(self)
|
72
|
+
end
|
73
|
+
|
74
|
+
def file_path
|
75
|
+
@file_path ||= source_location[0]
|
76
|
+
end
|
77
|
+
|
78
|
+
def source_line_number
|
79
|
+
@source_line_number ||= source_location[1]
|
36
80
|
end
|
37
81
|
|
38
|
-
|
39
|
-
|
82
|
+
# credit where credit is due: minitest-line
|
83
|
+
def source_location
|
84
|
+
if minitest_at_least_5_11?
|
85
|
+
minitest_result.source_location
|
86
|
+
else
|
87
|
+
minitest_result.method(minitest_result.name).source_location rescue ['unknown', -1]
|
88
|
+
end
|
40
89
|
end
|
41
90
|
|
42
91
|
private
|
43
92
|
|
44
|
-
attr_reader :minitest_result
|
93
|
+
attr_reader :minitest_result
|
45
94
|
|
46
|
-
def
|
47
|
-
|
95
|
+
def adjusted_class_name
|
96
|
+
class_name
|
48
97
|
end
|
49
98
|
|
50
|
-
def
|
51
|
-
|
99
|
+
def class_name
|
100
|
+
if minitest_at_least_5_11?
|
101
|
+
minitest_result.klass
|
102
|
+
else
|
103
|
+
minitest_result.class.name
|
104
|
+
end
|
52
105
|
end
|
53
106
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
when 100...10000
|
65
|
-
sprintf('%.0fs ', time_in_s)
|
66
|
-
else
|
67
|
-
sprintf('%.0fs', time_in_s)
|
68
|
-
end
|
69
|
-
Colorin.grey_700(time_with_unit.rjust(6))
|
107
|
+
def minitest_at_least_5_11?
|
108
|
+
@minitest_at_least_5_11 ||= Gem.loaded_specs['minitest'].version >= Gem::Version.new('5.11')
|
109
|
+
end
|
110
|
+
|
111
|
+
def class_separator
|
112
|
+
CLASS_SEPARATOR
|
113
|
+
end
|
114
|
+
|
115
|
+
def name_prefix
|
116
|
+
NAME_PREFIX
|
70
117
|
end
|
71
118
|
|
72
119
|
def rerun_command
|
73
|
-
relative_location = state.test_location(self)
|
74
|
-
|
120
|
+
return unless (relative_location = state.test_location(self))
|
121
|
+
|
122
|
+
relative_location = relative_location.split(':').first
|
123
|
+
|
124
|
+
stem = Minitest::Bender.configuration.rerun_command_stem
|
125
|
+
|
126
|
+
if stem.include?('rake')
|
127
|
+
"#{stem} TEST=#{relative_location} TESTOPTS=\"--name=#{name_for_rerun_command}\""
|
128
|
+
else
|
129
|
+
"#{stem} #{relative_location} --name=#{name_for_rerun_command}"
|
130
|
+
end
|
75
131
|
end
|
76
132
|
end
|
77
133
|
end
|