gloo-test 1.1 → 1.3

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: 4a73cec30908a847f9a57eff2a51260510ce2c6dae9c7ce3a5c899cb2b687385
4
- data.tar.gz: 3e39c1eeac6b251ed68f81047759a7a505d5eccff6c62b3c156994a8c42b5a8c
3
+ metadata.gz: 4487381d226f57da2c903ba429b55ad0df105b2f33f765ff0d82eaa89d63adf1
4
+ data.tar.gz: d2fa596dd35c471998d3186b1234053c8ee3464cbf596ac07206dcbb3b5a0646
5
5
  SHA512:
6
- metadata.gz: a78397cbeb4554166ec1d210149969121f1ebe133f3d6b7c45811fba1da0c1f3f2c2627a0a12dfa2257b3a6e9b4a85294fd61f42c53b8731cf201e33a29b6e5a
7
- data.tar.gz: b11b5be346c5de429676e3095c675b4ef651fc4ea4688890473fba113bcd1345777175ee95011ef4f930fe5d6054bbe8c751f3987df1e3ce5d347f28d9a83c29
6
+ metadata.gz: e1addf250dd2716c409a1fa723463a325786d98ba3c1ccb03ae1f9d9ee8ad001f7a3752186ab105ac31e499b8e2ea0c4a831db1b72372899cfc15218c572be76
7
+ data.tar.gz: 9dc962225a118a28757d033c60ed1cbc7d7406ff66763b56933019ff64208ac250a245fe796becdefb79cfd5d659583004f2bfdb1a4e0611c49d423f0a48a6fe
data/lib/assert.rb CHANGED
@@ -28,8 +28,7 @@ class Assert < Gloo::Core::Verb
28
28
  begin
29
29
  @engine.context_object.assert_count += 1
30
30
  if @engine.heap.it.is_true?
31
- # Assertion passes
32
- @engine.context_object.passed = true
31
+ # Assertion passes; leave passed alone so an earlier failure stands
33
32
  return true
34
33
  else
35
34
  # Assertion fails
data/lib/refute.rb CHANGED
@@ -29,8 +29,7 @@ class Refute < Gloo::Core::Verb
29
29
  begin
30
30
  @engine.context_object.refute_count += 1
31
31
  if @engine.heap.it.is_false?
32
- # Refutation passes
33
- @engine.context_object.passed = true
32
+ # Refutation passes; leave passed alone so an earlier failure stands
34
33
  return true
35
34
  else
36
35
  # Refutation fails
data/lib/result.rb CHANGED
@@ -4,8 +4,15 @@
4
4
  #
5
5
  class Result
6
6
 
7
- attr_accessor :passed, :assert_count, :refute_count
7
+ EXPECTED_FAIL_MSG = 'expected this test to fail, but no assertion failed'.freeze
8
8
 
9
+ attr_accessor :passed, :assert_count, :refute_count,
10
+ :error_count, :warning_count, :expect_errors
11
+ attr_reader :pn
12
+
13
+ #
14
+ # Set up the result for the given test.
15
+ #
9
16
  def initialize( engine, test )
10
17
  @engine = engine
11
18
  @test = test
@@ -15,10 +22,38 @@ class Result
15
22
  @assert_count = 0
16
23
  @refute_count = 0
17
24
 
25
+ # Errors and warnings logged while the test ran, and whether
26
+ # the test declared that it triggers them on purpose.
27
+ @error_count = 0
28
+ @warning_count = 0
29
+ @expect_errors = false
30
+
18
31
  @passed = true
19
32
  @failure_msg = ''
20
33
  end
21
34
 
35
+ #
36
+ # Did the test log errors or warnings it didn't declare?
37
+ #
38
+ def unexpected_logs?
39
+ return false if @expect_errors
40
+
41
+ return ( @error_count + @warning_count ).positive?
42
+ end
43
+
44
+ #
45
+ # The test was meant to fail: it passes if an assertion failed,
46
+ # and fails if no assertion failed.
47
+ #
48
+ def expect_failure
49
+ if @passed
50
+ @passed = false
51
+ add_message EXPECTED_FAIL_MSG
52
+ else
53
+ @passed = true
54
+ end
55
+ end
56
+
22
57
  #
23
58
  # Show the test result symbol.
24
59
  #
data/lib/results.rb CHANGED
@@ -76,10 +76,13 @@ class Results
76
76
  # Show the results.
77
77
  #
78
78
  def show_results
79
+ theme = @engine.theme
79
80
  delta = duration.round( 2 )
80
81
  puts
81
82
  puts get_result_summary
