tet 1.5.1 → 2.0.0
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/lib/tests.rb +54 -30
- data/lib/tet.rb +106 -261
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9c5b7e8d1240ae647425b19d13b5307bedf74a5
|
4
|
+
data.tar.gz: 930d474cc6a5f09b57bc590a5d8ef97a00c7622d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d6f765630b953aa0d691d4aa09d02297e4460eb48bd71d4841b1ca7393a39bb88429541bae25494798b69fc26cd10b0aab7c578fa527edc092dc5db67ce8746
|
7
|
+
data.tar.gz: d5ccdc37e41471a2ad0cf5d2cf6c4e029db2bae7f1db7d8b8346091b797fe90143a601d74adce29e56465cc241fda87393d47a03f0ef465450d7c5636dd5f785
|
data/lib/tests.rb
CHANGED
@@ -7,45 +7,69 @@
|
|
7
7
|
|
8
8
|
require_relative './tet'
|
9
9
|
|
10
|
-
|
11
|
-
class IntendedErrorChild < IntendedError; end
|
10
|
+
SHOW_EXPECTED = false
|
12
11
|
|
13
|
-
|
12
|
+
def prefix string
|
13
|
+
if SHOW_EXPECTED
|
14
|
+
TetCore.break_after_print
|
15
|
+
print string
|
16
|
+
end
|
17
|
+
end
|
14
18
|
|
15
|
-
|
16
|
-
|
19
|
+
def pass; prefix 'PASS = '; end
|
20
|
+
def fail; prefix 'FAIL = '; end
|
21
|
+
def err; prefix 'ERROR = '; end
|
17
22
|
|
18
|
-
|
23
|
+
def test_between
|
24
|
+
assert('Intentional failure') { false }
|
25
|
+
yield
|
26
|
+
assert('') { true }
|
27
|
+
yield
|
28
|
+
assert('Intentional failure') { false }
|
29
|
+
end
|
19
30
|
|
20
|
-
|
21
|
-
assert('first failure') { false }
|
22
|
-
assert('second failure') { false }
|
31
|
+
class IntendedError < StandardError; end
|
23
32
|
|
24
|
-
|
25
|
-
|
33
|
+
group('#assert') do
|
34
|
+
pass; assert('True assertions pass') { true }
|
35
|
+
fail; assert('False assertions fail') { false }
|
36
|
+
err; assert('Errors are caught') { raise IntendedError.new('error message') }
|
26
37
|
|
27
|
-
|
28
|
-
assert(
|
29
|
-
assert(
|
30
|
-
assert(
|
31
|
-
assert(true) { false }
|
32
|
-
assert({x: 1, y: 2}) { false }
|
33
|
-
assert(nil) { false }
|
38
|
+
puts 'Multiple passes in a row show on one line:'
|
39
|
+
assert('') { true }
|
40
|
+
assert('') { true }
|
41
|
+
assert('') { true }
|
34
42
|
end
|
35
43
|
|
36
|
-
group
|
37
|
-
|
38
|
-
|
44
|
+
group('#group') do
|
45
|
+
group('Can nest') do
|
46
|
+
fail; assert('Intentional failure') { false }
|
47
|
+
end
|
39
48
|
|
40
|
-
|
41
|
-
|
49
|
+
group('Can have classes as names') do
|
50
|
+
group(String) do
|
51
|
+
fail; assert('Intentional failure') { false }
|
52
|
+
end
|
53
|
+
end
|
42
54
|
end
|
43
55
|
|
44
|
-
group
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
err('
|
49
|
-
|
50
|
-
|
56
|
+
group('#error') do
|
57
|
+
fail; error('True errors fail', expect: StandardError) { true }
|
58
|
+
fail; error('False errors fail', expect: StandardError) { false }
|
59
|
+
|
60
|
+
err; error('Unexpected errors err', expect: NoMethodError) do
|
61
|
+
raise IntendedError.new('should expect different error')
|
62
|
+
end
|
63
|
+
|
64
|
+
pass; error('Expected errors pass', expect: IntendedError) do
|
65
|
+
raise IntendedError.new('SHOULD NOT BE SEEN')
|
66
|
+
end
|
51
67
|
end
|
68
|
+
|
69
|
+
puts
|
70
|
+
puts "Testing #puts between different results:"
|
71
|
+
test_between { puts 'Test of #puts' }
|
72
|
+
|
73
|
+
puts
|
74
|
+
puts "Testing #p between different results:"
|
75
|
+
test_between { p 'Test of #p' }
|
data/lib/tet.rb
CHANGED
@@ -5,299 +5,144 @@
|
|
5
5
|
# terms of the three-clause BSD license. See LICENSE.txt
|
6
6
|
# (located in root directory of this project) for details.
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
test: block,
|
21
|
-
no_nest: true,
|
22
|
-
truthy: -> { Tet.passed },
|
23
|
-
falsy: -> { Tet.failed }
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Assert that a block will err.
|
28
|
-
def err label = '', expect: StandardError, &block
|
29
|
-
Tet.run(
|
30
|
-
label: label,
|
31
|
-
test: block,
|
32
|
-
no_nest: true,
|
33
|
-
truthy: -> { Tet.failed },
|
34
|
-
falsy: -> { Tet.failed },
|
35
|
-
error: ->(caught) do
|
36
|
-
(expect >= caught.class) ? Tet.passed : Tet.erred(caught, expect)
|
37
|
-
end
|
38
|
-
)
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
# A namespace for all of the helper methods and classes.
|
44
|
-
module Tet
|
45
|
-
# Print all the reports after all the tests have run.
|
8
|
+
module TetCore
|
9
|
+
INDENT_DEPTH = 4
|
10
|
+
SEPERATOR = ' | '
|
11
|
+
FAIL_HEADER = 'FAIL: '
|
12
|
+
ERROR_HEADER = 'ERROR: '
|
13
|
+
|
14
|
+
@prev_printed = false
|
15
|
+
@messages = []
|
16
|
+
@counts = Struct.new(:tests, :fails, :errors)
|
17
|
+
.new(0, 0, 0)
|
18
|
+
|
19
|
+
# Output totals at the end of the test run.
|
46
20
|
at_exit do
|
47
|
-
puts
|
48
|
-
puts_report 'Failures', failure_report
|
49
|
-
puts_report 'Exceptions', error_report
|
50
|
-
puts_report 'Statistics', statistics_report
|
21
|
+
puts "\nTests: #{@counts.tests} Fails: #{@counts.fails} Errors: #{@counts.errors}"
|
51
22
|
end
|
52
23
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# Object oriented ways to do string formatting.
|
61
|
-
module StringFormatting
|
62
|
-
refine String do
|
63
|
-
def indent
|
64
|
-
gsub(/^/, ' ')
|
65
|
-
end
|
66
|
-
|
67
|
-
def to_label_string
|
68
|
-
self
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
refine Module do
|
73
|
-
def to_label_string
|
74
|
-
name
|
75
|
-
end
|
24
|
+
class << self
|
25
|
+
# Record an assertion.
|
26
|
+
def assert
|
27
|
+
@counts.tests += 1
|
76
28
|
end
|
77
29
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
30
|
+
# Record a passing assertion.
|
31
|
+
def pass
|
32
|
+
checked_print ?.
|
82
33
|
end
|
83
|
-
end
|
84
|
-
|
85
|
-
using StringFormatting
|
86
34
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# Call when an assertion has passed.
|
92
|
-
def passed
|
93
|
-
print_now ?.
|
94
|
-
Data.add_note(:pass)
|
35
|
+
# Record a failing assertion.
|
36
|
+
def fail
|
37
|
+
@counts.fails += 1
|
38
|
+
puts_failure_data(header: FAIL_HEADER)
|
95
39
|
end
|
96
40
|
|
97
|
-
#
|
98
|
-
def
|
99
|
-
|
100
|
-
|
41
|
+
# Run a block under a certain name, catching and printing errors.
|
42
|
+
def group name
|
43
|
+
@messages << name
|
44
|
+
yield
|
45
|
+
rescue StandardError => caught
|
46
|
+
@counts.errors += 1
|
47
|
+
puts_failure_data(
|
48
|
+
header: ERROR_HEADER,
|
49
|
+
additional_info: error_to_info_array(caught)
|
50
|
+
)
|
51
|
+
ensure
|
52
|
+
@messages.pop
|
101
53
|
end
|
102
54
|
|
103
|
-
#
|
104
|
-
def
|
105
|
-
|
106
|
-
Data.add_note(:error, caught: caught, expected: expected)
|
55
|
+
# Add a line break if the last output was a #print instead of a #puts.
|
56
|
+
def break_after_print
|
57
|
+
checked_puts if @prev_printed
|
107
58
|
end
|
108
59
|
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
no_nest: false,
|
115
|
-
test:
|
116
|
-
|
117
|
-
Data.with_label(label) do
|
118
|
-
nesting_guard(no_nest) do
|
119
|
-
begin
|
120
|
-
test.call ? truthy.call : falsy.call
|
121
|
-
rescue TestError => caught
|
122
|
-
erred(caught)
|
123
|
-
rescue StandardError => caught
|
124
|
-
error.call(caught)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
nil
|
130
|
-
end
|
60
|
+
# Alias original #puts and #p methods.
|
61
|
+
alias_method :real_puts, :puts
|
62
|
+
alias_method :real_p, :p
|
63
|
+
public :real_puts
|
64
|
+
public :real_p
|
131
65
|
|
132
|
-
|
66
|
+
private
|
133
67
|
|
134
|
-
#
|
135
|
-
def
|
136
|
-
|
137
|
-
|
138
|
-
end
|
68
|
+
# Output data related to a failure.
|
69
|
+
def puts_failure_data header:, additional_info: []
|
70
|
+
break_after_print
|
71
|
+
checked_puts header + @messages.join(SEPERATOR)
|
139
72
|
|
140
|
-
|
141
|
-
|
142
|
-
unless content.empty?
|
143
|
-
puts
|
144
|
-
puts "#{header}:"
|
145
|
-
puts content.indent
|
73
|
+
additional_info.each.with_index do |text, index|
|
74
|
+
checked_puts indent(text, index + 1)
|
146
75
|
end
|
147
76
|
end
|
148
77
|
|
149
|
-
#
|
150
|
-
def
|
151
|
-
|
152
|
-
|
153
|
-
error_count = Data.count_type(:error)
|
154
|
-
|
155
|
-
output = []
|
156
|
-
output << "Errors: #{error_count}" unless error_count.zero?
|
157
|
-
output << "Failed: #{fail_count}" unless fail_count.zero?
|
158
|
-
output << "Passed: #{pass_count}" unless pass_count.zero?
|
159
|
-
|
160
|
-
output.join(?\n)
|
78
|
+
# Perform a #puts and then set a flag for future line breaks.
|
79
|
+
def checked_puts object = ''
|
80
|
+
real_puts object
|
81
|
+
@prev_printed = false
|
161
82
|
end
|
162
83
|
|
163
|
-
#
|
164
|
-
def
|
165
|
-
|
166
|
-
|
167
|
-
Data.select_type(:fail, :error)
|
168
|
-
.map do |node|
|
169
|
-
node.label
|
170
|
-
.tap do |label|
|
171
|
-
if node.type == :error
|
172
|
-
error_note = "EXCEPTION_#{1 + errors.index(node)}"
|
173
|
-
expected = node.data[:expected]
|
174
|
-
error_note << " (expected: #{expected}" if expected
|
175
|
-
|
176
|
-
label << error_note
|
177
|
-
end
|
178
|
-
end
|
179
|
-
.map(&:to_label_string)
|
180
|
-
.join(' :: ')
|
181
|
-
end
|
182
|
-
.join(?\n)
|
84
|
+
# Perform a #print and then set a flag for future line breaks.
|
85
|
+
def checked_print object = ''
|
86
|
+
print object
|
87
|
+
@prev_printed = true
|
183
88
|
end
|
184
89
|
|
185
|
-
#
|
186
|
-
def
|
187
|
-
|
188
|
-
|
189
|
-
error = node.data[:caught]
|
190
|
-
message = error.to_s
|
191
|
-
message << " (#{error.class})" if message != error.class.to_s
|
192
|
-
summary = "#{index + 1}. #{message}"
|
193
|
-
|
194
|
-
error.backtrace
|
195
|
-
.reject { |line| line.start_with?(__FILE__) }
|
196
|
-
.map { |line| line.indent }
|
197
|
-
.unshift(summary)
|
198
|
-
.join(?\n)
|
199
|
-
end
|
200
|
-
.join("\n\n")
|
90
|
+
# Indent each line of a given string by a given amount.
|
91
|
+
def indent string, amount
|
92
|
+
indent_string = ' ' * amount * INDENT_DEPTH
|
93
|
+
string.gsub(/^/, indent_string)
|
201
94
|
end
|
202
95
|
|
203
|
-
#
|
204
|
-
def
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
96
|
+
# Convert an error object into an array of strings describing the error.
|
97
|
+
def error_to_info_array error
|
98
|
+
[
|
99
|
+
"#{error.class}: #{error.message}",
|
100
|
+
error.backtrace
|
101
|
+
.reject { |path| path.match?(/^#{__FILE__}:/) }
|
102
|
+
.join(?\n)
|
103
|
+
]
|
210
104
|
end
|
211
105
|
end
|
106
|
+
end
|
212
107
|
|
108
|
+
# Group together assertions and groups under a given name.
|
109
|
+
def group name
|
110
|
+
TetCore.group(name) { yield }
|
111
|
+
end
|
213
112
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
include Enumerable
|
219
|
-
|
220
|
-
# Create and append a new node to this node, returning the new node.
|
221
|
-
def append_node type, data
|
222
|
-
Node.new(type: type, data: data, parent: self)
|
223
|
-
.tap { |node| @children << node }
|
224
|
-
end
|
225
|
-
|
226
|
-
# Recursively iterate over each node in the test data tree in the order
|
227
|
-
# that they were added.
|
228
|
-
def each &block
|
229
|
-
@children.each do |node|
|
230
|
-
block.call(node)
|
231
|
-
node.each(&block)
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
# The root of the tree with methods to terminate Node methods which search
|
237
|
-
# up the tree, as well as methods for enumerating over the test data, adding
|
238
|
-
# labels and adding nodes.
|
239
|
-
class Root
|
240
|
-
include Basics
|
241
|
-
|
242
|
-
def initialize
|
243
|
-
@children = []
|
244
|
-
@current_node = self
|
245
|
-
end
|
246
|
-
|
247
|
-
# Terminate Node#label.
|
248
|
-
def label
|
249
|
-
[]
|
250
|
-
end
|
251
|
-
|
252
|
-
# Run a block where any notes added will be inside a new label node.
|
253
|
-
def with_label label
|
254
|
-
previous = @current_node
|
255
|
-
@current_node = add_note(:label, label)
|
256
|
-
yield
|
257
|
-
ensure
|
258
|
-
@current_node = previous
|
259
|
-
self
|
260
|
-
end
|
261
|
-
|
262
|
-
# Add a node to note some data within the node that is currently active.
|
263
|
-
def add_note type, data = nil
|
264
|
-
@current_node.append_node(type, data)
|
265
|
-
end
|
266
|
-
|
267
|
-
# Get an array of all nodes of some type in the order they were added.
|
268
|
-
def select_type *types
|
269
|
-
select { |node| types.include?(node.type) }
|
270
|
-
end
|
271
|
-
|
272
|
-
# Count the number of nodes of a given type.
|
273
|
-
def count_type type
|
274
|
-
select_type(type).size
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
# A node to store data about that some point in the test tree
|
279
|
-
class Node
|
280
|
-
include Basics
|
281
|
-
attr_reader :data, :type
|
113
|
+
# Assert that a given block will return true.
|
114
|
+
def assert name
|
115
|
+
TetCore.group(name) do
|
116
|
+
TetCore.assert
|
282
117
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
@parent = parent
|
287
|
-
@children = []
|
288
|
-
end
|
118
|
+
yield ? TetCore.pass : TetCore.fail
|
119
|
+
end
|
120
|
+
end
|
289
121
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
122
|
+
# Assert that a given block will raise an expected error.
|
123
|
+
def error name, expect:
|
124
|
+
TetCore.group(name) do
|
125
|
+
begin
|
126
|
+
TetCore.assert
|
127
|
+
yield
|
128
|
+
rescue expect
|
129
|
+
TetCore.pass
|
130
|
+
else
|
131
|
+
TetCore.fail
|
298
132
|
end
|
299
133
|
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# A redefined version of #puts which ensures a line break before the printed
|
137
|
+
# object (for easier debugging).
|
138
|
+
def puts object = ''
|
139
|
+
TetCore.break_after_print
|
140
|
+
TetCore.real_puts(object)
|
141
|
+
end
|
300
142
|
|
301
|
-
|
302
|
-
|
143
|
+
# A redefined version of #p which ensures a line break before the printed
|
144
|
+
# object (for easier debugging).
|
145
|
+
def p object
|
146
|
+
TetCore.break_after_print
|
147
|
+
TetCore.real_p(object)
|
303
148
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Colin Fulton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03
|
11
|
+
date: 2017-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A very minimal test framework designed for simple projects. A couple
|
14
14
|
of features, relatively nice looking output, and nothing else. Does the world need
|
@@ -32,7 +32,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
32
32
|
requirements:
|
33
33
|
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 2.
|
35
|
+
version: 2.4.0
|
36
36
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|