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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -1
  3. data/Gemfile +1 -1
  4. data/README.md +37 -6
  5. data/lib/minitest-bender/colorizer.rb +61 -0
  6. data/lib/minitest-bender/configuration.rb +174 -0
  7. data/lib/minitest-bender/printers/plain.rb +29 -0
  8. data/lib/minitest-bender/printers/with_progress_bar.rb +115 -0
  9. data/lib/minitest-bender/recorders/grouped_icons.rb +36 -0
  10. data/lib/minitest-bender/recorders/icons.rb +26 -0
  11. data/lib/minitest-bender/recorders/none.rb +17 -0
  12. data/lib/minitest-bender/recorders/progress.rb +25 -0
  13. data/lib/minitest-bender/recorders/progress_groups.rb +48 -0
  14. data/lib/minitest-bender/recorders/progress_groups_and_issues.rb +55 -0
  15. data/lib/minitest-bender/recorders/progress_issues.rb +32 -0
  16. data/lib/minitest-bender/recorders/progress_verbose.rb +34 -0
  17. data/lib/minitest-bender/result_context.rb +39 -0
  18. data/lib/minitest-bender/result_factory.rb +5 -0
  19. data/lib/minitest-bender/results/base.rb +94 -38
  20. data/lib/minitest-bender/results/expectation.rb +10 -8
  21. data/lib/minitest-bender/results/test.rb +21 -8
  22. data/lib/minitest-bender/sections/activity.rb +95 -0
  23. data/lib/minitest-bender/sections/issues.rb +22 -0
  24. data/lib/minitest-bender/sections/sorted_overview.rb +115 -0
  25. data/lib/minitest-bender/sections/suite_status.rb +72 -0
  26. data/lib/minitest-bender/sections/time_ranking.rb +49 -0
  27. data/lib/minitest-bender/states/base.rb +76 -19
  28. data/lib/minitest-bender/states/failing.rb +11 -8
  29. data/lib/minitest-bender/states/passing.rb +19 -8
  30. data/lib/minitest-bender/states/raising.rb +42 -20
  31. data/lib/minitest-bender/states/skipped.rb +12 -9
  32. data/lib/minitest-bender/utils.rb +26 -0
  33. data/lib/minitest-bender/version.rb +1 -1
  34. data/lib/minitest/bender.rb +166 -77
  35. data/lib/minitest/bender_plugin.rb +49 -3
  36. data/lib/minitest_bender.rb +23 -5
  37. data/minitest-bender.gemspec +6 -6
  38. metadata +39 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07494f6c231ff2de7a071fd6927d4e4084593d5db749d9f29eab51274e536322
4
- data.tar.gz: 6e0a7fdc255cd9a6effbbe701739ebd850ae50d003aac8aaafdab7d154cddcae
3
+ metadata.gz: 49e6e3621dfce3e4fea0607c005dba7865a7619e62d7391b715ac883cf2a43a5
4
+ data.tar.gz: 7566d1731c3ad37d5124ba48f87300fb1875b63108681c06f34966fa36e06100
5
5
  SHA512:
6
- metadata.gz: 7391d8c06ad48f013e43ecad0bc5504973a447d4668b9e23cffb45cb19820895226b1c1db38af78ecf8fb5e97d91cfd47c753e363f86bd035f0cd3d7b1be0e8a
7
- data.tar.gz: 6a0b1d44d864fe758e15ffce2182e9b579285cafcd72c11800856ef2fab08d159cd76dc221abf80fa71c88e0a8f4e6268e6170507541dc66ff08fee9b96d8518
6
+ metadata.gz: 511ca6879fa694f7195a86bdea865c213796a8e5bf2d3d05c438b6a1bb028fd9a57c7d5c103bee7572c1515603b279d71cc8018f28fe28067c46c516f2629549
7
+ data.tar.gz: b2c7a9517be2b69455620ba1c4a871d921d53dc09c37a9d27a11009035a7112ff528e1fe4bb2be147774114320235839eebd53034391e6f31ee4813739fe8dd9
@@ -6,6 +6,19 @@ All notable changes to this project will be documented in this file. This projec
6
6
 
7
7
  * Your contribution here!
8
8
 