82
- puts "Tests finished in #{delta} seconds".white
83
+ logged = get_logged_summary
84
+ puts theme.warn( logged ) if logged
85
+ puts theme.emphasis( "Tests finished in #{delta} seconds" )
83
86
  puts
84
87
  end
85
88
 
@@ -88,27 +91,94 @@ class Results
88
91
  #
89
92
  def show_failures
90
93
  if @fail_count > 0
94
+ theme = @engine.theme
91
95
  puts
92
- puts "*** Failures (#{@fail_count}) ***".red
96
+ puts theme.error( "*** Failures (#{@fail_count}) ***" )
93
97
  puts
94
98
  @failures.each do |failure|
95
99
  failure.show_failure
96
100
  end
97
101
  end
98
102
  end
99
-
100
- #
103
+
104
+ #
101
105
  # Get a textual summary of the results.
102
106
  #
103
107
  def get_result_summary
104
- str = "Tests: #{@all_results.length} • Passed: #{@pass_count} • ".white
108
+ theme = @engine.theme
109
+ str = theme.emphasis( "Tests: #{@all_results.length} • Passed: #{@pass_count} • " )
105
110
  if @fail_count > 0
106
- str += " Failed: #{@fail_count} ".red
111
+ str += theme.error( " Failed: #{@fail_count} " )
107
112
  else
108
- str += " Failed: #{@fail_count} ".white
113
+ str += theme.emphasis( " Failed: #{@fail_count} " )
109
114
  end
110
- str += "\n Assertions: #{@assert_count} • Files: #{@file_count}".yellow
115
+ str += theme.accent( "\n Assertions: #{@assert_count} • Files: #{@file_count}" )
111
116
  return str
112
117
  end
113
118
 
