tet 1.5.0 → 1.5.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/lib/tests.rb +1 -1
- data/lib/tet.rb +151 -133
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71c11439cad3f5c481d5242bc65ade2c8780804f
|
4
|
+
data.tar.gz: 6a410a5f775aa07096ed3b56e06cf85baddbdb33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bcdfe86d7625c0a0a259a75f61b76165f0bb5dcb20400edaa950207553eaa451af2a219f5b7075c56caabdd46abf0fc573d006e2a3682b70fad43d41027bc2f
|
7
|
+
data.tar.gz: b24180e3e816c9e165d857547072f73e5f4d2a0cbe6d9f5a010e4017a9bf1a95392374228110d45b05241442e3793ebe12bbb9a7a3e8625dd9020c076f17e624
|
data/lib/tests.rb
CHANGED
@@ -37,7 +37,7 @@ group '#err' do
|
|
37
37
|
err('errors pass') { raise IntendedError }
|
38
38
|
err('non-errors fail') { true }
|
39
39
|
|
40
|
-
err('correct errors pass',
|
40
|
+
err('correct errors pass', expect: IntendedError) { raise IntendedError }
|
41
41
|
err('incorrect errors err', expect: IntendedErrorChild) { raise IntendedError }
|
42
42
|
end
|
43
43
|
|
data/lib/tet.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
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
|
-
# Label a block of tests
|
8
|
+
# Label a block of tests.
|
9
9
|
def group label, &block
|
10
10
|
Tet.run(
|
11
11
|
label: label,
|
@@ -13,7 +13,7 @@ def group label, &block
|
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
16
|
-
# Assert that a block will return a truthy value
|
16
|
+
# Assert that a block will return a truthy value.
|
17
17
|
def assert label = '', &block
|
18
18
|
Tet.run(
|
19
19
|
label: label,
|
@@ -24,7 +24,7 @@ def assert label = '', &block
|
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
27
|
-
# Assert that a block will err
|
27
|
+
# Assert that a block will err.
|
28
28
|
def err label = '', expect: StandardError, &block
|
29
29
|
Tet.run(
|
30
30
|
label: label,
|
@@ -32,9 +32,9 @@ def err label = '', expect: StandardError, &block
|
|
32
32
|
no_nest: true,
|
33
33
|
truthy: -> { Tet.failed },
|
34
34
|
falsy: -> { Tet.failed },
|
35
|
-
error: ->(caught)
|
35
|
+
error: ->(caught) do
|
36
36
|
(expect >= caught.class) ? Tet.passed : Tet.erred(caught, expect)
|
37
|
-
|
37
|
+
end
|
38
38
|
)
|
39
39
|
end
|
40
40
|
|
@@ -42,41 +42,41 @@ end
|
|
42
42
|
|
43
43
|
# A namespace for all of the helper methods and classes.
|
44
44
|
module Tet
|
45
|
-
# Print all the reports after all the tests have run
|
45
|
+
# Print all the reports after all the tests have run.
|
46
46
|
at_exit do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
puts_report 'Statistics', Stats.report
|
52
|
-
end
|
47
|
+
puts
|
48
|
+
puts_report 'Failures', failure_report
|
49
|
+
puts_report 'Exceptions', error_report
|
50
|
+
puts_report 'Statistics', statistics_report
|
53
51
|
end
|
54
52
|
|
55
53
|
|
56
54
|
|
57
|
-
# An exception class to distinguish errors from incorrectly written tests
|
55
|
+
# An exception class to distinguish errors from incorrectly written tests.
|
58
56
|
class TestError < StandardError; end
|
59
57
|
|
60
|
-
|
58
|
+
|
59
|
+
|
60
|
+
# Object oriented ways to do string formatting.
|
61
61
|
module StringFormatting
|
62
62
|
refine String do
|
63
63
|
def indent
|
64
64
|
gsub(/^/, ' ')
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
67
|
+
def to_label_string
|
68
68
|
self
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
72
|
refine Module do
|
73
|
-
def
|
73
|
+
def to_label_string
|
74
74
|
name
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
78
|
refine Object do
|
79
|
-
def
|
79
|
+
def to_label_string
|
80
80
|
inspect
|
81
81
|
end
|
82
82
|
end
|
@@ -86,26 +86,27 @@ module Tet
|
|
86
86
|
|
87
87
|
|
88
88
|
|
89
|
-
# Helpers for building test methods
|
89
|
+
# Helpers for building test methods.
|
90
90
|
class << self
|
91
|
-
# Call when an assertion has passed
|
91
|
+
# Call when an assertion has passed.
|
92
92
|
def passed
|
93
|
-
|
93
|
+
print_now ?.
|
94
|
+
Data.add_note(:pass)
|
94
95
|
end
|
95
96
|
|
96
|
-
# Call when an assertion has failed
|
97
|
+
# Call when an assertion has failed.
|
97
98
|
def failed
|
98
|
-
|
99
|
-
|
99
|
+
print_now ?!
|
100
|
+
Data.add_note(:fail)
|
100
101
|
end
|
101
102
|
|
102
|
-
# Call when an assertion has erred
|
103
|
+
# Call when an assertion has erred.
|
103
104
|
def erred caught, expected = nil
|
104
|
-
|
105
|
-
|
105
|
+
print_now ??
|
106
|
+
Data.add_note(:error, caught: caught, expected: expected)
|
106
107
|
end
|
107
108
|
|
108
|
-
# Run a block as a test
|
109
|
+
# Run a block as a test.
|
109
110
|
def run label:,
|
110
111
|
truthy: -> { },
|
111
112
|
falsy: -> { },
|
@@ -113,7 +114,7 @@ module Tet
|
|
113
114
|
no_nest: false,
|
114
115
|
test:
|
115
116
|
|
116
|
-
|
117
|
+
Data.with_label(label) do
|
117
118
|
nesting_guard(no_nest) do
|
118
119
|
begin
|
119
120
|
test.call ? truthy.call : falsy.call
|
@@ -128,9 +129,15 @@ module Tet
|
|
128
129
|
nil
|
129
130
|
end
|
130
131
|
|
131
|
-
|
132
|
+
private
|
132
133
|
|
133
|
-
# Print out a
|
134
|
+
# Print out a string immediately. Calling #print alone may have a delay.
|
135
|
+
def print_now string
|
136
|
+
print string
|
137
|
+
$stdout.flush
|
138
|
+
end
|
139
|
+
|
140
|
+
# Print out a report to stdout.
|
134
141
|
def puts_report header, content
|
135
142
|
unless content.empty?
|
136
143
|
puts
|
@@ -139,6 +146,60 @@ module Tet
|
|
139
146
|
end
|
140
147
|
end
|
141
148
|
|
149
|
+
# Render a string with details about all of the test run.
|
150
|
+
def statistics_report
|
151
|
+
pass_count = Data.count_type(:pass)
|
152
|
+
fail_count = Data.count_type(:fail)
|
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)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Render a string with details about all of the failures encountered.
|
164
|
+
def failure_report
|
165
|
+
errors = Data.select_type(:error)
|
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)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Render a string with details about all of the errors encountered.
|
186
|
+
def error_report
|
187
|
+
Data.select_type(:error)
|
188
|
+
.map.with_index do |node, index|
|
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")
|
201
|
+
end
|
202
|
+
|
142
203
|
# Check and set a flag to prevent test blocks from nesting
|
143
204
|
def nesting_guard guard_state
|
144
205
|
raise TestError, 'assertions can not be nested' if @nesting_banned
|
@@ -150,136 +211,93 @@ module Tet
|
|
150
211
|
end
|
151
212
|
|
152
213
|
|
214
|
+
# Because tests are represented as series of nested groups containing
|
215
|
+
# assertions, the test data is stored in a tree.
|
216
|
+
module Tree
|
217
|
+
module Basics
|
218
|
+
include Enumerable
|
153
219
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
class << self
|
160
|
-
# Call when an assertion has passed
|
161
|
-
def passed
|
162
|
-
log :passed
|
163
|
-
end
|
164
|
-
|
165
|
-
# Call when an assertion has failed
|
166
|
-
def failed
|
167
|
-
log :failed
|
168
|
-
end
|
169
|
-
|
170
|
-
# Call when an assertion has erred
|
171
|
-
def erred
|
172
|
-
log :erred
|
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 }
|
173
224
|
end
|
174
225
|
|
175
|
-
#
|
176
|
-
|
177
|
-
|
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
|
178
233
|
end
|
234
|
+
end
|
179
235
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
output = []
|
187
|
-
output << "Errors: #{errors}" unless errors.zero?
|
188
|
-
output << "Failed: #{fails}"
|
189
|
-
output << "Passed: #{passes}"
|
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
|
190
241
|
|
191
|
-
|
242
|
+
def initialize
|
243
|
+
@children = []
|
244
|
+
@current_node = self
|
192
245
|
end
|
193
246
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
def log type
|
198
|
-
Counts[type] += 1
|
199
|
-
|
200
|
-
print Marks[type]
|
201
|
-
$stdout.flush
|
247
|
+
# Terminate Node#label.
|
248
|
+
def label
|
249
|
+
[]
|
202
250
|
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
|
207
|
-
# Tracks and reports messages for each test
|
208
|
-
module Messages
|
209
|
-
Labels = []
|
210
|
-
Results = []
|
211
|
-
Errors = []
|
212
251
|
|
213
|
-
|
214
|
-
# Add a label to all subsequent messages
|
252
|
+
# Run a block where any notes added will be inside a new label node.
|
215
253
|
def with_label label
|
216
|
-
|
254
|
+
previous = @current_node
|
255
|
+
@current_node = add_note(:label, label)
|
217
256
|
yield
|
218
257
|
ensure
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
# Call when an assertion has failed
|
223
|
-
def failed
|
224
|
-
add_result!
|
258
|
+
@current_node = previous
|
259
|
+
self
|
225
260
|
end
|
226
261
|
|
227
|
-
#
|
228
|
-
def
|
229
|
-
|
230
|
-
label = "EXCEPTION_#{number}"
|
231
|
-
label << " (expected: #{expected})" if expected
|
232
|
-
|
233
|
-
with_label(label) { add_result! }
|
234
|
-
|
235
|
-
Errors.push(error_message(caught, number))
|
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)
|
236
265
|
end
|
237
266
|
|
238
|
-
#
|
239
|
-
def
|
240
|
-
|
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) }
|
241
270
|
end
|
242
271
|
|
243
|
-
#
|
244
|
-
def
|
245
|
-
|
272
|
+
# Count the number of nodes of a given type.
|
273
|
+
def count_type type
|
274
|
+
select_type(type).size
|
246
275
|
end
|
276
|
+
end
|
247
277
|
|
248
|
-
|
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
|
249
282
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
.join(' :: ')
|
256
|
-
)
|
283
|
+
def initialize parent:, type:, data: nil
|
284
|
+
@type = type
|
285
|
+
@data = data
|
286
|
+
@parent = parent
|
287
|
+
@children = []
|
257
288
|
end
|
258
289
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
label
|
263
|
-
when String
|
264
|
-
label.to_s
|
290
|
+
# Generate the array of labels that identify this point in the tree.
|
291
|
+
def label
|
292
|
+
if @type == :label
|
293
|
+
@parent.label + [@data]
|
265
294
|
else
|
266
|
-
label
|
295
|
+
@parent.label
|
267
296
|
end
|
268
297
|
end
|
269
|
-
|
270
|
-
# Format an error into a message string
|
271
|
-
def error_message error, number
|
272
|
-
error_message = error.to_s
|
273
|
-
error_class = error.class.to_s
|
274
|
-
error_message << " (#{error.class})" if error_message != error_class
|
275
|
-
|
276
|
-
summary = "#{number}. #{error_message}"
|
277
|
-
details = error.backtrace
|
278
|
-
.reject { |line| line.start_with?(__FILE__) }
|
279
|
-
.map { |line| line.indent }
|
280
|
-
|
281
|
-
details.unshift(summary).join(?\n)
|
282
|
-
end
|
283
298
|
end
|
284
299
|
end
|
300
|
+
|
301
|
+
# The instance of the Tree data structure that stores all of the test results.
|
302
|
+
Data = Tree::Root.new
|
285
303
|
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: 1.5.
|
4
|
+
version: 1.5.1
|
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-03-10 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
|