blackstart 0.1.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.
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2024 Aaron Beckerman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.txt ADDED
@@ -0,0 +1,152 @@
1
+ Blackstart
2
+
3
+ Blackstart is a small, subdued library for automated testing in Ruby. It
4
+ doesn't depend on anything beyond the Ruby platform and doesn't modify the
5
+ environment outside its conventional namespace. It's tested with a primitive
6
+ program, not via an automated-testing library.
7
+
8
+ The blackstart is a small, subdued bird that eats bugs. A black start is when a
9
+ power plant starts up without relying on the electrical grid.
10
+
11
+ Here's an example of a test program that uses Blackstart:
12
+
13
+ require "blackstart"
14
+
15
+ exit Blackstart.run Blackstart.add { |adder|
16
+ adder.call do
17
+ unless "Hello, World!" == ["He", "", "o, Wor", "d!"].join("l")
18
+ raise "join did not work as expected"
19
+ end
20
+ end
21
+
22
+ adder.call do
23
+ unless "sample" == "simple".gsub(/i/, "a")
24
+ raise "gsub did not work as expected"
25
+ end
26
+ end
27
+ }
28
+
29
+ Blackstart.add adds procs to a collection and returns that collection. In the
30
+ example, each proc is designed to run a test and, if it fails, raise an error
31
+ to signal this.
32
+
33
+ Blackstart.run runs a sequence of tests and reports information about any that
34
+ fail -- that is, any that raise an error. In the example, failure information
35
+ would be written to the standard output stream. It returns false if there were
36
+ failures; otherwise, it returns true.
37
+
38
+ The library provides little beyond this, but it's easy to do relatively
39
+ sophisticated things with it. Some examples follow.
40
+
41
+
42
+ - Exiting with the appropriate status
43
+
44
+ Blackstart.run returns false if there were any failures; otherwise, it returns
45
+ true. If you use this as the argument to Kernel#exit, your test program will
46
+ exit with a successful status only if there were no failures.
47
+
48
+
49
+ - Defining helpers
50
+
51
+ You may want all your tests to be able to assert something, generate test data,
52
+ or perform some other task by sending a message. You could implement this
53
+ statelessly in a singleton object or all instances of Object, for example, but
54
+ there's another option that may be more convenient. Blackstart.run calls each
55
+ test proc in the context of a new Blackstart::Context instance. You can define
56
+ instance methods in that class like this:
57
+
58
+ class Blackstart::Context
59
+ def assert boolean
60
+ raise "assertion failed" unless boolean
61
+ end
62
+
63
+ def make_products
64
+ @cabbage = { :description => "head of cabbage", :price => 125 }
65
+ @orange = { :description => "Cara cara navel orange", :price => 100 }
66
+ nil
67
+ end
68
+ end
69
+
70
+ All of your tests will be able to use them by sending messages to self. These
71
+ methods can see and modify the test's state, which is disposable: it will be
72
+ discarded after the test is complete and so will not affect later tests.
73
+
74
+
75
+ - Running code before and after each test
76
+
77
+ You can run code before and after each test by defining a custom
78
+ Blackstart::Context#instance_exec. For example:
79
+
80
+ class Blackstart::Context
81
+ def instance_exec(*)
82
+ puts "doing setup"
83
+ @variable = "example"
84
+ super
85
+ ensure
86
+ puts "doing teardown"
87
+ end
88
+ end
89
+
90
+
91
+ - Building a test collection in stages
92
+
93
+ You can build your collection of test objects in stages and run it at the end.
94
+ For example:
95
+
96
+ require "blackstart"
97
+
98
+ TEST_OBJECTS = []
99
+
100
+ Blackstart.add TEST_OBJECTS do |adder|
101
+ adder.call do
102
+ unless "Hello, World!" == ["He", "", "o, Wor", "d!"].join("l")
103
+ raise "join did not work as expected"
104
+ end
105
+ end
106
+ end
107
+
108
+ Blackstart.add TEST_OBJECTS do |adder|
109
+ adder.call do
110
+ unless "sample" == "simple".gsub(/i/, "a")
111
+ raise "gsub did not work as expected"
112
+ end
113
+ end
114
+ end
115
+
116
+ exit Blackstart.run TEST_OBJECTS
117
+
118
+ This makes it straightforward to define your tests in multiple files that you
119
+ load in your test program.
120
+
121
+
122
+ - Running tests in random order
123
+
124
+ Blackstart.run runs a sequence of tests in order, but you can pass it a
125
+ randomly-ordered sequence. Array#shuffle may be helpful for this. If you do
126
+ this, you may also want to print the random seed at the start of your program
127
+ so you can re-run your tests in the same order.
128
+
129
+
130
+ - Reporting detailed test descriptions
131
+
132
+ After a test fails, Blackstart.run writes a description of the test to the
133
+ output stream. It gets this description by converting the test object to a
134
+ string. When the test object is an instance of Proc, which is what
135
+ Blackstart.add produces when used as expected, this string typically includes
136
+ the file path and line number where it was defined: helpful, but it won't be
137
+ immediately clear what was being tested.
138
+
139
+ You can improve this by making your own test objects instead of using
140
+ Blackstart.add. Blackstart.run does not strictly need a sequence of Proc
141
+ instances; it only needs a sequence of objects that convert to Proc instances
142
+ in response to to_proc messages. Your custom test objects can respond to to_s
143
+ with detailed descriptions instead of mere file paths and line numbers.
144
+
145
+
146
+ - Handling failures differently
147
+
148
+ Blackstart.run handles each failure by sending a puts message to the output
149
+ stream, one of its parameters. By default, this is $stdout, so the default
150
+ behavior is to print unadorned failure information to standard output. But you
151
+ can specify any object as the output stream -- even if it's not really a stream
152
+ -- allowing you to handle failure information however you want.
@@ -0,0 +1,11 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "blackstart"
3
+ s.version = "0.1.0"
4
+ s.authors = ["Aaron Beckerman"]
5
+ s.summary = "A small, subdued library for automated testing."
6
+ s.licenses = ["MIT"]
7
+ s.required_ruby_version = ">= 1.8.7"
8
+ s.files = ["LICENSE.txt", "README.txt", "blackstart.gemspec",
9
+ "lib/blackstart.rb", "test/blackstart_test.rb"]
10
+ s.test_files = ["test/blackstart_test.rb"]
11
+ end
data/lib/blackstart.rb ADDED
@@ -0,0 +1,92 @@
1
+ ##
2
+ # This module provides facilities for defining and running automated tests.
3
+
4
+ module Blackstart
5
+
6
+ ##
7
+ # Calls the block and returns a string describing the error raised, if any.
8
+ #
9
+ # In detail: This method sends call with no arguments to the object
10
+ # representing the block. If that raises an error -- that is, an exception
11
+ # whose class is StandardError or a descendent of StandardError -- this
12
+ # method creates a string describing that error and returns it; the
13
+ # description includes the error's class, message, and backtrace (if any). If
14
+ # sending the message raises any other exception, this method raises that
15
+ # exception. If sending the message does not raise an exception, this method
16
+ # returns nil.
17
+
18
+ def self.vet &prc
19
+ prc.call
20
+ nil
21
+ rescue ::StandardError
22
+ # Like IO#puts, separate lines with a line feed character rather than $\.
23
+ ["#{$!.class}: #{$!.message}"].concat($!.backtrace || []).join "\n"
24
+ end
25
+
26
+ ##
27
+ # Allows the block to add procs to a collection, which it returns.
28
+ #
29
+ # In detail: This method sends call with one positional argument, an adder
30
+ # object, to the object representing the block, director. This block can send
31
+ # call messages to the adder to add objects representing the respective
32
+ # blocks to the collection, sink. With each sending of call, the object to be
33
+ # added will be either a proc (if call is sent with a block) or nil (if call
34
+ # is sent without a block). If any non-block arguments are sent with the call
35
+ # message, an exception is raised. To add the object, the adder sends a <<
36
+ # message to sink with the object as the positional argument and no other
37
+ # arguments. The adder returns nil in response to a call message if it
38
+ # returns at all. This method returns sink.
39
+ #
40
+ # By default, sink is a new empty array.
41
+
42
+ def self.add sink = [], &director
43
+ director.call ::Kernel.lambda { |&prc|
44
+ sink << prc
45
+ nil
46
+ }
47
+ sink
48
+ end
49
+
50
+ ##
51
+ # A class for the contexts (the self objects) of tests.
52
+
53
+ class Context
54
+ end
55
+
56
+ ##
57
+ # Runs the tests, writes any failure information to the output stream, and
58
+ # returns a boolean indicating whether there were no failures.
59
+ #
60
+ # In detail: This method expects the sequence of test objects, source, to
61
+ # respond to an each message by yielding successive test objects to its
62
+ # block. Each test is run by converting the test object to a proc and calling
63
+ # it in the context of a new instance of Blackstart::Context. A failure is
64
+ # when the test raises an error (that is, an exception whose class is
65
+ # StandardError or a descendent of StandardError). After a failure, this
66
+ # method sends a puts message to the output stream, ostream, with these
67
+ # arguments (positional, in order): a string "FAILED TEST:", the test object
68
+ # converted to a string via to_s, a string "...ERROR:", a string describing
69
+ # the error, and an empty string. If a test raises any other exception, this
70
+ # method immediately raises that exception. After it has run all the tests
71
+ # and handled any failures, this method returns false if there were failures
72
+ # or true otherwise.
73
+ #
74
+ # By default, ostream is $stdout.
75
+
76
+ def self.run source, ostream = $stdout
77
+ success = true
78
+ for tst in source
79
+ # Convert to a proc and create a context outside the vet block so that
80
+ # this method will raise any exception that results instead of
81
+ # potentially treating it as a test failure.
82
+ prc = ::Proc.new(&tst)
83
+ context = Context.new
84
+ if err_desc = vet { context.instance_exec(&prc) }
85
+ success = false
86
+ ostream.puts "FAILED TEST:", tst.to_s, "...ERROR:", err_desc.to_s, ""
87
+ end
88
+ end
89
+ success
90
+ end
91
+
92
+ end
@@ -0,0 +1,404 @@
1
+ # Sections that create local variables are in class definitions so that later
2
+ # sections cannot accidentally reference those local variables.
3
+
4
+ require "blackstart"
5
+
6
+ # Blackstart should be a module.
7
+ fail "" unless Module.equal? Blackstart.class
8
+
9
+ # Blackstart should say it responds to vet, add, and run.
10
+ fail "" unless Blackstart.respond_to? :vet
11
+ fail "" unless Blackstart.respond_to? :add
12
+ fail "" unless Blackstart.respond_to? :run
13
+
14
+ # Test Blackstart.vet:
15
+
16
+ # Blackstart.vet should raise an exception if any non-block arguments are sent.
17
+ begin
18
+ Blackstart.vet nil
19
+ rescue ArgumentError
20
+ else
21
+ fail ""
22
+ end
23
+ begin
24
+ Blackstart.vet(nil) {}
25
+ rescue ArgumentError
26
+ else
27
+ fail ""
28
+ end
29
+
30
+ # If sending call with no arguments to the block raises an error,
31
+ # Blackstart.vet should return a new descriptive string.
32
+ class ::Object
33
+ fail "" unless /\ANoMethodError: / =~ Blackstart.vet
34
+
35
+ e_class = Class.new StandardError
36
+ def e_class.to_s
37
+ "FakeError".freeze
38
+ end
39
+
40
+ e_nil = e_class.new "a".freeze
41
+ def e_nil.backtrace
42
+ nil
43
+ end
44
+ fail "" unless "FakeError: a" == Blackstart.vet { ::Kernel.raise e_nil }
45
+
46
+ e_empty = e_class.new "b".freeze
47
+ def e_empty.backtrace
48
+ [].freeze
49
+ end
50
+ fail "" unless "FakeError: b" == Blackstart.vet { ::Kernel.raise e_empty }
51
+
52
+ e_full = e_class.new "c".freeze
53
+ def e_full.backtrace
54
+ ["d".freeze, "e".freeze].freeze
55
+ end
56
+ fail "" unless "FakeError: c\nd\ne" ==
57
+ Blackstart.vet { ::Kernel.raise e_full }
58
+ end
59
+
60
+ # If sending call with no arguments to the block raises a non-StandardError
61
+ # exception, Blackstart.vet should not rescue it.
62
+ class ::Object
63
+ non_standard_error = Class.new Exception
64
+ begin
65
+ Blackstart.vet { ::Kernel.raise non_standard_error }
66
+ rescue non_standard_error
67
+ else
68
+ fail ""
69
+ end
70
+ end
71
+
72
+ # If sending call with no arguments to the block does not raise an exception,
73
+ # Blackstart.vet should return nil.
74
+ fail "" unless nil.equal? Blackstart.vet { nil }
75
+ fail "" unless nil.equal? Blackstart.vet { true }
76
+
77
+ # Test Blackstart.add:
78
+
79
+ # When there is no block, Blackstart.add should raise an exception.
80
+ begin
81
+ Blackstart.add
82
+ rescue NoMethodError
83
+ else
84
+ fail ""
85
+ end
86
+ begin
87
+ Blackstart.add []
88
+ rescue NoMethodError
89
+ else
90
+ fail ""
91
+ end
92
+
93
+ # Blackstart.add should raise an exception if superfluous arguments are sent.
94
+ begin
95
+ Blackstart.add [], "invalid"
96
+ rescue ArgumentError
97
+ else
98
+ fail ""
99
+ end
100
+ begin
101
+ Blackstart.add([], "invalid") {}
102
+ rescue ArgumentError
103
+ else
104
+ fail ""
105
+ end
106
+
107
+ # When no collection is specified and the block does nothing, Blackstart.add
108
+ # should return an empty array.
109
+ fail "" unless [] == Blackstart.add {}
110
+
111
+ # When a collection is specified and the block tries to add to the collection,
112
+ # Blackstart.add should add corresponding procs or nil to the collection by
113
+ # sending <<.
114
+ class ::Object
115
+ sink = [42]
116
+ prc1 = proc {}
117
+ prc2 = proc {}
118
+ retval = Blackstart.add sink do |adder|
119
+ adder.call(&prc1)
120
+ adder.call(&prc2)
121
+ adder.call
122
+ end
123
+ fail "" unless sink.equal? retval
124
+ fail "" unless [42, prc1, prc2, nil] == sink
125
+ end
126
+
127
+ # When the block sends call to the adder with arguments other than a block, it
128
+ # should raise an exception and not add anything to the collection.
129
+ class ::Object
130
+ sink = []
131
+ begin
132
+ Blackstart.add(sink) { |adder| adder.call("invalid") {} }
133
+ rescue ArgumentError
134
+ else
135
+ fail ""
136
+ end
137
+ begin
138
+ Blackstart.add(sink) { |adder| adder.call "invalid" }
139
+ rescue ArgumentError
140
+ else
141
+ fail ""
142
+ end
143
+ fail "" unless 0 == sink.length
144
+ end
145
+
146
+ # When Blackstart.add's block sends call to the adder and it returns, nil
147
+ # should be the object it returns.
148
+ class ::Object
149
+ retval_block = retval_no_block = true
150
+ Blackstart.add do |adder|
151
+ retval_block = adder.call {}
152
+ retval_no_block = adder.call
153
+ end
154
+ fail "" unless nil.equal? retval_block
155
+ fail "" unless nil.equal? retval_no_block
156
+ end
157
+
158
+ # In general, when there is a block that raises an exception, Blackstart.add
159
+ # should not rescue it.
160
+ class ::Object
161
+ e = StandardError.new
162
+ begin
163
+ Blackstart.add { ::Kernel.raise e }
164
+ rescue
165
+ fail "" unless e.equal? $!
166
+ else
167
+ fail ""
168
+ end
169
+ end
170
+
171
+ # When there is a block that tries to add to the collection and the collection
172
+ # responds to the << message by raising an exception, Blackstart.add should not
173
+ # rescue it.
174
+ begin
175
+ Blackstart.add(nil) { |adder| adder.call {} }
176
+ rescue NoMethodError
177
+ else
178
+ fail ""
179
+ end
180
+
181
+ # When no collection is specified and the block tries to add to the collection,
182
+ # Blackstart.add should append to a new array that gets returned.
183
+ class ::Object
184
+ prc = proc {}
185
+ fail "" unless [prc] == Blackstart.add { |adder| adder.call(&prc) }
186
+ end
187
+
188
+ # Test Blackstart::Context:
189
+
190
+ # Blackstart::Context.new should return an instance of Blackstart::Context,
191
+ # which implies that Blackstart::Context should be a class.
192
+ fail "" unless Blackstart::Context.equal? Blackstart::Context.new.class
193
+
194
+ # Blackstart::Context.new should raise an exception if any non-block arguments
195
+ # are sent.
196
+ begin
197
+ Blackstart::Context.new nil
198
+ rescue ArgumentError
199
+ else
200
+ fail ""
201
+ end
202
+
203
+ # Test Blackstart.run:
204
+
205
+ # Blackstart.run should send appropriate messages to the output stream and
206
+ # return the appropriate object based on the behavior of the tests.
207
+ class ::Object
208
+ begin
209
+ # Set $stdout to a test spy and set it back in the ensure clause.
210
+ original_stdout = $stdout
211
+ spy_stdout = $stdout.clone
212
+ spy_stdout.instance_variable_set :@_test_calls, stdout_calls = []
213
+ def spy_stdout.puts *args
214
+ @_test_calls << args
215
+ nil
216
+ end
217
+ $stdout = spy_stdout
218
+
219
+ # No tests.
220
+ source = [].freeze
221
+ fail "" unless true.equal? Blackstart.run(source, Object.new)
222
+ fail "" unless true.equal? Blackstart.run(source, spy_stdout)
223
+ fail "" unless true.equal? Blackstart.run(source)
224
+ fail "" unless 0 == stdout_calls.length
225
+
226
+ # Tests that do not raise exceptions.
227
+ source = [proc {}, proc { 42 }].freeze
228
+ fail "" unless true.equal? Blackstart.run(source, Object.new)
229
+ fail "" unless true.equal? Blackstart.run(source, spy_stdout)
230
+ fail "" unless true.equal? Blackstart.run(source)
231
+ fail "" unless 0 == stdout_calls.length
232
+
233
+ # Define some example test objects.
234
+ e_class = Class.new StandardError
235
+ def e_class.to_s
236
+ "FakeError"
237
+ end
238
+ fail_prc1 = proc { ::Kernel.raise e_class, "fake message 1" }
239
+ def fail_prc1.to_s
240
+ "to_s 1"
241
+ end
242
+ fail_prc2 = Object.new # Not a Proc instance, but converts to one.
243
+ fail_prc2.instance_variable_set :@_test_e_class, e_class
244
+ def fail_prc2.to_proc
245
+ e_class = @_test_e_class
246
+ ::Proc.new { ::Kernel.raise e_class, "fake message 2" }
247
+ end
248
+ def fail_prc2.to_s
249
+ "to_s 2"
250
+ end
251
+ pass_prc = proc {}
252
+
253
+ # A mix of tests that raise errors and tests that return.
254
+ source = [fail_prc1, fail_prc2, pass_prc].freeze
255
+
256
+ # Output stream that does not conform to the expected interface. (And in
257
+ # general, the only exceptions Blackstart.run should rescue are
258
+ # StandardError exceptions raised by tests.)
259
+ begin
260
+ Blackstart.run source, Object.new
261
+ rescue NoMethodError
262
+ else
263
+ fail ""
264
+ end
265
+ fail "" unless 0 == stdout_calls.length
266
+
267
+ # Output stream that conforms to the expected interface.
268
+ spy_ostream = Object.new
269
+ spy_ostream.instance_variable_set :@_test_calls, calls = []
270
+ def spy_ostream.puts *args
271
+ @_test_calls << args
272
+ nil
273
+ end
274
+ fail "" unless false.equal? Blackstart.run(source, spy_ostream)
275
+ fail "" unless 0 == stdout_calls.length
276
+ fail "" unless 2 == calls.length
277
+ fail "" unless 5 == calls[0].length
278
+ fail "" unless "FAILED TEST:" == calls[0][0]
279
+ fail "" unless "to_s 1" == calls[0][1]
280
+ fail "" unless "...ERROR:" == calls[0][2]
281
+ fail "" unless /\AFakeError: fake message 1$/ =~ calls[0][3]
282
+ fail "" unless "" == calls[0][4]
283
+ fail "" unless 5 == calls[1].length
284
+ fail "" unless "FAILED TEST:" == calls[1][0]
285
+ fail "" unless "to_s 2" == calls[1][1]
286
+ fail "" unless "...ERROR:" == calls[1][2]
287
+ fail "" unless /\AFakeError: fake message 2$/ =~ calls[1][3]
288
+ fail "" unless "" == calls[1][4]
289
+ spy_ostream = calls = nil
290
+
291
+ # Default output stream.
292
+ stdout_calls.clear
293
+ fail "" unless false.equal? Blackstart.run(source)
294
+ fail "" unless 2 == stdout_calls.length
295
+ fail "" unless 5 == stdout_calls[0].length
296
+ fail "" unless "FAILED TEST:" == stdout_calls[0][0]
297
+ fail "" unless "to_s 1" == stdout_calls[0][1]
298
+ fail "" unless "...ERROR:" == stdout_calls[0][2]
299
+ fail "" unless /\AFakeError: fake message 1$/ =~ stdout_calls[0][3]
300
+ fail "" unless "" == stdout_calls[0][4]
301
+ fail "" unless 5 == stdout_calls[1].length
302
+ fail "" unless "FAILED TEST:" == stdout_calls[1][0]
303
+ fail "" unless "to_s 2" == stdout_calls[1][1]
304
+ fail "" unless "...ERROR:" == stdout_calls[1][2]
305
+ fail "" unless /\AFakeError: fake message 2$/ =~ stdout_calls[1][3]
306
+ fail "" unless "" == stdout_calls[1][4]
307
+ stdout_calls.clear
308
+
309
+ # Test that raises a non-StandardError exception. (And in general, the only
310
+ # exceptions Blackstart.run should rescue are StandardError exceptions
311
+ # raised by tests.)
312
+ non_standard_error = Class.new Exception
313
+ source = [proc { ::Kernel.raise non_standard_error }]
314
+ begin
315
+ Blackstart.run source, spy_stdout
316
+ rescue non_standard_error
317
+ else
318
+ fail ""
319
+ end
320
+ fail "" unless 0 == stdout_calls.length
321
+
322
+ # Test sequence that does not conform to the interface. (And in general,
323
+ # the only exceptions Blackstart.run should rescue are StandardError
324
+ # exceptions raised by tests.)
325
+ begin
326
+ Blackstart.run nil, spy_stdout
327
+ rescue NoMethodError
328
+ else
329
+ fail ""
330
+ end
331
+ fail "" unless 0 == stdout_calls.length
332
+
333
+ # Test sequences containing objects that do not convert to procs (and do
334
+ # not pretend to) and objects that pretend to convert to procs but do not.
335
+ # (And in general, the only exceptions Blackstart.run should rescue are
336
+ # StandardError exceptions raised by tests.)
337
+ source = [nil]
338
+ begin
339
+ Blackstart.run source, spy_stdout
340
+ rescue ArgumentError
341
+ else
342
+ fail ""
343
+ end
344
+ source = [0]
345
+ begin
346
+ Blackstart.run source, spy_stdout
347
+ rescue TypeError
348
+ else
349
+ fail ""
350
+ end
351
+ bad_to_proc = Object.new
352
+ def bad_to_proc.to_proc
353
+ nil
354
+ end
355
+ source = [bad_to_proc]
356
+ begin
357
+ Blackstart.run source, spy_stdout
358
+ rescue TypeError
359
+ else
360
+ fail ""
361
+ end
362
+ fail "" unless 0 == stdout_calls.length
363
+ ensure
364
+ $stdout = original_stdout
365
+ end
366
+ end
367
+
368
+ # Blackstart.run should call each test proc with no arguments.
369
+ class ::Object
370
+ args = nil
371
+ tst = proc do |*a|
372
+ args = a
373
+ end
374
+ Blackstart.run [tst], nil
375
+ fail "" unless [] == args
376
+ end
377
+
378
+ # Blackstart.run should call each test proc in the context of a unique instance
379
+ # of Blackstart::Context.
380
+ class ::Object
381
+ context1 = context2 = nil
382
+ Blackstart.run [proc { context1 = self }, proc { context2 = self }], nil
383
+ fail "" unless Blackstart::Context.equal? context1.class
384
+ fail "" unless Blackstart::Context.equal? context2.class
385
+ fail "" if context1.equal? context2
386
+ end
387
+
388
+ # Blackstart.run should raise an exception if too few or too many non-block
389
+ # arguments are sent.
390
+ begin
391
+ Blackstart.run
392
+ rescue ArgumentError
393
+ else
394
+ fail ""
395
+ end
396
+ begin
397
+ Blackstart.run [], nil, "invalid"
398
+ rescue ArgumentError
399
+ else
400
+ fail ""
401
+ end
402
+
403
+ # If this message doesn't get written, there was a problem.
404
+ puts "Test finished: #{__FILE__}"
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blackstart
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Aaron Beckerman
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2024-03-19 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email:
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - LICENSE.txt
32
+ - README.txt
33
+ - blackstart.gemspec
34
+ - lib/blackstart.rb
35
+ - test/blackstart_test.rb
36
+ has_rdoc: true
37
+ homepage:
38
+ licenses:
39
+ - MIT
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ hash: 57
51
+ segments:
52
+ - 1
53
+ - 8
54
+ - 7
55
+ version: 1.8.7
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.6.2
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A small, subdued library for automated testing.
72
+ test_files:
73
+ - test/blackstart_test.rb