tryouts 3.1.1 → 3.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca346c47683b393c8c60c586ab053a73c09b7d5f3e19ce184b35453135ae6594
4
- data.tar.gz: 2ba211232994981e53393167cce8e09fc29bbc988d14b9ac3178321cbf158aaf
3
+ metadata.gz: d2dea4f111f12c35d204df54313a62045bd9e8841710b19323454e5a626ac4fd
4
+ data.tar.gz: 275b234c7ce6ca2debd28e9d861053bc041e825443683078fee710de2b45e0cf
5
5
  SHA512:
6
- metadata.gz: 12f4d97b1f2049f1f6df4d0badca42d2a585360f12678e678cfbbcb85e0768cc2365eb7eb09a744713df15e2d51d3df9690fde78d160ff73947d2d9bdf986aa9
7
- data.tar.gz: d919d1923c471aaa240f66dd0f03760bf7f5f9e53f71c35f8ace03d84935648dc21dafd5c8dceb68468a1b7e31ed6a47ad554471758d6e345146e15a661eca4f
6
+ metadata.gz: 6c704d75d9bed36875b843b6014508df36292247e9c03bbc68892f1d7318db0cfd8ff9907c9c45d71d45441e9512dd5550e4c47b84a9075285ccf8980474c4b9
7
+ data.tar.gz: 0230e782d3a214bb92e647d2beb38e3b3ce1d3bbc129f6628ca14b0b7cef1430fee94ee7746bda55e78a8236da5df1fbf7b6270a8f0a186646f5a01662d0d667
data/exe/try CHANGED
@@ -46,8 +46,8 @@ begin
46
46
  expanded_files = []
47
47
  files.each do |file_or_dir|
48
48
  if File.directory?(file_or_dir)
49
- # If it's a directory, find all *_try.rb files within it
50
- dir_files = Dir.glob('**/*_try.rb', base: file_or_dir)
49
+ # If it's a directory, find all *_try.rb and *.try.rb files within it
50
+ dir_files = Dir.glob(['**/*_try.rb', '**/*.try.rb'], base: file_or_dir)
51
51
  expanded_files.concat(dir_files.map { |f| File.join(file_or_dir, f) })
52
52
  else
53
53
  # If it's a file, add it as-is
@@ -59,7 +59,7 @@ begin
59
59
  # Default file discovery if no files specified
60
60
  if files.empty?
61
61
  raw_files = Dir.glob(
62
- ['{app,apps,lib,try,tryouts}/**/*_try.rb', './*_try.rb'],
62
+ ['{app,apps,lib,try,tryouts}/**/*_try.rb', './*_try.rb', '{app,apps,lib,try,tryouts}/**/*.try.rb', './*.try.rb'],
63
63
  base: Dir.pwd,
64
64
  )
65
65
 
@@ -7,7 +7,6 @@ class Tryouts
7
7
  class CLI
8
8
  # Enhanced interface for all test output formatting
9
9
  module FormatterInterface
10
-
11
10
  attr_reader :current_indent
12
11
 
13
12
  # Phase-level output (major sections)
@@ -115,6 +114,5 @@ class Tryouts
115
114
  @current_indent = old_indent
116
115
  end
117
116
  end
118
-
119
117
  end
120
118
  end
@@ -22,7 +22,7 @@ class Tryouts
22
22
  io.puts text
23
23
  when 1
24
24
  # Skip execution phase headers - they create unwanted empty lines
25
- return
25
+ nil
26
26
  else
27
27
  # Other phase headers with minimal formatting
28
28
  io.puts indent_text(message, level - 1)
@@ -112,8 +112,8 @@ class Tryouts
112
112
  return if result_packet.passed? && !@show_passed
113
113
 
114
114
  test_case = result_packet.test_case
115
- desc = test_case.description.to_s
116
- desc = 'unnamed test' if desc.empty?
115
+ desc = test_case.description.to_s
116
+ desc = 'unnamed test' if desc.empty?
117
117
 
118
118
  case result_packet.status
119
119
  when :passed
@@ -133,6 +133,7 @@ class Tryouts
133
133
  if test_case.source_lines && test_case.source_lines.size <= 3
134
134
  test_case.source_lines.each do |line|
