minitest-heat 2.0.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 +18 -1
- data/Gemfile +12 -2
- data/Gemfile.lock +61 -4
- data/README.md +9 -4
- data/lib/minitest/heat/backtrace/line_count.rb +1 -1
- data/lib/minitest/heat/backtrace.rb +5 -15
- data/lib/minitest/heat/configuration.rb +11 -4
- data/lib/minitest/heat/hit.rb +5 -12
- data/lib/minitest/heat/issue.rb +22 -41
- 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,23 @@
|
|
|
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
|
+
|
|
14
|
+
## [2.1.0] - 2026-01-30
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- `inherently_slow_paths` configuration option to exclude directories (e.g. `test/system`, `test/integration`) from slow test reporting. Tests in listed paths still run and report errors and failures — they just aren't flagged as slow or painfully slow. ([#5](https://github.com/garrettdimon/minitest-heat/issues/5))
|
|
18
|
+
|
|
19
|
+
## [2.0.0] - 2026-01-29
|
|
20
|
+
|
|
3
21
|
### Breaking
|
|
4
22
|
- Require Ruby >= 3.2 (dropped 3.1 support)
|
|
5
23
|
|
|
@@ -57,4 +75,3 @@ The biggest update is that the slow thresholds are now configurable.
|
|
|
57
75
|
## [1.0.0] - 2021-12-01
|
|
58
76
|
|
|
59
77
|
Initial release.
|
|
60
|
-
|
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.
|
|
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
|
data/README.md
CHANGED
|
@@ -67,17 +67,22 @@ Minitest::Heat.configure do |config|
|
|
|
67
67
|
end
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
###
|
|
70
|
+
### Inherently Slow Paths
|
|
71
71
|
|
|
72
|
-
System tests and
|
|
72
|
+
System tests, integration tests, and other browser-driven tests are inherently slower than unit tests. Rather than raising your global thresholds to accommodate them, you can tell Minitest Heat which paths to exclude from slow test reporting. Tests in those directories still run and report errors and failures normally—they just aren't evaluated against the timing thresholds.
|
|
73
73
|
|
|
74
74
|
```ruby
|
|
75
75
|
Minitest::Heat.configure do |config|
|
|
76
|
-
config.
|
|
77
|
-
config.painfully_slow_threshold = 10.0
|
|
76
|
+
config.inherently_slow_paths = ['test/system', 'test/integration']
|
|
78
77
|
end
|
|
79
78
|
```
|
|
80
79
|
|
|
80
|
+
Any test whose file path starts with a listed prefix is excluded. Common paths to consider:
|
|
81
|
+
|
|
82
|
+
- `test/system` — Rails system tests (browser-driven)
|
|
83
|
+
- `test/integration` — Integration tests with broader scope
|
|
84
|
+
- `test/e2e` — End-to-end tests
|
|
85
|
+
|
|
81
86
|
### Example: Gem Development
|
|
82
87
|
|
|
83
88
|
For a gem with fast unit tests, stricter thresholds catch performance regressions early:
|
|
@@ -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
|
|
@@ -7,16 +7,23 @@ module Minitest
|
|
|
7
7
|
# For managing configuration options on how Minitest Heat should handle results
|
|
8
8
|
class Configuration
|
|
9
9
|
DEFAULTS = {
|
|
10
|
-
slow_threshold:
|
|
11
|
-
painfully_slow_threshold: 3.0
|
|
10
|
+
slow_threshold: 1.0,
|
|
11
|
+
painfully_slow_threshold: 3.0,
|
|
12
|
+
inherently_slow_paths: []
|
|
12
13
|
}.freeze
|
|
13
14
|
|
|
14
15
|
attr_accessor :slow_threshold,
|
|
15
|
-
:painfully_slow_threshold
|
|
16
|
+
:painfully_slow_threshold,
|
|
17
|
+
:inherently_slow_paths
|
|
16
18
|
|
|
17
19
|
def initialize
|
|
18
|
-
@slow_threshold
|
|
20
|
+
@slow_threshold = DEFAULTS[:slow_threshold]
|
|
19
21
|
@painfully_slow_threshold = DEFAULTS[:painfully_slow_threshold]
|
|
22
|
+
@inherently_slow_paths = DEFAULTS[:inherently_slow_paths].dup
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def inherently_slow_path?(path)
|
|
26
|
+
inherently_slow_paths.any? { |prefix| path.start_with?(prefix) }
|
|
20
27
|
end
|
|
21
28
|
end
|
|
22
29
|
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|
|