119
+ # ---------------------------------------------------------------------
120
+ # Logged Errors and Warnings
121
+ # ---------------------------------------------------------------------
122
+
123
+ #
124
+ # Get a summary of the errors and warnings logged during the run
125
+ # that no test declared (with expect_errors), naming the tests that
126
+ # logged them. Returns nil when there's nothing unexpected.
127
+ # Counts are since the log's counts were last reset (the runner
128
+ # resets them just before running the tests).
129
+ #
130
+ def get_logged_summary
131
+ unexpected = @all_results.select( &:unexpected_logs? )
132
+ outside_errors, outside_warnings = logged_outside_tests
133
+
134
+ errors = unexpected.sum( &:error_count ) + outside_errors
135
+ warnings = unexpected.sum( &:warning_count ) + outside_warnings
136
+ return nil if ( errors + warnings ).zero?
137
+
138
+ lines = [ " #{count_phrase( errors, warnings )} logged during the run; see #{log_path}" ]
139
+ unexpected.each do |r|
140
+ lines << " #{r.pn} (#{count_phrase( r.error_count, r.warning_count )})"
141
+ end
142
+ if ( outside_errors + outside_warnings ).positive?
143
+ lines << " (outside tests: #{count_phrase( outside_errors, outside_warnings )})"
144
+ end
145
+ return lines.join( "\n" )
146
+ end
147
+
148
+ #
149
+ # Get the errors and warnings logged outside any test (eg. while
150
+ # loading a test file): everything logged less what the tests logged.
151
+ #
152
+ def logged_outside_tests
153
+ log = @engine.log
154
+ errors = log.error_count - @all_results.sum( &:error_count )
155
+ warnings = log.warning_count - @all_results.sum( &:warning_count )
156
+ return [ errors, warnings ]
157
+ end
158
+
159
+ #
160
+ # Describe a count of errors and warnings, eg. "1 error",
161
+ # "2 warnings", or "2 errors and 1 warning". Zero counts are left out.
162
+ #
163
+ def count_phrase( errors, warnings )
164
+ parts = []
165
+ parts << pluralize( errors, 'error' ) if errors.positive?
166
+ parts << pluralize( warnings, 'warning' ) if warnings.positive?
167
+ return parts.join( ' and ' )
168
+ end
169
+
170
+ #
171
+ # A count with its noun, plural unless the count is one.
172
+ #
173
+ def pluralize( count, noun )
174
+ return count == 1 ? "1 #{noun}" : "#{count} #{noun}s"
175
+ end
176
+
177
+ #
178
+ # The error log's path, with the home folder shown as ~.
179
+ #
180
+ def log_path
181
+ return @engine.log.err_file.sub( /\A#{Regexp.escape( Dir.home )}/, '~' )
182
+ end
183
+
114
184
  end
data/lib/test.rb CHANGED
@@ -6,6 +6,8 @@ class Test < Gloo::Core::Obj
6
6
  KEYWORD = 'test'.freeze
7
7
  TEST_DESC = 'description'.freeze
8
8
  ON_TEST_EVENT = 'on_test'.freeze
9
+ EXPECT_ERRORS = 'expect_errors'.freeze
10
+ EXPECT_FAIL = 'expect_fail'.freeze
9
11
 
10
12
 
11
13
  #
@@ -31,6 +33,30 @@ class Test < Gloo::Core::Obj
31
33
  return o ? o.value : 'Unknown'
32
34
  end
33
35
 
36
+ #
37
+ # Does the test trigger errors or warnings on purpose?
38
+ # Set with an optional expect_errors [bool] child.
39
+ #
40
+ def expect_errors?
41
+ return flag_set?( EXPECT_ERRORS )
42
+ end
43
+
44
+ #
45
+ # Is the test meant to fail?
46
+ # Set with an optional expect_fail [bool] child.
47
+ #
48
+ def expect_fail?
49
+ return flag_set?( EXPECT_FAIL )
50
+ end
51
+
52
+ #
53
+ # Is the named bool child present and true?
54
+ #
55
+ def flag_set?( name )
56
+ o = find_child name
57
+ return o ? o.value == true : false
58
+ end
59
+
34
60
 
35
61
  # ---------------------------------------------------------------------
36
62
  # Children
@@ -69,10 +95,19 @@ class Test < Gloo::Core::Obj
69
95
  #
70
96
  def run_test
71
97
  result = Result.new( @engine, self )
98
+ errors_before = @engine.log.error_count
99
+ warnings_before = @engine.log.warning_count
100
+
72
101
  @engine.context_object = result
73
102
  run_on_test
74
103
  @engine.context_object = nil
75
104
 
105
+ # Record what this test logged, for the run's summary.
106
+ result.error_count = @engine.log.error_count - errors_before
107
+ result.warning_count = @engine.log.warning_count - warnings_before
108
+ result.expect_errors = expect_errors?
109
+ result.expect_failure if expect_fail?
110
+
76
111
  result.show_result_symbol
77
112
 
78
113
  return result
@@ -102,7 +137,9 @@ class Test < Gloo::Core::Obj
102
137
  :description => 'A single gloo test.',
103
138
  :children => [
104
139
  'description (string) — A textual description of the test and desired outcome, used in output if there is an error.',
105
- 'on_test (script) — The script to run when the test is executed. Note that the normal way to run tests is with gloo --test.'
140
+ 'on_test (script) — The script to run when the test is executed. Note that the normal way to run tests is with gloo --test.',
141
+ 'expect_errors (bool) — Optional. Set to true for a test that triggers errors or warnings on purpose (eg. to check on_error); they are left out of the summary of what was logged during the run.',
142
+ 'expect_fail (bool) — Optional. Set to true for a test that is meant to fail: it passes if at least one assertion fails, and fails if none does. It can\'t tell which assertion failed, or why, so keep such a test to the one thing it checks.'
106
143
  ],
107
144
  :examples => <<~EXAMPLES.strip
108
145
  #
data/lib/test_files.rb CHANGED
@@ -45,8 +45,7 @@ class TestFiles
45
45
  elsif File.exist?( f )
46
46
  add( f )
47
47
  else
48
- # TODO: Show error
49
- puts "Test file does not exist: #{f}"
48
+ @engine.err Gloo::Core::NotFound.file( f )
50
49
  end
51
50
  end
52
51
  end
data/lib/test_runner.rb CHANGED
@@ -20,6 +20,9 @@ class TestRunner
20
20
  # Execute all tests and display results.
21
21
  #
22
22
  def run
23
+ # Count only what's logged from here on, not loading gloo-test.
24
+ # Before setup, so a missing test file is counted.
25
+ @engine.log.reset_counts
23
26
  setup
24
27
 
25
28
  @results.start_timer
@@ -37,7 +40,7 @@ class TestRunner
37
40
  def setup
38
41
  @engine.log.debug "TestRunner is running…"
39
42
  puts
40
- puts "Gloo Test Runner".white
43
+ puts @engine.theme.emphasis( "Gloo Test Runner" )
41
44
  puts
42
45
 
43
46
  # Get a list of test files and randomize
metadata CHANGED
@@ -1,14 +1,82 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gloo-test
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.1'
4
+ version: '1.3'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Crane
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: gloo
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: bundler
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: minitest
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '5.1'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 5.14.2
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '5.1'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 5.14.2
60
+ - !ruby/object:Gem::Dependency
61
+ name: rake
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '13.0'
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 13.0.1
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '13.0'
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 13.0.1
12
80
  description: Adds Gloo Unit Test support to Gloo.
13
81
  email:
14
82
  - eric.crane@mac.com