135
135
  next if line.strip.empty? || line.strip.start_with?('#')
136
+
136
137
  io.puts indent_text(" #{line.strip}", 1)
137
138
  break # Only show first relevant line
138
139
  end
@@ -209,7 +210,7 @@ class Tryouts
209
210
 
210
211
  time_str = format_timing(elapsed_time)
211
212
 
212
- io.puts "Total: #{result} (#{time_str})"
213
+ io.puts "Total: #{result} #{time_str}"
213
214
  io.puts "Files: #{successful_files} of #{total_files} successful"
214
215
  end
215
216
 
@@ -112,7 +112,7 @@ class Tryouts
112
112
 
113
113
  issues_count = failed_count + error_count
114
114
  if issues_count > 0
115
- passed = [total_tests - issues_count, 0].max # Ensure passed never goes negative
115
+ passed = [total_tests - issues_count, 0].max # Ensure passed never goes negative
116
116
  details = []
117
117
  details << "#{failed_count} failed" if failed_count > 0
118
118
  details << "#{error_count} errors" if error_count > 0
@@ -80,7 +80,7 @@ class Tryouts
80
80
  details = [
81
81
  "#{passed_count} passed",
82
82
  ]
83
-
83
+ puts
84
84
  if issues_count > 0
85
85
  details << "#{failed_count} failed" if failed_count > 0
86
86
  details << "#{error_count} errors" if error_count > 0
@@ -134,7 +134,7 @@ class Tryouts
134
134
  end
135
135
 
136
136
  test_case = result_packet.test_case
137
- location = "#{Console.pretty_path(test_case.path)}:#{test_case.first_expectation_line + 1}"
137
+ location = "#{Console.pretty_path(test_case.path)}:#{test_case.first_expectation_line + 1}"
138
138
  puts
139
139
  puts indent_text("#{status_line} @ #{location}", 2)
140
140
 
@@ -181,6 +181,7 @@ class Tryouts
181
181
  def teardown_start(line_range)
182
182
  message = "Executing teardown (lines #{line_range.first}..#{line_range.last})"
183
183
  puts indent_text(Console.color(:cyan, message), 2)
184
+ puts
184
185
  end
185
186
 
186
187
  def teardown_output(output_text)
@@ -278,7 +279,7 @@ class Tryouts
278
279
  puts indent_text('Exception Details:', 4)
279
280
 
280
281
  actual_results.each_with_index do |actual, idx|
281
- expected = expected_results[idx] if expected_results && idx < expected_results.length
282
+ expected = expected_results[idx] if expected_results && idx < expected_results.length
282
283
  expectation = test_case.expectations[idx] if test_case.expectations
283
284
 
284
285
  if expectation&.type == :exception
@@ -299,7 +300,7 @@ class Tryouts
299
300
  line_display = format('%3d: %s', line_num + 1, line_content)
300
301
 
301
302
  # Highlight expectation lines by checking if this line contains any expectation syntax
