tryouts 3.5.1 → 3.5.2
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/README.md +5 -8
- data/lib/tryouts/cli/formatters/agent.rb +33 -15
- data/lib/tryouts/cli/opts.rb +15 -15
- data/lib/tryouts/file_processor.rb +2 -2
- data/lib/tryouts/parser_warning.rb +10 -0
- data/lib/tryouts/parsers/CLAUDE.md +178 -0
- data/lib/tryouts/parsers/base_parser.rb +101 -1
- data/lib/tryouts/parsers/enhanced_parser.rb +177 -25
- data/lib/tryouts/parsers/legacy_parser.rb +254 -0
- data/lib/tryouts/parsers/shared_methods.rb +5 -1
- data/lib/tryouts/test_batch.rb +1 -1
- data/lib/tryouts/test_executor.rb +12 -4
- data/lib/tryouts/test_result_aggregator.rb +15 -11
- data/lib/tryouts/test_runner.rb +18 -15
- data/lib/tryouts/version.rb +1 -1
- data/lib/tryouts.rb +1 -1
- metadata +3 -2
- data/lib/tryouts/parsers/prism_parser.rb +0 -122
data/lib/tryouts/test_runner.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# lib/tryouts/test_runner.rb
|
2
2
|
|
3
3
|
require 'concurrent'
|
4
|
-
require_relative 'parsers/
|
4
|
+
require_relative 'parsers/legacy_parser'
|
5
5
|
require_relative 'parsers/enhanced_parser'
|
6
6
|
require_relative 'test_batch'
|
7
7
|
require_relative 'translators/rspec_translator'
|
@@ -24,11 +24,11 @@ class Tryouts
|
|
24
24
|
}.freeze
|
25
25
|
|
26
26
|
def initialize(files:, options:, output_manager:)
|
27
|
-
@files
|
28
|
-
@options
|
29
|
-
@output_manager
|
30
|
-
@translator
|
31
|
-
@global_tally
|
27
|
+
@files = files
|
28
|
+
@options = apply_framework_defaults(options)
|
29
|
+
@output_manager = output_manager
|
30
|
+
@translator = initialize_translator
|
31
|
+
@global_tally = initialize_global_tally
|
32
32
|
@file_line_specs = options[:file_line_specs] || {}
|
33
33
|
end
|
34
34
|
|
@@ -44,8 +44,11 @@ class Tryouts
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# For agent critical mode, only count errors as failures
|
47
|
-
if @options[:agent] && (
|
48
|
-
|
47
|
+
if @options[:agent] && ([:critical, 'critical'].include?(@options[:agent_focus]))
|
48
|
+
# Include infrastructure failures as errors for agent critical mode
|
49
|
+
display_errors = @global_tally[:aggregator].get_display_counts[:errors]
|
50
|
+
infrastructure_errors = @global_tally[:aggregator].infrastructure_failure_count
|
51
|
+
display_errors + infrastructure_errors
|
49
52
|
else
|
50
53
|
result
|
51
54
|
end
|
@@ -118,7 +121,7 @@ class Tryouts
|
|
118
121
|
min_threads: 1,
|
119
122
|
max_threads: pool_size,
|
120
123
|
max_queue: @files.length, # Queue size must accommodate all files
|
121
|
-
fallback_policy: :abort # Raise exception if pool and queue are exhausted
|
124
|
+
fallback_policy: :abort, # Raise exception if pool and queue are exhausted
|
122
125
|
)
|
123
126
|
|
124
127
|
# Submit all file processing tasks to the thread pool
|
@@ -132,15 +135,15 @@ class Tryouts
|
|
132
135
|
failure_count = 0
|
133
136
|
futures.each_with_index do |future, idx|
|
134
137
|
begin
|
135
|
-
result
|
138
|
+
result = future.value # This blocks until the future completes
|
136
139
|
failure_count += result unless result.zero?
|
137
140
|
|
138
141
|
status = result.zero? ? Console.color(:green, 'PASS') : Console.color(:red, 'FAIL')
|
139
|
-
file
|
142
|
+
file = @files[idx]
|
140
143
|
@output_manager.info "#{status} #{Console.pretty_path(file)} (#{result} failures)", 1
|
141
144
|
rescue StandardError => ex
|
142
145
|
failure_count += 1
|
143
|
-
file
|
146
|
+
file = @files[idx]
|
144
147
|
@output_manager.info "#{Console.color(:red, 'ERROR')} #{Console.pretty_path(file)} (#{ex.message})", 1
|
145
148
|
end
|
146
149
|
end
|
@@ -184,10 +187,10 @@ class Tryouts
|
|
184
187
|
end
|
185
188
|
|
186
189
|
def show_grand_total
|
187
|
-
elapsed_time
|
188
|
-
aggregator
|
190
|
+
elapsed_time = Time.now - @global_tally[:start_time]
|
191
|
+
aggregator = @global_tally[:aggregator]
|
189
192
|
display_counts = aggregator.get_display_counts
|
190
|
-
file_counts
|
193
|
+
file_counts = aggregator.get_file_counts
|
191
194
|
|
192
195
|
@output_manager.grand_total(
|
193
196
|
display_counts[:total_tests],
|
data/lib/tryouts/version.rb
CHANGED
data/lib/tryouts.rb
CHANGED
@@ -8,7 +8,7 @@ TRYOUTS_LIB_HOME = __dir__ unless defined?(TRYOUTS_LIB_HOME)
|
|
8
8
|
require_relative 'tryouts/console'
|
9
9
|
require_relative 'tryouts/test_batch'
|
10
10
|
require_relative 'tryouts/version'
|
11
|
-
require_relative 'tryouts/parsers/
|
11
|
+
require_relative 'tryouts/parsers/legacy_parser'
|
12
12
|
require_relative 'tryouts/parsers/enhanced_parser'
|
13
13
|
require_relative 'tryouts/cli'
|
14
14
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tryouts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.5.
|
4
|
+
version: 3.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -171,9 +171,10 @@ files:
|
|
171
171
|
- lib/tryouts/failure_collector.rb
|
172
172
|
- lib/tryouts/file_processor.rb
|
173
173
|
- lib/tryouts/parser_warning.rb
|
174
|
+
- lib/tryouts/parsers/CLAUDE.md
|
174
175
|
- lib/tryouts/parsers/base_parser.rb
|
175
176
|
- lib/tryouts/parsers/enhanced_parser.rb
|
176
|
-
- lib/tryouts/parsers/
|
177
|
+
- lib/tryouts/parsers/legacy_parser.rb
|
177
178
|
- lib/tryouts/parsers/shared_methods.rb
|
178
179
|
- lib/tryouts/test_batch.rb
|
179
180
|
- lib/tryouts/test_case.rb
|
@@ -1,122 +0,0 @@
|
|
1
|
-
# lib/tryouts/parsers/prism_parser.rb
|
2
|
-
|
3
|
-
require_relative '../test_case'
|
4
|
-
require_relative 'base_parser'
|
5
|
-
|
6
|
-
class Tryouts
|
7
|
-
# Fixed PrismParser with pattern matching for robust token filtering
|
8
|
-
class PrismParser < Tryouts::Parsers::BaseParser
|
9
|
-
|
10
|
-
def parse
|
11
|
-
return handle_syntax_errors if @prism_result.failure?
|
12
|
-
|
13
|
-
tokens = tokenize_content
|
14
|
-
test_boundaries = find_test_case_boundaries(tokens)
|
15
|
-
tokens = classify_potential_descriptions_with_boundaries(tokens, test_boundaries)
|
16
|
-
test_blocks = group_into_test_blocks(tokens)
|
17
|
-
process_test_blocks(test_blocks)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
# Tokenize content using pattern matching for clean line classification
|
23
|
-
def tokenize_content
|
24
|
-
tokens = []
|
25
|
-
|
26
|
-
@lines.each_with_index do |line, index|
|
27
|
-
token = case line
|
28
|
-
in /^##\s*(.*)$/ # Test description format: ## description
|
29
|
-
{ type: :description, content: $1.strip, line: index }
|
30
|
-
in /^#\s*TEST\s*\d*:\s*(.*)$/ # rubocop:disable Lint/DuplicateBranch
|
31
|
-
{ type: :description, content: $1.strip, line: index }
|
32
|
-
in /^#\s*=!>\s*(.*)$/ # Exception expectation (updated for consistency)
|
33
|
-
{ type: :exception_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
34
|
-
in /^#\s*=<>\s*(.*)$/ # Intentional failure expectation
|
35
|
-
{ type: :intentional_failure_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
36
|
-
in /^#\s*==>\s*(.*)$/ # Boolean true expectation
|
37
|
-
{ type: :true_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
38
|
-
in %r{^#\s*=/=>\s*(.*)$} # Boolean false expectation
|
39
|
-
{ type: :false_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
40
|
-
in /^#\s*=\|>\s*(.*)$/ # Boolean (true or false) expectation
|
41
|
-
{ type: :boolean_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
42
|
-
in /^#\s*=\*>\s*(.*)$/ # Non-nil expectation
|
43
|
-
{ type: :non_nil_expectation, content: $1.strip, line: index }
|
44
|
-
in /^#\s*=:>\s*(.*)$/ # Result type expectation
|
45
|
-
{ type: :result_type_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
46
|
-
in /^#\s*=~>\s*(.*)$/ # Regex match expectation
|
47
|
-
{ type: :regex_match_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
48
|
-
in /^#\s*=%>\s*(.*)$/ # Performance time expectation
|
49
|
-
{ type: :performance_time_expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
50
|
-
in /^#\s*=(\d+)>\s*(.*)$/ # Output expectation (stdout/stderr with pipe number)
|
51
|
-
{ type: :output_expectation, content: $2.strip, pipe: $1.to_i, line: index, ast: parse_expectation($2.strip) }
|
52
|
-
in /^#\s*=>\s*(.*)$/ # Regular expectation
|
53
|
-
{ type: :expectation, content: $1.strip, line: index, ast: parse_expectation($1.strip) }
|
54
|
-
in /^##\s*=>\s*(.*)$/ # Commented out expectation (should be ignored)
|
55
|
-
{ type: :comment, content: '=>' + $1.strip, line: index }
|
56
|
-
in /^#\s*(.*)$/ # Single hash comment - potential description
|
57
|
-
{ type: :potential_description, content: $1.strip, line: index }
|
58
|
-
in /^\s*$/ # Blank line
|
59
|
-
{ type: :blank, line: index }
|
60
|
-
else # Ruby code
|
61
|
-
{ type: :code, content: line, line: index, ast: parse_ruby_line(line) }
|
62
|
-
end
|
63
|
-
|
64
|
-
tokens << token
|
65
|
-
end
|
66
|
-
|
67
|
-
# Return tokens with potential_descriptions - they'll be classified later with test boundaries
|
68
|
-
tokens
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
# Convert potential_descriptions to descriptions or comments based on context
|
73
|
-
def classify_potential_descriptions(tokens)
|
74
|
-
tokens.map.with_index do |token, index|
|
75
|
-
if token[:type] == :potential_description
|
76
|
-
# Check if this looks like a test description based on content and context
|
77
|
-
content = token[:content].strip
|
78
|
-
|
79
|
-
# Skip if it's clearly just a regular comment (short, lowercase, etc.)
|
80
|
-
# Test descriptions are typically longer and more descriptive
|
81
|
-
looks_like_regular_comment = content.length < 20 &&
|
82
|
-
content.downcase == content &&
|
83
|
-
!content.match?(/test|example|demonstrate|show/i)
|
84
|
-
|
85
|
-
# Check if there's code immediately before this (suggesting it's mid-test)
|
86
|
-
prev_token = index > 0 ? tokens[index - 1] : nil
|
87
|
-
has_code_before = prev_token && prev_token[:type] == :code
|
88
|
-
|
89
|
-
if looks_like_regular_comment || has_code_before
|
90
|
-
# Treat as regular comment
|
91
|
-
token.merge(type: :comment)
|
92
|
-
else
|
93
|
-
# Look ahead for test pattern: code + at least one expectation within reasonable distance
|
94
|
-
following_tokens = tokens[(index + 1)..]
|
95
|
-
|
96
|
-
# Skip blanks and comments to find meaningful content
|
97
|
-
meaningful_following = following_tokens.reject { |t| [:blank, :comment].include?(t[:type]) }
|
98
|
-
|
99
|
-
# Look for test pattern: at least one code token followed by at least one expectation
|
100
|
-
# within the next 10 meaningful tokens (to avoid matching setup/teardown)
|
101
|
-
test_window = meaningful_following.first(10)
|
102
|
-
has_code = test_window.any? { |t| t[:type] == :code }
|
103
|
-
has_expectation = test_window.any? { |t| is_expectation_type?(t[:type]) }
|
104
|
-
|
105
|
-
if has_code && has_expectation
|
106
|
-
token.merge(type: :description)
|
107
|
-
else
|
108
|
-
token.merge(type: :comment)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
else
|
112
|
-
token
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Parser type identification for metadata
|
118
|
-
def parser_type
|
119
|
-
:prism_v2_fixed
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|