tst 0.0.2 → 0.0.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.
- data/README.md +3 -3
- data/lib/tst.rb +45 -171
- data/lib/tst/reporters/plain.rb +3 -5
- data/test/plain_reporter.rb +31 -19
- data/test/test.rb +3 -21
- data/test/test2.rb +5 -0
- metadata +4 -2
data/README.md
CHANGED
@@ -184,7 +184,7 @@ Just looking in the 'lib' directories:
|
|
184
184
|
- test/unit: 6313
|
185
185
|
- rspec: 5460
|
186
186
|
- minitest: 1210
|
187
|
-
- tst:
|
187
|
+
- tst: 190
|
188
188
|
|
189
|
-
The core of tst's testing engine is really just
|
190
|
-
other
|
189
|
+
The core of tst's testing engine is really just 91 lines (see 'tst.rb'). The
|
190
|
+
other 99 is IO/reporting code.
|
data/lib/tst.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
require 'tst/reporters'
|
2
2
|
|
3
|
-
# Tst
|
4
3
|
module Tst
|
5
|
-
VERSION = "0.0.
|
4
|
+
VERSION = "0.0.3"
|
6
5
|
|
7
|
-
# ### Failure ###
|
8
|
-
#
|
9
6
|
# An error class that carries data about test failures.
|
10
7
|
class Failure < StandardError
|
11
8
|
attr_reader :message, :expected, :actual
|
12
9
|
|
13
|
-
# Takes the `message`, `expected`, and `actual` parameters
|
14
|
-
# and stuffs them into instance variables.
|
15
10
|
def initialize(message, expected, actual)
|
16
11
|
@message = message
|
17
12
|
@expected = expected
|
@@ -20,48 +15,23 @@ module Tst
|
|
20
15
|
end
|
21
16
|
end
|
22
17
|
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# Defines a few `assert` methods for use in tests.
|
26
|
-
#
|
27
|
-
# If you'd like to define your own assertion methods,
|
28
|
-
# open up the module and do so:
|
29
|
-
#
|
30
|
-
# module Tst::Assertions
|
31
|
-
# def assert_seven(actual)
|
32
|
-
# # return without raising to pass
|
33
|
-
# return if actual == 7
|
34
|
-
#
|
35
|
-
# # raise a Tst::Failure to fail
|
36
|
-
# raise Tst::Failure.new('Not 7', 7, actual)
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# Because `Assertions` is included into `Test`, your
|
41
|
-
# new methods will be available in `tst` blocks.
|
18
|
+
# Assertions available in `tst` blocks.
|
42
19
|
module Assertions
|
43
|
-
|
44
|
-
#
|
45
|
-
# It fails if `value` is `false` or `nil`. Succeeds otherwise.
|
20
|
+
|
21
|
+
# Fails if `value` is `false` or `nil`. Succeeds otherwise.
|
46
22
|
def assert(value)
|
47
23
|
return if value
|
48
24
|
raise Failure.new("Failure: Truthiness", "not false or nil", value)
|
49
25
|
end
|
50
26
|
|
51
|
-
# *assert_equal*, the egalitarian.
|
52
|
-
#
|
53
27
|
# Fails unless it's arguments are equal (with `==`).
|
54
28
|
def assert_equal(expected, actual)
|
55
29
|
return if expected == actual
|
56
30
|
raise Failure.new("Equality Failure", expected, actual)
|
57
31
|
end
|
58
32
|
|
59
|
-
# *assert_raises*, the pessimist.
|
60
|
-
#
|
61
33
|
# Succeeds if it catches an error AND that error is
|
62
|
-
# a `kind_of?` the `expected` error.
|
63
|
-
#
|
64
|
-
# Fails otherwise.
|
34
|
+
# a `kind_of?` the `expected` error. Fails otherwise.
|
65
35
|
def assert_raises(expected=StandardError)
|
66
36
|
begin
|
67
37
|
yield
|
@@ -73,55 +43,25 @@ module Tst
|
|
73
43
|
end
|
74
44
|
end
|
75
45
|
|
76
|
-
# ### Test ###
|
77
|
-
#
|
78
|
-
# An instance of test is basically only responsible for providing
|
79
|
-
# a scope within which to run a block.
|
80
|
-
#
|
81
|
-
# It includes the Assertions module so that the assertions
|
82
|
-
# methods are available to you inside your tests.
|
83
|
-
class Test
|
84
|
-
include Assertions
|
85
|
-
|
86
|
-
attr_reader :name
|
87
|
-
|
88
|
-
def initialize(name, &block)
|
89
|
-
@name = name
|
90
|
-
@block = block
|
91
|
-
end
|
92
|
-
|
93
|
-
def run
|
94
|
-
instance_eval &@block
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
46
|
# Set up some constants to represent test outcomes.
|
99
47
|
SUCCEEDED = :success
|
100
48
|
FAILED = :failure
|
101
49
|
RAISED = :exception
|
102
50
|
|
103
|
-
#
|
104
|
-
#
|
105
|
-
# A tidy little place to store test result information.
|
106
|
-
# The values should be self-explanatory.
|
51
|
+
# A little value object containing test result data
|
107
52
|
Result = Struct.new(:name, :status, :elapsed, :exception)
|
108
53
|
|
109
|
-
|
110
|
-
# ### Results ###
|
111
|
-
#
|
112
54
|
# A collection class that keeps track of test results.
|
113
55
|
class Results
|
114
56
|
attr_reader :count, :elapsed, :results
|
115
57
|
|
116
|
-
# It starts out with everything zeroed out.
|
117
58
|
def initialize
|
118
59
|
@count = 0
|
119
60
|
@elapsed = 0
|
120
61
|
@results = []
|
121
62
|
end
|
122
63
|
|
123
|
-
# Collects
|
124
|
-
# to reflect the new `result`.
|
64
|
+
# Collects a test result.
|
125
65
|
def <<(result)
|
126
66
|
@count += 1
|
127
67
|
@elapsed += result.elapsed
|
@@ -134,38 +74,31 @@ module Tst
|
|
134
74
|
def exceptions; results.select { |r| r.status == RAISED } end
|
135
75
|
end
|
136
76
|
|
137
|
-
#
|
138
|
-
#
|
139
|
-
# Collects and runs your tests.
|
77
|
+
# Runs test files in a fresh scope. It's not perfectly isolated, since
|
78
|
+
# requires can still add to the global scope, but it's good enough.
|
140
79
|
class Runner
|
141
|
-
attr_reader :tests, :results, :reporter
|
142
80
|
|
143
|
-
#
|
144
|
-
|
145
|
-
#
|
146
|
-
# Look at 'lib/tst/reporters.rb' for more information on reporters.
|
147
|
-
def initialize(reporter=nil)
|
148
|
-
@tests = []
|
149
|
-
@results = Results.new
|
150
|
-
@reporter = reporter || Reporters::Plain.new
|
151
|
-
end
|
81
|
+
# Gets us access to the assertions in our `tst` blocks.
|
82
|
+
include Assertions
|
152
83
|
|
153
|
-
|
154
|
-
|
155
|
-
|
84
|
+
def initialize(file, reporter, results)
|
85
|
+
@__reporter = reporter
|
86
|
+
@__results = results
|
87
|
+
__run_tests(file)
|
156
88
|
end
|
157
89
|
|
158
|
-
# Runs
|
159
|
-
|
160
|
-
|
161
|
-
tests.each { |test| run_test(test) }
|
162
|
-
reporter.summarize(results)
|
90
|
+
# Runs the tests by `instance-eval`-ing the test file.
|
91
|
+
def __run_tests(file)
|
92
|
+
instance_eval(File.read(file), File.expand_path(file), 1)
|
163
93
|
end
|
164
94
|
|
165
|
-
# The
|
166
|
-
|
95
|
+
# The `tst` methods itself.
|
96
|
+
# Takes a `name` and a block.
|
97
|
+
# Runs the block.
|
98
|
+
# Records the result.
|
99
|
+
def tst(name, &block)
|
167
100
|
start = Time.now
|
168
|
-
|
101
|
+
block.call
|
169
102
|
status = SUCCEEDED
|
170
103
|
rescue Failure => exception
|
171
104
|
status = FAILED
|
@@ -173,95 +106,36 @@ module Tst
|
|
173
106
|
status = RAISED
|
174
107
|
ensure
|
175
108
|
elapsed = Time.now - start
|
176
|
-
|
109
|
+
__record(name, status, elapsed, exception)
|
177
110
|
end
|
178
111
|
|
179
|
-
|
180
|
-
# `failure`, or `exception` method on `reporter` so
|
181
|
-
# it can show you your results as they come in.
|
182
|
-
def record(name, status, elapsed, exception=nil)
|
112
|
+
def __record(name, status, elapsed, exception=nil)
|
183
113
|
result = Result.new(name, status, elapsed, exception)
|
184
|
-
|
185
|
-
|
114
|
+
@__results << result
|
115
|
+
@__reporter.send(status, result)
|
186
116
|
end
|
187
117
|
end
|
188
118
|
|
189
|
-
#
|
119
|
+
# The main entry point.
|
190
120
|
#
|
191
|
-
#
|
192
|
-
#
|
193
|
-
class FileRunner
|
194
|
-
attr_reader :runner
|
195
|
-
|
196
|
-
# Runs the tests in the files represented by `glob`.
|
197
|
-
#
|
198
|
-
# `glob`: is any string that `Dir.glob` knows how to handle.
|
199
|
-
#
|
200
|
-
# Accepts the following options:
|
201
|
-
# `:reporter`: any object that responds_to the reporter
|
202
|
-
# interface
|
203
|
-
# (see 'lib/tst/reporters.rb' for details)
|
204
|
-
#
|
205
|
-
# `:load_paths`: an Array of directories to be added to
|
206
|
-
# the load path before running the tests.
|
207
|
-
#
|
208
|
-
# Note that `run` makes a new Runner each time it's called,
|
209
|
-
# allowing it to be called several times on the same
|
210
|
-
# FileRunner instance while still doing the right thing.
|
211
|
-
def run(glob, options={})
|
212
|
-
@runner = Runner.new options[:reporter]
|
213
|
-
load_files(glob, options[:load_paths] || [])
|
214
|
-
runner.run!
|
215
|
-
end
|
216
|
-
|
217
|
-
# Collects incoming tests and hands them off to the `runner`.
|
218
|
-
def <<(test)
|
219
|
-
runner << test
|
220
|
-
end
|
221
|
-
|
222
|
-
# Modifies the load path if necessary and loads all the
|
223
|
-
# test files.
|
224
|
-
def load_files(glob, load_paths)
|
225
|
-
load_paths.each { |path| $:.unshift(path) }
|
226
|
-
Dir[glob].each { |file| load(file, true) }
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
# Module-level accessor to a FileRunner instance.
|
231
|
-
def self.file_runner
|
232
|
-
@file_runner ||= FileRunner.new
|
233
|
-
end
|
234
|
-
|
235
|
-
# Hands a test off to `file_runner`. This is called by
|
236
|
-
# the top-level `tst` method (i.e., the one you use to
|
237
|
-
# write your tests with).
|
238
|
-
def self.add_test(name, &block)
|
239
|
-
file_runner << Test.new(name, &block)
|
240
|
-
end
|
241
|
-
|
242
|
-
# The module-level API entry point.
|
243
|
-
#
|
244
|
-
# An example from Tst's own Rakefile:
|
121
|
+
# glob - a String defining which test files to run.
|
122
|
+
# Passed through to Dir[].
|
245
123
|
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
# end
|
124
|
+
# Accepted options:
|
125
|
+
# :load_paths - an Array of directories to add to the load path.
|
126
|
+
# :reporter - a reporter instance (see 'lib/tst/reporters.rb'
|
127
|
+
# for docs on reporters)
|
251
128
|
def self.run(glob, options={})
|
252
|
-
|
129
|
+
options = default_options.merge(options)
|
130
|
+
$:.unshift(*options[:load_paths])
|
131
|
+
results = Results.new
|
132
|
+
reporter = options[:reporter]
|
133
|
+
Dir[glob].each { |file| Runner.new(file, reporter, results) }
|
134
|
+
reporter.summarize(results)
|
253
135
|
end
|
254
|
-
end
|
255
136
|
|
256
|
-
# The `
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
#
|
261
|
-
# tst "the answer is correct" do
|
262
|
-
# answer = Answer.new
|
263
|
-
# assert_equal 42, answer
|
264
|
-
# end
|
265
|
-
def tst(name=nil, &block)
|
266
|
-
Tst.add_test(name, &block)
|
137
|
+
# The default options for `run`.
|
138
|
+
def self.default_options
|
139
|
+
{ :reporter => Reporters::Plain.new, :load_paths => [] }
|
140
|
+
end
|
267
141
|
end
|
data/lib/tst/reporters/plain.rb
CHANGED
@@ -15,6 +15,7 @@ module Tst
|
|
15
15
|
@results = results
|
16
16
|
summary = ["\n"] + failures + exceptions + conclusion
|
17
17
|
summary.each { |line| io.puts(line) }
|
18
|
+
nil
|
18
19
|
end
|
19
20
|
|
20
21
|
def failures
|
@@ -62,12 +63,9 @@ module Tst
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def conclusion
|
65
|
-
[ "#{
|
66
|
+
[ "#{passed}, #{failed}, #{raised} in %.6fs" % results.elapsed ]
|
66
67
|
end
|
67
68
|
|
68
|
-
def elapsed
|
69
|
-
"Ran %d tests in %.6fs" % [results.count, results.elapsed]
|
70
|
-
end
|
71
69
|
def passed; "#{results.successes.count} passed" end
|
72
70
|
def failed; "#{results.failures.count} failed" end
|
73
71
|
def raised; "#{results.exceptions.count} raised" end
|
@@ -76,7 +74,7 @@ module Tst
|
|
76
74
|
backtrace.reject do |line|
|
77
75
|
line =~ BACKTRACE_FILTER
|
78
76
|
end.map do |line|
|
79
|
-
line.gsub("#{Dir.pwd}/", "")
|
77
|
+
line.gsub("#{Dir.pwd}/", "").gsub(/:in.*$/, '')
|
80
78
|
end
|
81
79
|
end
|
82
80
|
|
data/test/plain_reporter.rb
CHANGED
@@ -11,46 +11,58 @@ end
|
|
11
11
|
|
12
12
|
tst_runner_output "test/fixtures/success.rb", <<-end
|
13
13
|
.
|
14
|
-
|
14
|
+
1 passed, 0 failed, 0 raised in X.XXXs
|
15
15
|
end
|
16
16
|
|
17
17
|
tst_runner_output "test/fixtures/failure.rb", <<-end
|
18
18
|
F
|
19
|
-
F1: Failure: Truthiness -
|
20
|
-
exp:
|
19
|
+
F1: Failure: Truthiness - "one failing test"
|
20
|
+
exp: "not false or nil"
|
21
21
|
got: false
|
22
|
-
* test/fixtures/failure.rb:2
|
23
|
-
* test/
|
22
|
+
* test/fixtures/failure.rb:2
|
23
|
+
* test/fixtures/failure.rb:1
|
24
|
+
* test/plain_reporter.rb:7
|
25
|
+
* test/plain_reporter.rb:4
|
26
|
+
* test/plain_reporter.rb:17
|
24
27
|
|
25
|
-
|
28
|
+
0 passed, 1 failed, 0 raised in X.XXXs
|
26
29
|
end
|
27
30
|
|
28
31
|
tst_runner_output "test/fixtures/exception.rb", <<-end
|
29
32
|
E
|
30
|
-
E1: #<RuntimeError: I'm a teapot> -
|
31
|
-
* test/fixtures/exception.rb:2
|
32
|
-
* test/
|
33
|
+
E1: #<RuntimeError: I'm a teapot> - "one 'exceptional' test"
|
34
|
+
* test/fixtures/exception.rb:2
|
35
|
+
* test/fixtures/exception.rb:1
|
36
|
+
* test/plain_reporter.rb:7
|
37
|
+
* test/plain_reporter.rb:4
|
38
|
+
* test/plain_reporter.rb:31
|
33
39
|
|
34
|
-
|
40
|
+
0 passed, 0 failed, 1 raised in X.XXXs
|
35
41
|
end
|
36
42
|
|
37
43
|
tst_runner_output "test/fixtures/{exception,success,failure}.rb", <<-end
|
38
44
|
E.F
|
39
|
-
F1: Failure: Truthiness -
|
40
|
-
exp:
|
45
|
+
F1: Failure: Truthiness - "one failing test"
|
46
|
+
exp: "not false or nil"
|
41
47
|
got: false
|
42
|
-
* test/fixtures/failure.rb:2
|
43
|
-
* test/
|
48
|
+
* test/fixtures/failure.rb:2
|
49
|
+
* test/fixtures/failure.rb:1
|
50
|
+
* test/plain_reporter.rb:7
|
51
|
+
* test/plain_reporter.rb:4
|
52
|
+
* test/plain_reporter.rb:43
|
44
53
|
|
45
|
-
E1: #<RuntimeError: I'm a teapot> -
|
46
|
-
* test/fixtures/exception.rb:2
|
47
|
-
* test/
|
54
|
+
E1: #<RuntimeError: I'm a teapot> - "one 'exceptional' test"
|
55
|
+
* test/fixtures/exception.rb:2
|
56
|
+
* test/fixtures/exception.rb:1
|
57
|
+
* test/plain_reporter.rb:7
|
58
|
+
* test/plain_reporter.rb:4
|
59
|
+
* test/plain_reporter.rb:43
|
48
60
|
|
49
|
-
|
61
|
+
1 passed, 1 failed, 1 raised in X.XXXs
|
50
62
|
end
|
51
63
|
|
52
64
|
tst_runner_output "test/fixtures/does_not_exist.rb", <<-end
|
53
65
|
|
54
|
-
|
66
|
+
0 passed, 0 failed, 0 raised in X.XXXs
|
55
67
|
end
|
56
68
|
|
data/test/test.rb
CHANGED
@@ -1,23 +1,5 @@
|
|
1
|
-
|
2
|
-
# which helps mitigate state leakage...
|
3
|
-
tst "tests don't have access to top-level instance variables" do
|
4
|
-
@outside = "I'm outside"
|
1
|
+
def hello; 'hello' end
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
end.run
|
9
|
-
|
10
|
-
assert_equal "I'm outside", @outside
|
11
|
-
end
|
12
|
-
|
13
|
-
# ... but ruby block scope can be a bitch.
|
14
|
-
tst "for better or for worse, local variables are fair game" do
|
15
|
-
outside = "I'm outside"
|
16
|
-
|
17
|
-
Tst::Test.new "local variable" do
|
18
|
-
outside = "I'm inside, muahahaha!"
|
19
|
-
end.run
|
20
|
-
|
21
|
-
assert_equal "I'm inside, muahahaha!", outside
|
3
|
+
tst "access to methods defined in the file" do
|
4
|
+
assert_equal 'hello', hello
|
22
5
|
end
|
23
|
-
|
data/test/test2.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tst
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A small testing library that tries not to do too much.
|
15
15
|
email: satchmorun@gmail.com
|
@@ -32,6 +32,7 @@ files:
|
|
32
32
|
- test/fixtures/success.rb
|
33
33
|
- test/plain_reporter.rb
|
34
34
|
- test/test.rb
|
35
|
+
- test/test2.rb
|
35
36
|
homepage: http://github.com/satchmorun/tst
|
36
37
|
licenses:
|
37
38
|
- MIT
|
@@ -64,3 +65,4 @@ test_files:
|
|
64
65
|
- test/fixtures/success.rb
|
65
66
|
- test/plain_reporter.rb
|
66
67
|
- test/test.rb
|
68
|
+
- test/test2.rb
|