302
- if line_content.match?(/^\s*#\s*=(!|<|=|\/=|\||:|~|%|\d+)?>\s*/)
303
+ if line_content.match?(%r{^\s*#\s*=(!|<|=|/=|\||:|~|%|\d+)?>\s*})
303
304
  line_display = Console.color(:yellow, line_display)
304
305
  end
305
306
 
@@ -319,12 +320,13 @@ class Tryouts
319
320
  # Use the evaluated expected value from the evaluator
320
321
  puts indent_text("Expected: #{Console.color(:green, expected.inspect)}", 4)
321
322
  puts indent_text("Actual: #{Console.color(:red, actual.inspect)}", 4)
322
- elsif expected_line
323
- # Fallback to raw expectation content
323
+ elsif expected_line && !expected_results.empty?
324
+ # Only show raw expectation content if we have expected_results (non-error case)
324
325
  puts indent_text("Expected: #{Console.color(:green, expected_line.content)}", 4)
325
326
  puts indent_text("Actual: #{Console.color(:red, actual.inspect)}", 4)
326
327
  else
327
- puts indent_text("Actual: #{Console.color(:red, actual.inspect)}", 4)
328
+ # For error cases (empty expected_results), just show the error
329
+ puts indent_text("Error: #{Console.color(:red, actual.inspect)}", 4)
328
330
  end
329
331
 
330
332
  # Show difference if both are strings
@@ -143,7 +143,7 @@ class Tryouts
143
143
 
144
144
  # Enable colors if neither appears redirected
145
145
  return "\e[%sm" % att.join(';') unless stdout_redirected || stderr_redirected
146
- rescue
146
+ rescue StandardError
147
147
  # If stat fails, fall back to enabling colors with TERM set
148
148
  return "\e[%sm" % att.join(';')
149
149
  end
@@ -45,7 +45,7 @@ class Tryouts
45
45
 
46
46
  def evaluate(actual_result = nil)
47
47
  expectation_result = ExpectationResult.from_result(actual_result)
48
- expression_result = eval_expectation_content(@expectation.content, expectation_result)
48
+ expression_result = eval_expectation_content(@expectation.content, expectation_result)
49
49
 
50
50
  build_result(
51
51
  passed: [true, false].include?(expression_result),
@@ -22,7 +22,7 @@ class Tryouts
22
22
 
23
23
  # Create result packet for evaluation to show what was expected
24
24
  expectation_result = ExpectationResult.from_result(nil)
25
- expected_value = eval_expectation_content(@expectation.content, expectation_result)
25
+ expected_value = eval_expectation_content(@expectation.content, expectation_result)
26
26
 
27
27
  build_result(
28
28
  passed: false,
@@ -41,7 +41,7 @@ class Tryouts
41
41
  @context.define_singleton_method(:error) { caught_error }
42
42
 
43
43
  expectation_result = ExpectationResult.from_result(caught_error)
44
- expected_value = eval_expectation_content(@expectation.content, expectation_result)
44
+ expected_value = eval_expectation_content(@expectation.content, expectation_result)
45
45
 
46
46
  build_result(
47
47
  passed: !!expected_value,
@@ -32,7 +32,7 @@ class Tryouts
32
32
  start_time_ns: nil,
33
33
  end_time_ns: nil,
34
34
  stdout_content: nil,
35
- stderr_content: nil
35
+ stderr_content: nil,
36
36
  )
37
37
  end
38
38
 
@@ -46,7 +46,7 @@ class Tryouts
46
46
  start_time_ns: start_time_ns,
47
47
  end_time_ns: end_time_ns,
48
48
  stdout_content: nil,
49
- stderr_content: nil
49
+ stderr_content: nil,
50
50
  )
51
51
  end
52
52
 
@@ -59,7 +59,7 @@ class Tryouts
59
59
  start_time_ns: nil,
60
60
  end_time_ns: nil,
61
61
  stdout_content: stdout_content,
62
- stderr_content: stderr_content
62
+ stderr_content: stderr_content,
63
63
  )
64
64
  end
65
65
  end
@@ -45,7 +45,7 @@ class Tryouts
45
45
 
46
46
  def evaluate(actual_result = nil)
47
47
  expectation_result = ExpectationResult.from_result(actual_result)
48
- expression_result = eval_expectation_content(@expectation.content, expectation_result)
48
+ expression_result = eval_expectation_content(@expectation.content, expectation_result)
49
49
 
50
50
  build_result(
51
51
  passed: expression_result == false,
@@ -56,14 +56,14 @@ class Tryouts
56
56
 
57
57
  # Delegate to regular evaluator
58
58
  regular_evaluator = Regular.new(regular_expectation, @test_case, @context)
59
- regular_result = regular_evaluator.evaluate(actual_result)
59
+ regular_result = regular_evaluator.evaluate(actual_result)
60
60
 
61
61
  # Invert the result while preserving metadata
62
62
  build_result(
63
63
  passed: !regular_result[:passed],
64
64
  actual: regular_result[:actual],
65
65
  expected: "NOT #{regular_result[:expected]} (intentional failure)",
66
- expectation: @expectation.content
66
+ expectation: @expectation.content,
67
67
  )
68
68
  rescue StandardError => ex
69
69
  # If evaluation itself fails (not the expectation), that's a real error
@@ -56,9 +56,9 @@ class Tryouts
56
56
 
57
57
  # Get the appropriate captured content
58
58
  captured_content = case pipe_number
59
- when 1 then stdout_content || ""
60
- when 2 then stderr_content || ""
61
- else ""
59
+ when 1 then stdout_content || ''
60
+ when 2 then stderr_content || ''
61
+ else ''
62
62
  end
63
63
 
64
64
  # Create result packet for expression evaluation
@@ -82,8 +82,8 @@ class Tryouts
82
82
 
83
83
  # Build result with appropriate pipe description
84
84
  pipe_name = case pipe_number
85
- when 1 then "stdout"
86
- when 2 then "stderr"
85
+ when 1 then 'stdout'
86
+ when 2 then 'stderr'
87
87
  else "pipe#{pipe_number}"
88
88
  end
89
89
 
@@ -91,7 +91,7 @@ class Tryouts
91
91
  passed: matched,
92
92
  actual: "#{pipe_name}: #{captured_content.inspect}",
93
93
  expected: expected_pattern.inspect,
94
- expectation: @expectation.content
94
+ expectation: @expectation.content,
95
95
  )
96
96
  rescue StandardError => ex
97
97
  handle_evaluation_error(ex, actual_result)
@@ -54,18 +54,18 @@ class Tryouts
54
54
  passed: false,
55
55
  actual: 'No timing data available',
56
56
  expected: 'Performance measurement',
57
- error: 'Performance expectations require execution timing data'
57
+ error: 'Performance expectations require execution timing data',
58
58
  )
59
59
  end
60
60
 
61
61
  # Create result packet with timing data available to expectation
62
62
  expectation_result = ExpectationResult.from_timing(actual_result, execution_time_ns)
63
- expected_limit_ms = eval_expectation_content(@expectation.content, expectation_result)
63
+ expected_limit_ms = eval_expectation_content(@expectation.content, expectation_result)
64
64
 
65
65
  actual_time_ms = expectation_result.execution_time_ms
66
66
 
67
67
  # Performance tolerance: actual <= expected + 10% (not strict window)
68
- max_allowed_ms = expected_limit_ms * 1.1
68
+ max_allowed_ms = expected_limit_ms * 1.1
69
69
  within_tolerance = actual_time_ms <= max_allowed_ms
70
70
 
71
71
  build_result(
@@ -38,11 +38,11 @@ class Tryouts
38
38
 
39
39
  def evaluate(actual_result = nil)
40
40
  expectation_result = ExpectationResult.from_result(actual_result)
41
- pattern = eval_expectation_content(@expectation.content, expectation_result)
41
+ pattern = eval_expectation_content(@expectation.content, expectation_result)
42
42
 
43
43
  # Convert actual_result to string for regex matching
44
44
  string_result = actual_result.to_s
45
- match_result = string_result =~ pattern
45
+ match_result = string_result =~ pattern
46
46
 
47
47
  build_result(
48
48
  passed: !match_result.nil?,
@@ -52,7 +52,7 @@ class Tryouts
52
52
 
53
53
  def evaluate(actual_result = nil)
54
54
  expectation_result = ExpectationResult.from_result(actual_result)
55
- expected_value = eval_expectation_content(@expectation.content, expectation_result)
55
+ expected_value = eval_expectation_content(@expectation.content, expectation_result)
56
56
 
57
57
  build_result(
58
58
  passed: actual_result == expected_value,
@@ -36,7 +36,7 @@ class Tryouts
36
36
 
37
37
  def evaluate(actual_result = nil)
38
38
  expectation_result = ExpectationResult.from_result(actual_result)
39
- expected_class = eval_expectation_content(@expectation.content, expectation_result)
39
+ expected_class = eval_expectation_content(@expectation.content, expectation_result)
40
40
 
41
41
  build_result(
42
42
  passed: actual_result.is_a?(expected_class),
@@ -42,8 +42,8 @@ class Tryouts
42
42
  end
43
43
 
44
44
  def evaluate(actual_result = nil)
45
- expectation_result = ExpectationResult.from_result(actual_result)
46
- expression_result = eval_expectation_content(@expectation.content, expectation_result)
45
+ expectation_result = ExpectationResult.from_result(actual_result)
46
+ expression_result = eval_expectation_content(@expectation.content, expectation_result)
47
47
 
48
48
  build_result(
49
49
  passed: expression_result == true,
@@ -83,7 +83,7 @@ class Tryouts
83
83
  # Find the end of this test case by looking for the last expectation
84
84
  # before the next description or end of file
85
85
  start_line = token[:line]
86
- end_line = find_test_case_end(tokens, index)
86
+ end_line = find_test_case_end(tokens, index)
87
87
 
88
88
  boundaries << { start: start_line, end: end_line } if end_line
89
89
  end
@@ -118,10 +118,10 @@ class Tryouts
118
118
  tokens.map.with_index do |token, index|
119
119
  if token[:type] == :potential_description
120
120
  # Check if this comment falls within any test case boundary
121
- line_num = token[:line]
122
- within_test_case = test_boundaries.any? { |boundary|
121
+ line_num = token[:line]
122
+ within_test_case = test_boundaries.any? do |boundary|
123
123
  line_num >= boundary[:start] && line_num <= boundary[:end]
124
- }
124
+ end
125
125
 
126
126
  if within_test_case
127
127
  # This comment is within a test case, treat as regular comment
@@ -134,10 +134,10 @@ class Tryouts
134
134
 
135
135
  # Check if this looks like a test description based on content
136
136
  looks_like_test_description = content.match?(/test|example|demonstrate|show|should|when|given/i) &&
137
- content.length > 10
137
+ content.length > 10
138
138
 
139
139
  # Check if there's code immediately before this (suggesting it's mid-test)
140
- prev_token = index > 0 ? tokens[index - 1] : nil
140
+ prev_token = index > 0 ? tokens[index - 1] : nil
141
141
  has_code_before = prev_token && prev_token[:type] == :code
142
142
 
143
143
  if has_code_before || !looks_like_test_description
@@ -151,8 +151,8 @@ class Tryouts
151
151
  meaningful_following = following_tokens.reject { |t| [:blank, :comment].include?(t[:type]) }
152
152
 
153
153
  # Look for test pattern within next 5 tokens (more restrictive)
154
- test_window = meaningful_following.first(5)
155
- has_code = test_window.any? { |t| t[:type] == :code }
154
+ test_window = meaningful_following.first(5)
155
+ has_code = test_window.any? { |t| t[:type] == :code }
156
156
  has_expectation = test_window.any? { |t| is_expectation_type?(t[:type]) }
157
157
 
158
158
  # Only promote to description if BOTH code and expectation are found nearby
@@ -180,11 +180,11 @@ class Tryouts
180
180
  # Skip if it's clearly just a regular comment (short, lowercase, etc.)
181
181
  # Test descriptions are typically longer and more descriptive
182
182
  looks_like_regular_comment = content.length < 20 &&
183
- content.downcase == content &&
184
- !content.match?(/test|example|demonstrate|show/i)
183
+ content.downcase == content &&
184
+ !content.match?(/test|example|demonstrate|show/i)
185
185
 
186
186
  # Check if there's code immediately before this (suggesting it's mid-test)
187
- prev_token = index > 0 ? tokens[index - 1] : nil
187
+ prev_token = index > 0 ? tokens[index - 1] : nil
188
188
  has_code_before = prev_token && prev_token[:type] == :code
189
189
 
190
190
  if looks_like_regular_comment || has_code_before
@@ -199,8 +199,8 @@ class Tryouts
199
199
 
200
200
  # Look for test pattern: at least one code token followed by at least one expectation
201
201
  # within the next 10 meaningful tokens (to avoid matching setup/teardown)
202
- test_window = meaningful_following.first(10)
203
- has_code = test_window.any? { |t| t[:type] == :code }
202
+ test_window = meaningful_following.first(10)
203
+ has_code = test_window.any? { |t| t[:type] == :code }
204
204
  has_expectation = test_window.any? { |t| is_expectation_type?(t[:type]) }
205
205
 
206
206
  if has_code && has_expectation
@@ -466,12 +466,12 @@ class Tryouts
466
466
  TestCase.new(
467
467
  description: desc,
468
468
  code: extract_code_content(code_tokens),
469
- expectations: exp_tokens.map { |token|
469
+ expectations: exp_tokens.map do |token|
470
470
  type = case token[:type]
471
471
  when :exception_expectation then :exception
472
472
  when :intentional_failure_expectation then :intentional_failure
473
- when :true_expectation then :true
474
- when :false_expectation then :false
473
+ when :true_expectation then :true # rubocop:disable Lint/BooleanSymbol
474
+ when :false_expectation then :false # rubocop:disable Lint/BooleanSymbol
475
475
  when :boolean_expectation then :boolean
476
476
  when :result_type_expectation then :result_type
477
477
  when :regex_match_expectation then :regex_match
@@ -486,7 +486,7 @@ class Tryouts
486
486
  else
487
487
  Expectation.new(content: token[:content], type: type)
488
488
  end
489
- },
489
+ end,
490
490
  line_range: start_line..end_line,
491
491
  path: @source_path,
492
492
  source_lines: source_lines,
@@ -89,7 +89,7 @@ class Tryouts
89
89
  :error, # Exception object (if any)
90
90
  :captured_output, # Captured stdout/stderr content
91
91
  :elapsed_time, # Execution timing (future use)
92
- :metadata # Hash for future extensibility
92
+ :metadata, # Hash for future extensibility
93
93
  ) do
94
94
  def passed?
95
95
  status == :passed
@@ -131,7 +131,7 @@ class Tryouts
131
131
  error: nil,
132
132
  captured_output: captured_output,
133
133
  elapsed_time: elapsed_time,
134
- metadata: metadata
134
+ metadata: metadata,
135
135
  )
136
136
  end
137
137
 
@@ -146,7 +146,7 @@ class Tryouts
146
146
  error: nil,
147
147
  captured_output: captured_output,
148
148
  elapsed_time: elapsed_time,
149
- metadata: metadata
149
+ metadata: metadata,
150
150
  )
151
151
  end
152
152
 
@@ -171,7 +171,7 @@ class Tryouts
171
171
  error: error,
172
172
  captured_output: captured_output,
173
173
  elapsed_time: elapsed_time,
174
- metadata: metadata
174
+ metadata: metadata,
175
175
  )
176
176
  end
177
177
  end
@@ -79,7 +79,7 @@ class Tryouts
79
79
  def process_files
80
80
  failure_count = 0
81
81
 
82
- @files.each_with_index do |file, idx|
82
+ @files.each_with_index do |file, _idx|
83
83
  result = process_file(file)
84
84
  failure_count += result unless result.zero?
85
85
  status = result.zero? ? Console.color(:green, 'PASS') : Console.color(:red, 'FAIL')
@@ -1,5 +1,5 @@
1
1
  # lib/tryouts/version.rb
2
2
 
3
3
  class Tryouts
4
- VERSION = '3.1.1'
4
+ VERSION = '3.1.2'
5
5
  end
data/lib/tryouts.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # lib/tryouts.rb
2
2
 
3
-
4
-
5
3
  require 'stringio'
6
4
  require 'timeout'
7
5
 
@@ -20,7 +18,6 @@ class Tryouts
20
18
  @fails = false
21
19
  @container = Class.new
22
20
  @cases = [] # rubocop:disable ThreadSafety/MutableClassInstanceVariable
23
- @sysinfo = nil
24
21
  @testcase_io = StringIO.new
25
22
 
26
23
  module ClassMethods
@@ -28,12 +25,6 @@ class Tryouts
28
25
  attr_writer :debug
29
26
  attr_reader :cases, :testcase_io
30
27
 
31
- def sysinfo
32
- require 'sysinfo'
33
- @sysinfo ||= SysInfo.new
34
- @sysinfo
35
- end
36
-
37
28
  def debug?
38
29
  @debug == true
39
30
  end
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.1.1
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delano Mandelbaum
@@ -37,26 +37,6 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '3.0'
40
- - !ruby/object:Gem::Dependency
41
- name: sysinfo
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '0.8'
47
- - - "<"
48
- - !ruby/object:Gem::Version
49
- version: '1.0'
50
- type: :runtime
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: '0.8'
57
- - - "<"
58
- - !ruby/object:Gem::Version
59
- version: '1.0'
60
40
  description: A simple test framework for Ruby code that uses introspection to allow
61
41
  defining checks in comments.
62
42
  email: gems@solutious.com