minitest-heat 2.1.0 → 2.1.1
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/.flayignore +1 -0
- data/.reek.yml +87 -0
- data/.reviewer.yml +87 -0
- data/.reviewer_history.yml +42 -0
- data/.rubocop.yml +33 -2
- data/CHANGELOG.md +11 -0
- data/Gemfile +12 -2
- data/Gemfile.lock +61 -4
- data/lib/minitest/heat/backtrace/line_count.rb +1 -1
- data/lib/minitest/heat/backtrace.rb +5 -15
- data/lib/minitest/heat/hit.rb +5 -12
- data/lib/minitest/heat/issue.rb +15 -39
- data/lib/minitest/heat/location.rb +25 -63
- data/lib/minitest/heat/locations.rb +8 -24
- data/lib/minitest/heat/map.rb +3 -9
- data/lib/minitest/heat/output/backtrace.rb +16 -26
- data/lib/minitest/heat/output/issue.rb +1 -1
- data/lib/minitest/heat/output/map.rb +7 -7
- data/lib/minitest/heat/output/marker.rb +3 -9
- data/lib/minitest/heat/output/results.rb +15 -37
- data/lib/minitest/heat/output/source_code.rb +4 -12
- data/lib/minitest/heat/output/token.rb +23 -22
- data/lib/minitest/heat/output.rb +9 -11
- data/lib/minitest/heat/source.rb +14 -27
- data/lib/minitest/heat/timer.rb +6 -12
- data/lib/minitest/heat/version.rb +1 -1
- data/lib/minitest/heat_plugin.rb +2 -1
- data/lib/minitest/heat_reporter.rb +4 -8
- data/minitest-heat.gemspec +1 -9
- metadata +5 -99
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc5068c6b1be1b2c9b8c7022da1df9ec2e03aa6c1aac37f579925973d55f8efb
|
|
4
|
+
data.tar.gz: f492675d598fd4cd51aeb04af25db4a12d3bc3d5b4c2bfbfc0c53e7f0dc44c61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 51f03b1d83f8ab6cd0b2ee95bb3e5308750cfe44ac2aa6095101e2e61dcae3a1f4176cd5c5d7d23ab844011ac162bf08ac3b2c79edeae2e310dba13b83cdf35d
|
|
7
|
+
data.tar.gz: 0b3e98d2e537e1b2df31f0800fab55bf72030be73f70eb823f7cd6799a8dd8c83daebc2692cfcd653017b3a21542a4de5215398456658f89131f7d132052b038
|
data/.flayignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
./test/**/*.rb
|
data/.reek.yml
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Reek configuration for minitest-heat
|
|
2
|
+
# https://github.com/troessner/reek/blob/master/docs/defaults.reek.yml
|
|
3
|
+
|
|
4
|
+
detectors:
|
|
5
|
+
# --- Disabled: conflicts with standard Ruby patterns ---
|
|
6
|
+
|
|
7
|
+
# Flags attr_accessor as a writable attribute. Standard Ruby; no value suppressing.
|
|
8
|
+
Attribute:
|
|
9
|
+
enabled: false
|
|
10
|
+
|
|
11
|
+
# Flags keyword arguments like `clear_screen: false`. Idiomatic Ruby.
|
|
12
|
+
BooleanParameter:
|
|
13
|
+
enabled: false
|
|
14
|
+
|
|
15
|
+
# Flags branching on method arguments. Appropriate for configuration and options.
|
|
16
|
+
ControlParameter:
|
|
17
|
+
enabled: false
|
|
18
|
+
|
|
19
|
+
# Issue#initialize wraps Minitest::Result data — all parameters are necessary.
|
|
20
|
+
# Map#add takes pathname, line_number, type, and backtrace — all distinct inputs.
|
|
21
|
+
LongParameterList:
|
|
22
|
+
max_params: 4
|
|
23
|
+
exclude:
|
|
24
|
+
- 'Minitest::Heat::Issue#initialize'
|
|
25
|
+
|
|
26
|
+
# --- Threshold adjustments: defaults are too aggressive ---
|
|
27
|
+
|
|
28
|
+
# Default max_calls (1) flags every repeated method call. Raise to 3 so only
|
|
29
|
+
# genuine duplication is flagged, not incidental reuse.
|
|
30
|
+
DuplicateMethodCall:
|
|
31
|
+
max_calls: 3
|
|
32
|
+
|
|
33
|
+
# Guard clauses like `file_exists?` and mode checks like `json_output?` are
|
|
34
|
+
# repeated across public methods by design, not duplication.
|
|
35
|
+
RepeatedConditional:
|
|
36
|
+
enabled: false
|
|
37
|
+
|
|
38
|
+
# Default max_statements (5) flags nearly every non-trivial method. 12 keeps
|
|
39
|
+
# the check useful while allowing token-building methods that are linear and clear.
|
|
40
|
+
TooManyStatements:
|
|
41
|
+
max_statements: 12
|
|
42
|
+
|
|
43
|
+
# Location is a comprehensive value object with many accessors.
|
|
44
|
+
# 30 keeps the check useful for genuinely bloated classes.
|
|
45
|
+
TooManyMethods:
|
|
46
|
+
max_methods: 30
|
|
47
|
+
|
|
48
|
+
# Flags nil checks (`nil?`, `!x`). Legitimate for optional settings and
|
|
49
|
+
# backtrace data where nil is a normal value.
|
|
50
|
+
NilCheck:
|
|
51
|
+
enabled: false
|
|
52
|
+
|
|
53
|
+
# Output classes format data from domain objects — accessing their attributes
|
|
54
|
+
# is the entire purpose, not a design flaw.
|
|
55
|
+
FeatureEnvy:
|
|
56
|
+
enabled: false
|
|
57
|
+
|
|
58
|
+
# Flags private methods that don't reference instance state. These methods
|
|
59
|
+
# logically belong to their class even without direct instance access.
|
|
60
|
+
UtilityFunction:
|
|
61
|
+
enabled: false
|
|
62
|
+
|
|
63
|
+
# ManualDispatch is legitimate for duck-typing checks (respond_to? + send).
|
|
64
|
+
ManualDispatch:
|
|
65
|
+
enabled: false
|
|
66
|
+
|
|
67
|
+
# Nested iterators are common in token-building code where lines contain tokens.
|
|
68
|
+
# Two levels deep is readable and appropriate for this codebase.
|
|
69
|
+
NestedIterators:
|
|
70
|
+
max_allowed_nesting: 2
|
|
71
|
+
|
|
72
|
+
# Issue wraps a Minitest::Result with classification; 9 ivars reflect the data it needs.
|
|
73
|
+
# Source has 5 ivars for file reading context — all necessary.
|
|
74
|
+
TooManyInstanceVariables:
|
|
75
|
+
max_instance_variables: 9
|
|
76
|
+
|
|
77
|
+
# Timer.start! and Timer.stop! are mutating operations with no safe equivalent.
|
|
78
|
+
# The bang convention here signals state mutation, not a safe/unsafe pair.
|
|
79
|
+
MissingSafeMethod:
|
|
80
|
+
enabled: false
|
|
81
|
+
|
|
82
|
+
# RuboCop enforces `e` for rescue variables (Naming/RescuedExceptionsVariableName).
|
|
83
|
+
# Allow `e` to avoid conflicts between the two tools.
|
|
84
|
+
UncommunicativeVariableName:
|
|
85
|
+
accept:
|
|
86
|
+
- e
|
|
87
|
+
- i
|
data/.reviewer.yml
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Review gem dependencies for security issues
|
|
3
|
+
bundle_audit:
|
|
4
|
+
name: Bundle Audit
|
|
5
|
+
description: Review gem dependencies for security issues
|
|
6
|
+
tags: [security, dependencies, ruby]
|
|
7
|
+
commands:
|
|
8
|
+
install: bundle exec gem install bundler-audit
|
|
9
|
+
prepare: bundle exec bundle-audit update
|
|
10
|
+
review: bundle exec bundle-audit check --no-update
|
|
11
|
+
|
|
12
|
+
# Review Ruby syntax and formatting for consistency
|
|
13
|
+
rubocop:
|
|
14
|
+
name: RuboCop
|
|
15
|
+
description: Review Ruby syntax and formatting for consistency
|
|
16
|
+
tags: [ruby, syntax]
|
|
17
|
+
commands:
|
|
18
|
+
install: bundle exec gem install rubocop
|
|
19
|
+
review: bundle exec rubocop --parallel
|
|
20
|
+
format: bundle exec rubocop --auto-correct
|
|
21
|
+
files:
|
|
22
|
+
flag: ''
|
|
23
|
+
separator: ' '
|
|
24
|
+
pattern: '*.rb'
|
|
25
|
+
|
|
26
|
+
# Examine Ruby classes for code smells
|
|
27
|
+
reek:
|
|
28
|
+
disabled: true
|
|
29
|
+
name: Reek
|
|
30
|
+
description: Examine Ruby classes for code smells
|
|
31
|
+
tags: [ruby, quality]
|
|
32
|
+
links:
|
|
33
|
+
home: https://github.com/troessner/reek
|
|
34
|
+
install: https://github.com/troessner/reek#quickstart
|
|
35
|
+
max_exit_status: 2
|
|
36
|
+
commands:
|
|
37
|
+
install: bundle exec gem install reek
|
|
38
|
+
review: bundle exec reek --config .reek.yml lib/
|
|
39
|
+
files:
|
|
40
|
+
flag: ''
|
|
41
|
+
separator: ' '
|
|
42
|
+
pattern: '*.rb'
|
|
43
|
+
|
|
44
|
+
# Reports most tortured ruby code in a pain report
|
|
45
|
+
flog:
|
|
46
|
+
disabled: true
|
|
47
|
+
name: Flog
|
|
48
|
+
description: Reports your most tortured ruby code in an easy to read pain report.
|
|
49
|
+
tags: [ruby, quality]
|
|
50
|
+
links:
|
|
51
|
+
home: https://ruby.sadi.st/Flog.html
|
|
52
|
+
install: https://ruby.sadi.st/Flog.html
|
|
53
|
+
commands:
|
|
54
|
+
install: bundle exec gem install flog
|
|
55
|
+
review: bundle exec flog -g lib
|
|
56
|
+
flags:
|
|
57
|
+
threshold: 10
|
|
58
|
+
group:
|
|
59
|
+
methods-only:
|
|
60
|
+
|
|
61
|
+
# Review ruby code for structural similarities
|
|
62
|
+
flay:
|
|
63
|
+
disabled: true
|
|
64
|
+
name: Flay
|
|
65
|
+
description: Review ruby code for structural similarities and refactoring opportunities.
|
|
66
|
+
tags: [ruby, quality]
|
|
67
|
+
links:
|
|
68
|
+
home: https://ruby.sadi.st/Flay.html
|
|
69
|
+
install: https://ruby.sadi.st/Flay.html
|
|
70
|
+
commands:
|
|
71
|
+
install: bundle exec gem install flay
|
|
72
|
+
review: bundle exec flay ./lib
|
|
73
|
+
flags:
|
|
74
|
+
liberal:
|
|
75
|
+
summary:
|
|
76
|
+
|
|
77
|
+
# Unit tests and coverage
|
|
78
|
+
tests:
|
|
79
|
+
name: Minitest
|
|
80
|
+
description: Unit tests and coverage
|
|
81
|
+
tags: [ruby, tests]
|
|
82
|
+
commands:
|
|
83
|
+
review: bundle exec rake test
|
|
84
|
+
files:
|
|
85
|
+
review: bundle exec ruby -Itest
|
|
86
|
+
pattern: '*_test.rb'
|
|
87
|
+
map_to_tests: minitest
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
:bundle_audit:
|
|
3
|
+
:last_status: :passed
|
|
4
|
+
:last_prepared_at: '2026-02-01 10:15:13 -0700'
|
|
5
|
+
bundle exec bundle-audit update:
|
|
6
|
+
- 0.94
|
|
7
|
+
bundle exec bundle-audit check --no-update:
|
|
8
|
+
- 0.2
|
|
9
|
+
- 0.15
|
|
10
|
+
- 0.23
|
|
11
|
+
- 0.21
|
|
12
|
+
- 0.29
|
|
13
|
+
:last_failed_files:
|
|
14
|
+
:rubocop:
|
|
15
|
+
:last_status: :passed
|
|
16
|
+
:last_failed_files:
|
|
17
|
+
bundle exec rubocop --parallel:
|
|
18
|
+
- 1.4
|
|
19
|
+
- 1.11
|
|
20
|
+
- 1.76
|
|
21
|
+
:tests:
|
|
22
|
+
:last_status: :passed
|
|
23
|
+
:last_failed_files:
|
|
24
|
+
bundle exec rake test:
|
|
25
|
+
- 0.54
|
|
26
|
+
- 0.5
|
|
27
|
+
- 0.66
|
|
28
|
+
:reek:
|
|
29
|
+
:last_status: :passed
|
|
30
|
+
:last_failed_files:
|
|
31
|
+
bundle exec reek --config .reek.yml lib/:
|
|
32
|
+
- 0.91
|
|
33
|
+
:flog:
|
|
34
|
+
:last_status: :passed
|
|
35
|
+
:last_failed_files:
|
|
36
|
+
bundle exec flog -g lib --threshold 10 --group --methods-only:
|
|
37
|
+
- 0.38
|
|
38
|
+
:flay:
|
|
39
|
+
:last_status: :passed
|
|
40
|
+
:last_failed_files:
|
|
41
|
+
bundle exec flay ./lib --liberal --summary:
|
|
42
|
+
- 0.36
|
data/.rubocop.yml
CHANGED
|
@@ -7,14 +7,26 @@ AllCops:
|
|
|
7
7
|
Exclude:
|
|
8
8
|
- 'bin/**/*'
|
|
9
9
|
- 'test/files/source.rb' # An example test file for reading source code
|
|
10
|
+
- 'test/minitest/contrived_*' # Intentional failures for testing the reporter
|
|
10
11
|
|
|
11
12
|
# Let's aim for 80, but we don't need to be nagged if we judiciously go over.
|
|
12
13
|
Layout/LineLength:
|
|
13
14
|
Enabled: false
|
|
14
15
|
|
|
15
|
-
# One case statement in a single method isn't complex.
|
|
16
|
+
# One case statement in a single method isn't complex. Issue classification
|
|
17
|
+
# methods use cascading conditionals that are clear and linear.
|
|
16
18
|
Metrics/CyclomaticComplexity:
|
|
17
|
-
AllowedMethods: ['case']
|
|
19
|
+
AllowedMethods: ['case', 'type', 'issue_label']
|
|
20
|
+
|
|
21
|
+
# Issue#initialize wraps Minitest::Result with keyword args — all are needed.
|
|
22
|
+
# build_issue test helper mirrors those parameters.
|
|
23
|
+
Metrics/ParameterLists:
|
|
24
|
+
CountKeywordArgs: false
|
|
25
|
+
|
|
26
|
+
# Classification and token-building methods are linear with many branches.
|
|
27
|
+
# 20 is reasonable for this codebase.
|
|
28
|
+
Metrics/AbcSize:
|
|
29
|
+
Max: 20
|
|
18
30
|
|
|
19
31
|
# Development dependencies in gemspec is fine for this gem
|
|
20
32
|
Gemspec/DevelopmentDependencies:
|
|
@@ -25,5 +37,24 @@ Metrics/MethodLength:
|
|
|
25
37
|
CountAsOne: ['array', 'hash', 'heredoc']
|
|
26
38
|
Max: 15
|
|
27
39
|
|
|
40
|
+
# Test classes naturally grow with coverage (see test/.rubocop.yml for higher limit)
|
|
41
|
+
Metrics/ClassLength:
|
|
42
|
+
CountAsOne: ['array', 'hash', 'heredoc']
|
|
43
|
+
Max: 150
|
|
44
|
+
|
|
45
|
+
Metrics/ModuleLength:
|
|
46
|
+
CountAsOne: ['array', 'hash', 'heredoc']
|
|
47
|
+
Max: 150
|
|
48
|
+
|
|
49
|
+
# Fasterer prefers yield over block.call for performance
|
|
50
|
+
Style/ExplicitBlockArgument:
|
|
51
|
+
Enabled: false
|
|
52
|
+
|
|
53
|
+
# Fasterer prefers fetch with block over second argument for performance
|
|
54
|
+
Style/RedundantFetchBlock:
|
|
55
|
+
Enabled: false
|
|
56
|
+
|
|
57
|
+
# Compact style (Minitest::Heat::IssueTest) is standard for this project.
|
|
58
|
+
# Nested style breaks when intermediary names are classes, not modules (e.g. Backtrace).
|
|
28
59
|
Style/ClassAndModuleChildren:
|
|
29
60
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [2.1.1] - 2026-02-01
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Converted ~90 single-expression methods to Ruby 3.0+ endless method syntax
|
|
7
|
+
- Moved dev dependencies from gemspec to Gemfile; changed `add_runtime_dependency` to `add_dependency`
|
|
8
|
+
- Moved constants above `private` in Output::Token for conventional ordering
|
|
9
|
+
- Replaced inline rubocop disables with targeted reek annotations
|
|
10
|
+
- Switched to leading-dot method chains, symbol-to-proc where applicable, and minor style fixes
|
|
11
|
+
- Removed unnecessary `begin`/`end` block in Output#print_tokens rescue
|
|
12
|
+
- Cleaned up test suite: removed redundant tests, fixed silent-pass conditionals, replaced fragile mutation-based setup with fresh instances, added ensure-based cleanup for filesystem tests
|
|
13
|
+
|
|
3
14
|
## [2.1.0] - 2026-01-30
|
|
4
15
|
|
|
5
16
|
### Added
|
data/Gemfile
CHANGED
|
@@ -2,9 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
source 'https://rubygems.org'
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# Runtime dependencies in minitest-heat.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
+
# Development dependencies
|
|
8
9
|
gem 'bundler-audit', '>= 0.9'
|
|
9
|
-
gem '
|
|
10
|
+
gem 'debug'
|
|
11
|
+
gem 'flay'
|
|
12
|
+
gem 'flog'
|
|
10
13
|
gem 'rake', '>= 13.0'
|
|
14
|
+
gem 'reek'
|
|
15
|
+
gem 'reviewer'
|
|
16
|
+
gem 'rubocop'
|
|
17
|
+
gem 'rubocop-minitest'
|
|
18
|
+
gem 'rubocop-rake'
|
|
19
|
+
gem 'simplecov'
|
|
20
|
+
gem 'simplecov_json_formatter'
|
data/Gemfile.lock
CHANGED
|
@@ -1,23 +1,63 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
minitest-heat (2.1.
|
|
4
|
+
minitest-heat (2.1.1)
|
|
5
5
|
minitest
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
ast (2.4.3)
|
|
11
|
-
|
|
11
|
+
bigdecimal (4.0.1)
|
|
12
12
|
bundler-audit (0.9.3)
|
|
13
13
|
bundler (>= 1.2.0)
|
|
14
14
|
thor (~> 1.0)
|
|
15
|
+
concurrent-ruby (1.3.6)
|
|
15
16
|
date (3.5.1)
|
|
16
17
|
debug (1.11.1)
|
|
17
18
|
irb (~> 1.10)
|
|
18
19
|
reline (>= 0.3.8)
|
|
19
20
|
docile (1.4.1)
|
|
21
|
+
dry-configurable (1.3.0)
|
|
22
|
+
dry-core (~> 1.1)
|
|
23
|
+
zeitwerk (~> 2.6)
|
|
24
|
+
dry-core (1.2.0)
|
|
25
|
+
concurrent-ruby (~> 1.0)
|
|
26
|
+
logger
|
|
27
|
+
zeitwerk (~> 2.6)
|
|
28
|
+
dry-inflector (1.3.1)
|
|
29
|
+
dry-initializer (3.2.0)
|
|
30
|
+
dry-logic (1.6.0)
|
|
31
|
+
bigdecimal
|
|
32
|
+
concurrent-ruby (~> 1.0)
|
|
33
|
+
dry-core (~> 1.1)
|
|
34
|
+
zeitwerk (~> 2.6)
|
|
35
|
+
dry-schema (1.15.0)
|
|
36
|
+
concurrent-ruby (~> 1.0)
|
|
37
|
+
dry-configurable (~> 1.0, >= 1.0.1)
|
|
38
|
+
dry-core (~> 1.1)
|
|
39
|
+
dry-initializer (~> 3.2)
|
|
40
|
+
dry-logic (~> 1.6)
|
|
41
|
+
dry-types (~> 1.8)
|
|
42
|
+
zeitwerk (~> 2.6)
|
|
43
|
+
dry-types (1.9.0)
|
|
44
|
+
bigdecimal (>= 3.0)
|
|
45
|
+
concurrent-ruby (~> 1.0)
|
|
46
|
+
dry-core (~> 1.0)
|
|
47
|
+
dry-inflector (~> 1.0)
|
|
48
|
+
dry-logic (~> 1.4)
|
|
49
|
+
zeitwerk (~> 2.6)
|
|
20
50
|
erb (6.0.1)
|
|
51
|
+
erubi (1.13.1)
|
|
52
|
+
flay (2.14.2)
|
|
53
|
+
erubi (~> 1.10)
|
|
54
|
+
path_expander (~> 2.0)
|
|
55
|
+
prism (~> 1.7)
|
|
56
|
+
sexp_processor (~> 4.0)
|
|
57
|
+
flog (4.9.4)
|
|
58
|
+
path_expander (~> 2.0)
|
|
59
|
+
prism (~> 1.7)
|
|
60
|
+
sexp_processor (~> 4.8)
|
|
21
61
|
io-console (0.8.2)
|
|
22
62
|
irb (1.16.0)
|
|
23
63
|
pp (>= 0.6.0)
|
|
@@ -26,11 +66,13 @@ GEM
|
|
|
26
66
|
json (2.18.0)
|
|
27
67
|
language_server-protocol (3.17.0.5)
|
|
28
68
|
lint_roller (1.1.0)
|
|
69
|
+
logger (1.7.0)
|
|
29
70
|
minitest (5.27.0)
|
|
30
71
|
parallel (1.27.0)
|
|
31
72
|
parser (3.3.10.1)
|
|
32
73
|
ast (~> 2.4.1)
|
|
33
74
|
racc
|
|
75
|
+
path_expander (2.0.1)
|
|
34
76
|
pp (0.6.3)
|
|
35
77
|
prettyprint
|
|
36
78
|
prettyprint (0.2.0)
|
|
@@ -45,9 +87,19 @@ GEM
|
|
|
45
87
|
erb
|
|
46
88
|
psych (>= 4.0.0)
|
|
47
89
|
tsort
|
|
90
|
+
reek (6.5.0)
|
|
91
|
+
dry-schema (~> 1.13)
|
|
92
|
+
logger (~> 1.6)
|
|
93
|
+
parser (~> 3.3.0)
|
|
94
|
+
rainbow (>= 2.0, < 4.0)
|
|
95
|
+
rexml (~> 3.1)
|
|
48
96
|
regexp_parser (2.11.3)
|
|
49
97
|
reline (0.6.3)
|
|
50
98
|
io-console (~> 0.5)
|
|
99
|
+
reviewer (0.1.5)
|
|
100
|
+
rainbow
|
|
101
|
+
slop
|
|
102
|
+
rexml (3.4.4)
|
|
51
103
|
rubocop (1.84.0)
|
|
52
104
|
json (~> 2.3)
|
|
53
105
|
language_server-protocol (~> 3.17.0.2)
|
|
@@ -70,30 +122,35 @@ GEM
|
|
|
70
122
|
lint_roller (~> 1.1)
|
|
71
123
|
rubocop (>= 1.72.1)
|
|
72
124
|
ruby-progressbar (1.13.0)
|
|
125
|
+
sexp_processor (4.17.5)
|
|
73
126
|
simplecov (0.22.0)
|
|
74
127
|
docile (~> 1.1)
|
|
75
128
|
simplecov-html (~> 0.11)
|
|
76
129
|
simplecov_json_formatter (~> 0.1)
|
|
77
130
|
simplecov-html (0.13.2)
|
|
78
131
|
simplecov_json_formatter (0.1.4)
|
|
132
|
+
slop (4.10.1)
|
|
79
133
|
stringio (3.2.0)
|
|
80
134
|
thor (1.5.0)
|
|
81
135
|
tsort (0.2.0)
|
|
82
136
|
unicode-display_width (3.2.0)
|
|
83
137
|
unicode-emoji (~> 4.1)
|
|
84
138
|
unicode-emoji (4.2.0)
|
|
139
|
+
zeitwerk (2.7.4)
|
|
85
140
|
|
|
86
141
|
PLATFORMS
|
|
87
142
|
arm64-darwin-24
|
|
88
143
|
ruby
|
|
89
144
|
|
|
90
145
|
DEPENDENCIES
|
|
91
|
-
awesome_print
|
|
92
146
|
bundler-audit (>= 0.9)
|
|
93
147
|
debug
|
|
94
|
-
|
|
148
|
+
flay
|
|
149
|
+
flog
|
|
95
150
|
minitest-heat!
|
|
96
151
|
rake (>= 13.0)
|
|
152
|
+
reek
|
|
153
|
+
reviewer
|
|
97
154
|
rubocop
|
|
98
155
|
rubocop-minitest
|
|
99
156
|
rubocop-rake
|
|
@@ -21,9 +21,7 @@ module Minitest
|
|
|
21
21
|
# Determines if the raw backtrace has values in it
|
|
22
22
|
#
|
|
23
23
|
# @return [Boolean] true if there's no backtrace or it's empty
|
|
24
|
-
def empty?
|
|
25
|
-
raw_backtrace.empty?
|
|
26
|
-
end
|
|
24
|
+
def empty? = raw_backtrace.empty?
|
|
27
25
|
|
|
28
26
|
# All lines of the backtrace converted to Backtrace::LineParser's
|
|
29
27
|
#
|
|
@@ -38,30 +36,22 @@ module Minitest
|
|
|
38
36
|
# files at the beginning
|
|
39
37
|
#
|
|
40
38
|
# @return [Array<Location>] the sorted backtrace lines from the project
|
|
41
|
-
def recently_modified_locations
|
|
42
|
-
@recently_modified_locations ||= project_locations.sort_by(&:mtime).reverse
|
|
43
|
-
end
|
|
39
|
+
def recently_modified_locations = (@recently_modified_locations ||= project_locations.sort_by(&:mtime).reverse)
|
|
44
40
|
|
|
45
41
|
# All entries from the backtrace that are files within the project
|
|
46
42
|
#
|
|
47
43
|
# @return [Array<Location>] the backtrace lines from within the project
|
|
48
|
-
def project_locations
|
|
49
|
-
@project_locations ||= locations.select(&:project_file?)
|
|
50
|
-
end
|
|
44
|
+
def project_locations = (@project_locations ||= locations.select(&:project_file?))
|
|
51
45
|
|
|
52
46
|
# All entries from the backtrace within the project tests
|
|
53
47
|
#
|
|
54
48
|
# @return [Array<Location>] the backtrace lines from within the tests
|
|
55
|
-
def test_locations
|
|
56
|
-
@test_locations ||= project_locations.select(&:test_file?)
|
|
57
|
-
end
|
|
49
|
+
def test_locations = (@test_locations ||= project_locations.select(&:test_file?))
|
|
58
50
|
|
|
59
51
|
# All source code entries from the backtrace (i.e. excluding tests)
|
|
60
52
|
#
|
|
61
53
|
# @return [Array<Location>] the backtrace lines from within the source code
|
|
62
|
-
def source_code_locations
|
|
63
|
-
@source_code_locations ||= project_locations.select(&:source_code_file?)
|
|
64
|
-
end
|
|
54
|
+
def source_code_locations = (@source_code_locations ||= project_locations.select(&:source_code_file?))
|
|
65
55
|
end
|
|
66
56
|
end
|
|
67
57
|
end
|
data/lib/minitest/heat/hit.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Minitest
|
|
|
7
7
|
# Kind of like an issue, but instead of focusing on a failing test, it covers all issues for a
|
|
8
8
|
# given file to build a heat map of the affected files and line numbers
|
|
9
9
|
class Hit
|
|
10
|
+
# Represents a single occurrence of an issue at a specific line
|
|
10
11
|
Trace = Struct.new(:type, :line_number, :locations)
|
|
11
12
|
|
|
12
13
|
# So we can sort hot spots by liklihood of being the most important spot to check out before
|
|
@@ -62,23 +63,17 @@ module Minitest
|
|
|
62
63
|
# the most problematic across the various issue types
|
|
63
64
|
#
|
|
64
65
|
# @return [Integer] the problem weight for the file
|
|
65
|
-
def weight
|
|
66
|
-
issues.sum { |type, values| values.size * WEIGHTS.fetch(type, 0) }
|
|
67
|
-
end
|
|
66
|
+
def weight = issues.sum { |type, values| values.size * WEIGHTS.fetch(type, 0) }
|
|
68
67
|
|
|
69
68
|
# The total issue count for the file across all issue types. Includes duplicates if they exist
|
|
70
69
|
#
|
|
71
70
|
# @return [Integer] the sum of the counts for all line numbers for all issue types
|
|
72
|
-
def count
|
|
73
|
-
issues.sum { |_type, values| values.size }
|
|
74
|
-
end
|
|
71
|
+
def count = issues.sum { |_type, values| values.size }
|
|
75
72
|
|
|
76
73
|
# The full set of unique line numbers across all issue types
|
|
77
74
|
#
|
|
78
75
|
# @return [Array<Integer>] the full set of unique offending line numbers for the hit
|
|
79
|
-
def line_numbers
|
|
80
|
-
issues.values.flatten.uniq.sort
|
|
81
|
-
end
|
|
76
|
+
def line_numbers = issues.values.flatten.uniq.sort
|
|
82
77
|
|
|
83
78
|
# Generates a hash representation for JSON serialization
|
|
84
79
|
#
|
|
@@ -93,9 +88,7 @@ module Minitest
|
|
|
93
88
|
|
|
94
89
|
private
|
|
95
90
|
|
|
96
|
-
def relative_path
|
|
97
|
-
pathname.to_s.delete_prefix("#{Dir.pwd}/")
|
|
98
|
-
end
|
|
91
|
+
def relative_path = pathname.to_s.delete_prefix("#{Dir.pwd}/")
|
|
99
92
|
|
|
100
93
|
def lines_summary
|
|
101
94
|
line_numbers.map do |line_num|
|
data/lib/minitest/heat/issue.rb
CHANGED
|
@@ -90,7 +90,7 @@ module Minitest
|
|
|
90
90
|
# painfully slow and should get more attention.
|
|
91
91
|
#
|
|
92
92
|
# @return [Symbol] issue type for classifying issues and reporting
|
|
93
|
-
def type # rubocop:disable Metrics/
|
|
93
|
+
def type # rubocop:disable Metrics/PerceivedComplexity
|
|
94
94
|
if error? && in_test?
|
|
95
95
|
:broken
|
|
96
96
|
elsif error?
|
|
@@ -112,88 +112,66 @@ module Minitest
|
|
|
112
112
|
# (Because slow tests still pass and wouldn't otherwise be considered an issue.)
|
|
113
113
|
#
|
|
114
114
|
# @return [Boolean] true if the test did not pass or if it was slow
|
|
115
|
-
def hit?
|
|
116
|
-
!passed? || slow? || painful?
|
|
117
|
-
end
|
|
115
|
+
def hit? = !passed? || slow? || painful?
|
|
118
116
|
|
|
119
117
|
# The number, in seconds, for a test to be considered "slow"
|
|
120
118
|
#
|
|
121
119
|
# @return [Float] number of seconds after which a test is considered slow
|
|
122
|
-
def slow_threshold
|
|
123
|
-
Minitest::Heat.configuration.slow_threshold
|
|
124
|
-
end
|
|
120
|
+
def slow_threshold = Minitest::Heat.configuration.slow_threshold
|
|
125
121
|
|
|
126
122
|
# The number, in seconds, for a test to be considered "painfully slow"
|
|
127
123
|
#
|
|
128
124
|
# @return [Float] number of seconds after which a test is considered painfully slow
|
|
129
|
-
def painfully_slow_threshold
|
|
130
|
-
Minitest::Heat.configuration.painfully_slow_threshold
|
|
131
|
-
end
|
|
125
|
+
def painfully_slow_threshold = Minitest::Heat.configuration.painfully_slow_threshold
|
|
132
126
|
|
|
133
127
|
# Determines if a test should be considered slow by comparing it to the low end definition of
|
|
134
128
|
# what is considered slow.
|
|
135
129
|
#
|
|
136
130
|
# @return [Boolean] true if the test took longer to run than `slow_threshold`
|
|
137
|
-
def slow?
|
|
138
|
-
execution_time >= slow_threshold && execution_time < painfully_slow_threshold
|
|
139
|
-
end
|
|
131
|
+
def slow? = execution_time >= slow_threshold && execution_time < painfully_slow_threshold
|
|
140
132
|
|
|
141
133
|
# Determines if a test should be considered painfully slow by comparing it to the high end
|
|
142
134
|
# definition of what is considered slow.
|
|
143
135
|
#
|
|
144
136
|
# @return [Boolean] true if the test took longer to run than `painfully_slow_threshold`
|
|
145
|
-
def painful?
|
|
146
|
-
execution_time >= painfully_slow_threshold
|
|
147
|
-
end
|
|
137
|
+
def painful? = execution_time >= painfully_slow_threshold
|
|
148
138
|
|
|
149
139
|
# Determines if the issue is an exception that was raised from directly within a test
|
|
150
140
|
# definition. In these cases, it's more likely to be a quick fix.
|
|
151
141
|
#
|
|
152
142
|
# @return [Boolean] true if the final locations of the stacktrace was a test file
|
|
153
|
-
def in_test?
|
|
154
|
-
locations.broken_test?
|
|
155
|
-
end
|
|
143
|
+
def in_test? = locations.broken_test?
|
|
156
144
|
|
|
157
145
|
# Determines if the issue is an exception that was raised from directly within the project
|
|
158
146
|
# codebase.
|
|
159
147
|
#
|
|
160
148
|
# @return [Boolean] true if the final locations of the stacktrace was a file from the project
|
|
161
149
|
# (as opposed to a dependency or Ruby library)
|
|
162
|
-
def in_source?
|
|
163
|
-
locations.proper_failure?
|
|
164
|
-
end
|
|
150
|
+
def in_source? = locations.proper_failure?
|
|
165
151
|
|
|
166
152
|
# Was the result a pass? i.e. Skips aren't passes or failures. Slows are still passes. So this
|
|
167
153
|
# is purely a measure of whether the test explicitly passed all assertions
|
|
168
154
|
#
|
|
169
155
|
# @return [Boolean] false for errors, failures, or skips, true for passes (including slows)
|
|
170
|
-
def passed?
|
|
171
|
-
passed
|
|
172
|
-
end
|
|
156
|
+
def passed? = passed
|
|
173
157
|
|
|
174
158
|
# Was there an exception that triggered a failure?
|
|
175
159
|
#
|
|
176
160
|
# @return [Boolean] true if there's an exception
|
|
177
|
-
def error?
|
|
178
|
-
error
|
|
179
|
-
end
|
|
161
|
+
def error? = error
|
|
180
162
|
|
|
181
163
|
# Was the test skipped?
|
|
182
164
|
#
|
|
183
165
|
# @return [Boolean] true if the test was explicitly skipped, false otherwise
|
|
184
|
-
def skipped?
|
|
185
|
-
skipped
|
|
186
|
-
end
|
|
166
|
+
def skipped? = skipped
|
|
187
167
|
|
|
188
168
|
# The more nuanced detail of the failure. If it's an error, digs into the exception. Otherwise
|
|
189
169
|
# uses the message from the result
|
|
190
170
|
#
|
|
191
171
|
# @return [String] a more detailed explanation of the issue
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
error? ? first_line_of_exception_message : message
|
|
196
|
-
end
|
|
172
|
+
# When there's an exception, use the first line from the exception message. Otherwise, the
|
|
173
|
+
# message represents explanation for a test failure, and should be used in full
|
|
174
|
+
def summary = error? ? first_line_of_exception_message : message
|
|
197
175
|
|
|
198
176
|
# Returns the first line of an exception message when the issue is from a proper exception
|
|
199
177
|
# failure since exception messages can be long and cumbersome.
|
|
@@ -207,9 +185,7 @@ module Minitest
|
|
|
207
185
|
text.size > exception_message_limit ? "#{text[0..exception_message_limit]}..." : text
|
|
208
186
|
end
|
|
209
187
|
|
|
210
|
-
def exception_message_limit
|
|
211
|
-
200
|
|
212
|
-
end
|
|
188
|
+
def exception_message_limit = 200
|
|
213
189
|
|
|
214
190
|
# Generates a hash representation for JSON serialization
|
|
215
191
|
#
|