9
+ ## [1.0.0][] (2020-07-19)
10
+
11
+ Thanks to [cboos](https://github.com/cboos) for contributing some of these enhancements!
12
+
13
+ * Two-step activation for better interoperability with other reporters
14
+ * Seven different recorders to choose from, five of which display a progress bar
15
+ * New "overview" section with sorted test results, enabled by default
16
+ * Skips, failures and errors are consistently sorted
17
+ * Irrelevant portions of backtraces are hidden by default
18
+ * Many configurable options such as visible sections and custom colors
19
+ * Graceful degradation of colors in console environments with poor support for them
20
+ * Smarter rerun command generation
21
+
9
22
  ## [0.0.3][] (2019-06-09)
10
23
 
11
24
  * Fixed running time format of slow tests
@@ -20,6 +33,7 @@ All notable changes to this project will be documented in this file. This projec
20
33
  * Initial release
21
34
 
22
35
  [Semver]: http://semver.org
23
- [Unreleased]: https://github.com/eugeniobruno/minitest-bender/compare/v0.0.2...HEAD
36
+ [Unreleased]: https://github.com/eugeniobruno/minitest-bender/compare/v1.0.0...HEAD
37
+ [1.0.0]: https://github.com/eugeniobruno/minitest-bender/compare/v0.0.3...v1.0.0
24
38
  [0.0.3]: https://github.com/eugeniobruno/minitest-bender/compare/v0.0.2...v0.0.3
25
39
  [0.0.2]: https://github.com/eugeniobruno/minitest-bender/compare/v0.0.1...v0.0.2
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in openhouse.gemspec
3
+ # Specify your gem's dependencies in minitest-bender.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/minitest-bender.svg)](https://badge.fury.io/rb/minitest-bender)
4
4
  [![Code Climate](https://codeclimate.com/github/eugeniobruno/minitest-bender.svg)](https://codeclimate.com/github/eugeniobruno/minitest-bender)
5
5
 
6
- My own Minitest reporter, without blackjack but with a hook.
6
+ A comprehensive Minitest reporter.
7
7
 
8
8
  ## Installation
9
9
 
@@ -23,24 +23,55 @@ Or install it yourself as:
23
23
 
24
24
  ## Usage
25
25
 
26
- Require this plugin right after Minitest:
26
+ Require this plugin right after Minitest, and then enable it explicitly:
27
27
 
28
28
  ```ruby
29
29
  require 'minitest/autorun'
30
30
  require 'minitest/bender'
31
+ Minitest::Bender.enable!
31
32
  ```
32
33
 
33
34
  That's it! The next time you run your tests, a new report format will be used instead of the default one.
34
35
 
36
+ Instead of calling the `enable!` method, you can also specify the `--bender` test option, e.g.
37
+
38
+ $ rake test TESTOPTS="--bender"
39
+
40
+ In both of these cases, Bender is activated with its default configuration. You can refer to [bender_plugin.rb](https://github.com/eugeniobruno/minitest-bender/blob/master/lib/minitest/bender_plugin.rb) or [configuration.rb](https://github.com/eugeniobruno/minitest-bender/blob/master/lib/minitest-bender/configuration.rb) to explore the multitude of options available to customize the output.
41
+
42
+ As an example, let's say your test suite takes several minutes to run, so you want to see detailed output in realtime. This behaviour is provided by a particular recorder called "progress_verbose", which is not the default one. In order to select this recorder for your app/gem, you can activate Bender like this instead:
43
+
44
+ ```ruby
45
+ Minitest::Bender.enable!({ recorder: :progress_verbose })
46
+ ```
47
+
48
+ You can also set configuration options via environment variables:
49
+
50
+ $ BENDER_RECORDER=progress_verbose rake test
51
+
52
+ Finally, command-line options also work:
53
+
54
+ $ rake test TESTOPTS="--bender-recorder=progress_verbose"
55
+
56
+ Bear in mind that setting a configuration option does not automatically enable the reporter, so remember to either call the `enable!` method, or to include the `--bender` argument.
57
+
58
+ If you use [minitest-reporters](https://github.com/kern/minitest-reporters) and have it installed and activated, you can select the `BenderReporter` as (one of the) reporters:
59
+
60
+ $ MINITEST_REPORTER=BenderReporter,HtmlReporter rake test
61
+
62
+
35
63
  ## Features
36
64
 
37
- Based on [minitest-colorin](https://github.com/gabynaiman/minitest-colorin/), the minitest-bender reporter offers you colored output including:
65
+ Originally based on [minitest-colorin](https://github.com/gabynaiman/minitest-colorin/), the minitest-bender reporter offers you, out of the box, colored output including:
38
66
 
39
- * Status, running time, name and message for each test/expectation, grouped by class/context
40
- * Details of skips, failures and errors in three different sections, with diffs, backtraces and commands to rerun each single test
41
- * Details of the top 3 slowest tests, if they may be relevant
67
+ * A progress bar, mostly useful for long-running suites, as the default of many different recorders
68
+ * Status, running time, name and message for each test/expectation, grouped by class/context and sorted by name
69
+ * Details of skips, failures and errors, with diffs, backtraces and commands to rerun each single test
70
+ * Details of the slowest tests, if they may be relevant
42
71
  * The same basic statistics of the default reporter
43
72
 
73
+ If the NO_COLOR environment variable is set, Bender will output non-colored text honoring [this standard](https://no-color.org/), thanks to the [paint gem](https://github.com/janlelis/paint/) dependency.
74
+
44
75
 
45
76
  ## Development
46
77
 
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['ANSICON'] ||= 'Y' if ENV['ConEmuANSI'] != 'ON'
4
+ require 'paint'
5
+
6
+ module MinitestBender
7
+ class Colorizer
8
+ COLORS = { # Xterm No. - Xterm Name
9
+ pass: '87ff87', # 120 - LightGreen
10
+ skip: '5fd7ff', # 81 - SteelBlue1
11
+ fail: 'ff5f5f', # 203 - IndianRed1
12
+ error: 'ffd75f', # 221 - LightGoldenrod2
13
+ tests: '5fafaf', # 73 - CadetBlue
14
+ assertions: 'd75fd7', # 170 - Orchid
15
+ time: '878787', # 102 - Grey53
16
+ number: '5fafaf', # 73 - CadetBlue
17
+ backtrace: 'af8787' # 138 - RosyBrown
18
+ }
19
+
20
+ # In compatibility modes, colors that are mapped to black are avoided.
21
+ SAFE_COLORS = {
22
+ pass: '00ff5f', # 47 - SpringGreen2
23
+ tests: 'blue',
24
+ time: 'gray',
25
+ number: 'gray',
26
+ backtrace: 'gray'
27
+ }
28
+ COLORS.merge!(SAFE_COLORS) if Paint.mode < 256
29
+
30
+ COLORS.freeze
31
+
32
+ class << self
33
+ def custom_colors=(custom_colors)
34
+ @custom_colors = custom_colors
35
+ end
36
+
37
+ def colorize(string, color, *args)
38
+ if color == :normal
39
+ Paint[string, *args]
40
+ else
41
+ color_value = colors.fetch(color)
42
+ Paint[string, color_value, *args]
43
+ end
44
+ end
45
+
46
+ def color_keys
47
+ COLORS.keys
48
+ end
49
+
50
+ private
51
+
52
+ def colors
53
+ @colors ||= COLORS.merge(custom_colors)
54
+ end
55
+
56
+ def custom_colors
57
+ @custom_colors || {}
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,174 @@
1
+ module MinitestBender
2
+ class Configuration
3
+ DEFAULT_CONFIG = {
4
+ mode: :oblivious,
5
+ recorder: :progress,
6
+ sections: [:overview, :time_ranking, :issues, :activity, :suite_status],
7
+ sections_blacklist: [],
8
+ overview_sort_key: :name,
9
+ time_ranking_size: 5,
10
+ backtrace_view: :user,
11
+ rerun_command_stem: defined?(Rake) ? 'rake' : 'ruby',
12
+ custom_colors: {}
13
+ }.freeze
14
+
15
+ def initialize
16
+ @client_config = {}
17
+ @options_config = {}
18
+ end
19
+
20
+ def add_client_config(config)
21
+ validate_config(config)
22
+ client_config.merge!(config)
23
+ end
24
+
25
+ def mode=(mode)
26
+ options_config[:mode] = mode
27
+ end
28
+
29
+ def recorder=(recorder)
30
+ options_config[:recorder] = recorder
31
+ end
32
+
33
+ def sections=(sections)
34
+ options_config[:sections] = sections
35
+ end
36
+
37
+ def sections_blacklist=(sections_blacklist)
38
+ options_config[:sections_blacklist] = sections_blacklist
39
+ end
40
+
41
+ def overview_sort_key=(overview_sort_key)
42
+ options_config[:overview_sort_key] = overview_sort_key
43
+ end
44
+
45
+ def time_ranking_size=(time_ranking_size)
46
+ options_config[:time_ranking_size] = time_ranking_size
47
+ end
48
+
49
+ def backtrace_view=(backtrace_view)
50
+ options_config[:backtrace_view] = backtrace_view
51
+ end
52
+
53
+ def rerun_command_stem=(rerun_command_stem)
54
+ options_config[:rerun_command_stem] = rerun_command_stem
55
+ end
56
+
57
+ def set_custom_color(color_key, color)
58
+ options_config[:custom_colors] ||= {}
59
+ options_config[:custom_colors][color_key] = color
60
+ end
61
+
62
+ def cooperative?
63
+ final_config.fetch(:mode) == :cooperative
64
+ end
65
+
66
+ def recorder
67
+ final_config.fetch(:recorder)
68
+ end
69
+
70
+ def sections
71
+ sections_whitelist - sections_blacklist
72
+ end
73
+
74
+ def overview_sort_key
75
+ final_config.fetch(:overview_sort_key)
76
+ end
77
+
78
+ def time_ranking_size
79
+ final_config.fetch(:time_ranking_size)
80
+ end
81
+
82
+ def backtrace_view
83
+ final_config.fetch(:backtrace_view)
84
+ end
85
+
86
+ def rerun_command_stem
87
+ final_config.fetch(:rerun_command_stem)
88
+ end
89
+
90
+ def custom_colors
91
+ final_config.fetch(:custom_colors)
92
+ end
93
+
94
+ private
95
+
96
+ attr_reader :client_config, :options_config
97
+
98
+ def validate_config(config)
99
+ invalid_options = config.keys.map(&:to_sym) - valid_options
100
+ unless invalid_options.empty?
101
+ first_invalid_option = invalid_options.first
102
+ message = "invalid option: '#{first_invalid_option}'"
103
+ raise ArgumentError, message
104
+ end
105
+ end
106
+
107
+ def valid_options
108
+ default_config.keys
109
+ end
110
+
111
+ def parsed_list(list)
112
+ strings = list.is_a?(Array) ? list.map(&:to_s) : list.split(',')
113
+ strings.map { |s| s.strip.to_sym }
114
+ end
115
+
116
+ def default_config
117
+ DEFAULT_CONFIG
118
+ end
119
+
120
+ def env_config
121
+ {
122
+ mode: ENV['BENDER_MODE'],
123
+ recorder: ENV['BENDER_RECORDER'],
124
+ sections: ENV['BENDER_SECTIONS'],
125
+ sections_blacklist: ENV['BENDER_SECTIONS_BLACKLIST'],
126
+ overview_sort_key: ENV['BENDER_OVERVIEW_SORT_KEY'],
127
+ time_ranking_size: ENV['BENDER_TIME_RANKING_SIZE'],
128
+ backtrace_view: ENV['BENDER_BACKTRACE_VIEW'],
129
+ rerun_command_stem: ENV['BENDER_RERUN_COMMAND_STEM'],
130
+ custom_colors: custom_colors_env_config
131
+ }
132
+ end
133
+
134
+ def custom_colors_env_config
135
+ Colorizer.color_keys.each_with_object({}) do |color_key, h|
136
+ h[color_key] = ENV["BENDER_#{color_key.upcase}_COLOR"]
137
+ end
138
+ end
139
+
140
+ def merged_config
141
+ [default_config, client_config, env_config, options_config].reduce do |acum, config|
142
+ proper_config = Utils.with_symbolized_keys(Utils.without_nil_values(config))
143
+ acum.merge(proper_config) do |key, old_val, new_val|
144
+ if key == :custom_colors
145
+ old_val.merge(Utils.with_symbolized_keys(Utils.without_nil_values(new_val)))
146
+ else
147
+ new_val
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ def final_config
154
+ merged_config.tap do |config|
155
+ config[:mode] = config[:mode].to_sym
156
+ config[:recorder] = config[:recorder].to_sym
157
+ config[:sections] = parsed_list(config[:sections])
158
+ config[:sections_blacklist] = parsed_list(config[:sections_blacklist])
159
+ config[:overview_sort_key] = config[:overview_sort_key].to_sym
160
+ config[:time_ranking_size] = config[:time_ranking_size].to_i
161
+ config[:rerun_command_stem] = config[:rerun_command_stem].to_s
162
+ config[:backtrace_view] = config[:backtrace_view].to_sym
163
+ end
164
+ end
165
+
166
+ def sections_whitelist
167
+ final_config.fetch(:sections)
168
+ end
169
+
170
+ def sections_blacklist
171
+ final_config.fetch(:sections_blacklist)
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,29 @@
1
+ module MinitestBender
2
+ module Printers
3
+ class Plain
4
+ def initialize(io)
5
+ @io = io
6
+ end
7
+
8
+ def print(string)
9
+ io.print(string)
10
+ end
11
+
12
+ def print_line(line = '')
13
+ io.puts(line)
14
+ end
15
+
16
+ def print_lines(lines)
17
+ lines.each { |line| print_line(line) }
18
+ end
19
+
20
+ def advance
21
+ # do nothing
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :io
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,115 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'tty-progressbar'
5
+
6
+ module MinitestBender
7
+ module Printers
8
+ class WithProgressBar
9
+ COMPLETE_ICON = ' '
10
+ HEAD_ICON = 'ᗧ'
11
+ INCOMPLETE_ICON = '•'
12
+ ELAPSED_ICON = '⏱'
13
+ ETA_ICON = '⌛'
14
+
15
+ def initialize(io, total)
16
+ @io = io
17
+ @total = total
18
+ @bar = new_bar
19
+ end
20
+
21
+ def print(string)
22
+ io.print(string)
23
+ end
24
+
25
+ def print_line(line = '')
26
+ if io.tty?
27
+ bar.log(line)
28
+ else
29
+ io.puts(line)
30
+ end
31
+ end
32
+
33
+ def print_lines(lines)
34
+ lines.each { |line| print_line(line) }
35
+ end
36
+
37
+ def advance
38
+ bar.update({ head: head })
39
+ bar.advance(1, { counters_sym => counters })
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :io, :bar, :total
45
+
46
+ def new_bar
47
+ TTY::ProgressBar.new(bar_format_string, {
48
+ total: total,
49
+ width: [total, TTY::ProgressBar.max_columns].max,
50
+ complete: complete_icon,
51
+ head: head_icon,
52
+ incomplete: incomplete_icon
53
+ })
54
+ end
55
+
56
+ def bar_format_string
57
+ ":bar #{Colorizer.colorize(':current/:total', :tests)} :#{counters_sym} #{Colorizer.colorize(elapsed_icon + ' :elapsed', :time)} #{Colorizer.colorize(eta_icon + ':eta', :time)} #{Colorizer.colorize(':percent', :normal, :bold)}"
58
+ end
59
+
60
+ def counters
61
+ states.map do |state|
62
+ state.colored_icon_with_count(counters_padding_right)
63
+ end.join(' ')
64
+ end
65
+
66
+ def counters_sym
67
+ ('c' * counters_sym_length).to_sym
68
+ end
69
+
70
+ def counters_sym_length
71
+ ( 4 * (total.to_s.size + 1) ) + 6
72
+ end
73
+
74
+ def head
75
+ Colorizer.colorize(head_icon, head_color)
76
+ end
77
+
78
+ def complete_icon
79
+ COMPLETE_ICON
80
+ end
81
+
82
+ def head_icon
83
+ HEAD_ICON
84
+ end
85
+
86
+ def incomplete_icon
87
+ INCOMPLETE_ICON
88
+ end
89
+
90
+ def elapsed_icon
91
+ ELAPSED_ICON
92
+ end
93
+
94
+ def eta_icon
95
+ ETA_ICON
96
+ end
97
+
98
+ def head_color
99
+ reverse_states.find { |s| !s.results.empty? }.color
100
+ end
101
+
102
+ def states
103
+ @states ||= MinitestBender.states.values
104
+ end
105
+
106
+ def reverse_states
107
+ @reverse_states ||= states.reverse
108
+ end
109
+
110
+ def counters_padding_right
111
+ @counters_padding_right ||= total.to_s.size + 1
112
+ end
113
+ end
114
+ end
115
+ end