rutema 2.0.1 → 2.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.
- checksums.yaml +4 -4
- data/History.txt +7 -2
- data/README.md +12 -12
- data/bin/rutema +4 -4
- data/lib/rutema/application.rb +34 -31
- data/lib/rutema/core/configuration.rb +122 -117
- data/lib/rutema/core/engine.rb +102 -113
- data/lib/rutema/core/framework.rb +54 -54
- data/lib/rutema/core/objectmodel.rb +112 -95
- data/lib/rutema/core/parser.rb +9 -10
- data/lib/rutema/core/reporter.rb +76 -70
- data/lib/rutema/core/runner.rb +118 -97
- data/lib/rutema/elements/minimal.rb +29 -25
- data/lib/rutema/parsers/xml.rb +101 -93
- data/lib/rutema/reporters/json.rb +18 -20
- data/lib/rutema/reporters/junit.rb +88 -80
- data/lib/rutema/version.rb +1 -1
- metadata +13 -14
data/lib/rutema/core/engine.rb
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# Copyright (c) 2007-2021 Vassilis Rizopoulos. All rights reserved.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
7
|
-
require_relative '../version'
|
|
3
|
+
require_relative "parser"
|
|
4
|
+
require_relative "reporter"
|
|
5
|
+
require_relative "runner"
|
|
6
|
+
require_relative "../version"
|
|
8
7
|
|
|
9
8
|
module Rutema
|
|
10
9
|
##
|
|
@@ -29,21 +28,21 @@ module Rutema
|
|
|
29
28
|
#
|
|
30
29
|
# * +configuration+ - a Configuration instance according to which Engine,
|
|
31
30
|
# its components and the test run shall be set up
|
|
32
|
-
def initialize
|
|
33
|
-
@queue=Queue.new
|
|
34
|
-
@parser=instantiate_class(configuration.parser,configuration) if configuration.parser
|
|
31
|
+
def initialize(configuration)
|
|
32
|
+
@queue = Queue.new
|
|
33
|
+
@parser = instantiate_class(configuration.parser, configuration) if configuration.parser
|
|
35
34
|
if configuration.runner
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
end
|
|
35
|
+
raise RutemaError, "Runner settting overriden, but missing :class" unless configuration.runner[:class]
|
|
36
|
+
|
|
37
|
+
@runner = configuration.runner[:class].new(configuration.context, @queue)
|
|
38
|
+
|
|
41
39
|
else
|
|
42
|
-
@runner=Rutema::Runners::Default.new(configuration.context
|
|
40
|
+
@runner = Rutema::Runners::Default.new(configuration.context, @queue)
|
|
43
41
|
end
|
|
44
|
-
raise RutemaError,"Could not instantiate parser" unless @parser
|
|
45
|
-
|
|
46
|
-
@
|
|
42
|
+
raise RutemaError, "Could not instantiate parser" unless @parser
|
|
43
|
+
|
|
44
|
+
@dispatcher = Dispatcher.new(@queue, configuration)
|
|
45
|
+
@configuration = configuration
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
##
|
|
@@ -52,18 +51,18 @@ module Rutema
|
|
|
52
51
|
# * +test_identifier+ - an optional identifier of a single test case to be
|
|
53
52
|
# executed, this cannot be an arbitrary one but must still be contained
|
|
54
53
|
# in the configured test specification identifiers
|
|
55
|
-
def run
|
|
54
|
+
def run(test_identifier = nil)
|
|
56
55
|
@dispatcher.run!
|
|
57
56
|
# start
|
|
58
57
|
message("start")
|
|
59
|
-
suite_setup,suite_teardown,setup,teardown,tests
|
|
60
|
-
if tests.empty?
|
|
58
|
+
suite_setup, suite_teardown, setup, teardown, tests = *parse(test_identifier)
|
|
59
|
+
if tests.empty?
|
|
61
60
|
@dispatcher.exit
|
|
62
|
-
raise RutemaError,"No tests to run!"
|
|
61
|
+
raise RutemaError, "No tests to run!"
|
|
63
62
|
else
|
|
64
63
|
# running - at this point all checks are done and the tests are active
|
|
65
64
|
message("running")
|
|
66
|
-
run_scenarios(tests,suite_setup,suite_teardown,setup,teardown)
|
|
65
|
+
run_scenarios(tests, suite_setup, suite_teardown, setup, teardown)
|
|
67
66
|
end
|
|
68
67
|
message("end")
|
|
69
68
|
@dispatcher.exit
|
|
@@ -77,23 +76,23 @@ module Rutema
|
|
|
77
76
|
# * +test_identifier+ - an optional identifier of a single test case to be
|
|
78
77
|
# executed, this cannot be an arbitrary one but must still be contained
|
|
79
78
|
# in the configured test specification identifiers
|
|
80
|
-
def parse
|
|
81
|
-
specs=[]
|
|
82
|
-
#so, while we are parsing, we have a list of tests
|
|
83
|
-
#we're either parsing all of the tests, or just one
|
|
84
|
-
#make sure the one test is on the list
|
|
79
|
+
def parse(test_identifier = nil)
|
|
80
|
+
specs = []
|
|
81
|
+
# so, while we are parsing, we have a list of tests
|
|
82
|
+
# we're either parsing all of the tests, or just one
|
|
83
|
+
# make sure the one test is on the list
|
|
85
84
|
if test_identifier
|
|
86
85
|
if is_spec_included?(test_identifier)
|
|
87
|
-
specs<<parse_specification(File.expand_path(test_identifier))
|
|
86
|
+
specs << parse_specification(File.expand_path(test_identifier))
|
|
88
87
|
else
|
|
89
|
-
error(File.expand_path(test_identifier),"does not exist in the configuration")
|
|
88
|
+
error(File.expand_path(test_identifier), "does not exist in the configuration")
|
|
90
89
|
end
|
|
91
90
|
else
|
|
92
|
-
specs=parse_specifications(@configuration.tests)
|
|
91
|
+
specs = parse_specifications(@configuration.tests)
|
|
93
92
|
end
|
|
94
93
|
specs.compact!
|
|
95
|
-
suite_setup,suite_teardown,setup,teardown=parse_specials(@configuration)
|
|
96
|
-
return [suite_setup,suite_teardown,setup,teardown,specs]
|
|
94
|
+
suite_setup, suite_teardown, setup, teardown = parse_specials(@configuration)
|
|
95
|
+
return [suite_setup, suite_teardown, setup, teardown, specs]
|
|
97
96
|
end
|
|
98
97
|
|
|
99
98
|
private
|
|
@@ -103,8 +102,8 @@ module Rutema
|
|
|
103
102
|
#
|
|
104
103
|
# * +tests+ - an array containing paths to test specification files or the
|
|
105
104
|
# test specifications' texts themselves
|
|
106
|
-
def parse_specifications
|
|
107
|
-
tests.map do |t|
|
|
105
|
+
def parse_specifications(tests)
|
|
106
|
+
tests.map do |t|
|
|
108
107
|
parse_specification(t)
|
|
109
108
|
end.compact
|
|
110
109
|
end
|
|
@@ -116,13 +115,11 @@ module Rutema
|
|
|
116
115
|
# actual test specification text itself
|
|
117
116
|
#
|
|
118
117
|
# A ParserError is raised upon failure.
|
|
119
|
-
def parse_specification
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
raise Rutema::ParserError, "In #{spec_identifier}: #{$!.message}"
|
|
125
|
-
end
|
|
118
|
+
def parse_specification(spec_identifier)
|
|
119
|
+
@parser.parse_specification(spec_identifier)
|
|
120
|
+
rescue Rutema::ParserError
|
|
121
|
+
error(spec_identifier, $!.message)
|
|
122
|
+
raise Rutema::ParserError, "In #{spec_identifier}: #{$!.message}"
|
|
126
123
|
end
|
|
127
124
|
|
|
128
125
|
##
|
|
@@ -133,24 +130,16 @@ module Rutema
|
|
|
133
130
|
# * test suite teardown
|
|
134
131
|
# * test setup
|
|
135
132
|
# * test teardown
|
|
136
|
-
def parse_specials
|
|
137
|
-
suite_setup=nil
|
|
138
|
-
suite_teardown=nil
|
|
139
|
-
setup=nil
|
|
140
|
-
teardown=nil
|
|
141
|
-
if configuration.suite_setup
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if configuration.
|
|
145
|
-
|
|
146
|
-
end
|
|
147
|
-
if configuration.setup
|
|
148
|
-
setup=parse_specification(configuration.setup)
|
|
149
|
-
end
|
|
150
|
-
if configuration.teardown
|
|
151
|
-
teardown=parse_specification(configuration.teardown)
|
|
152
|
-
end
|
|
153
|
-
return suite_setup,suite_teardown,setup,teardown
|
|
133
|
+
def parse_specials(configuration)
|
|
134
|
+
suite_setup = nil
|
|
135
|
+
suite_teardown = nil
|
|
136
|
+
setup = nil
|
|
137
|
+
teardown = nil
|
|
138
|
+
suite_setup = parse_specification(configuration.suite_setup) if configuration.suite_setup
|
|
139
|
+
suite_teardown = parse_specification(configuration.suite_teardown) if configuration.suite_teardown
|
|
140
|
+
setup = parse_specification(configuration.setup) if configuration.setup
|
|
141
|
+
teardown = parse_specification(configuration.teardown) if configuration.teardown
|
|
142
|
+
return suite_setup, suite_teardown, setup, teardown
|
|
154
143
|
end
|
|
155
144
|
|
|
156
145
|
##
|
|
@@ -162,7 +151,7 @@ module Rutema
|
|
|
162
151
|
# * +suite_teardown+ - a test suite teardown Specification instance
|
|
163
152
|
def run_scenarios(specs, suite_setup, suite_teardown, setup, teardown)
|
|
164
153
|
if specs.empty?
|
|
165
|
-
error(nil,"No tests to run")
|
|
154
|
+
error(nil, "No tests to run")
|
|
166
155
|
else
|
|
167
156
|
@runner.setup = nil
|
|
168
157
|
@runner.teardown = nil
|
|
@@ -170,7 +159,7 @@ module Rutema
|
|
|
170
159
|
if !suite_setup || (run_test(suite_setup, true) == :success)
|
|
171
160
|
@runner.setup = setup
|
|
172
161
|
@runner.teardown = teardown
|
|
173
|
-
specs.each{|spec| run_test(spec)}
|
|
162
|
+
specs.each { |spec| run_test(spec) }
|
|
174
163
|
else
|
|
175
164
|
error(nil, "Suite setup test failed")
|
|
176
165
|
end
|
|
@@ -182,41 +171,40 @@ module Rutema
|
|
|
182
171
|
end
|
|
183
172
|
end
|
|
184
173
|
|
|
185
|
-
|
|
186
|
-
#
|
|
174
|
+
# rubocop:disable-next Style/OptionalBooleanParameter
|
|
187
175
|
def run_test(specification, is_special = false)
|
|
188
176
|
if specification.scenario
|
|
189
177
|
status = @runner.run(specification, is_special)["status"]
|
|
190
178
|
else
|
|
191
|
-
status
|
|
192
|
-
message(:test=>specification.name
|
|
179
|
+
status = :not_executed
|
|
180
|
+
message(:test => specification.name, :text => "No scenario", :status => status)
|
|
193
181
|
end
|
|
194
182
|
return status
|
|
195
183
|
end
|
|
196
184
|
|
|
197
|
-
##
|
|
198
185
|
# Instantiate a new class of a given type passing it a given configuration
|
|
199
186
|
# upon construction
|
|
200
187
|
#
|
|
201
188
|
# * +definition+ - class of which a new instance shall be instantiated
|
|
202
189
|
# * +configuration+ - Configuration instance which shall be passed to the
|
|
203
190
|
# initializer of the to be created instance
|
|
204
|
-
def instantiate_class
|
|
191
|
+
def instantiate_class(definition, configuration)
|
|
205
192
|
if definition[:class]
|
|
206
|
-
klass=definition[:class]
|
|
193
|
+
klass = definition[:class]
|
|
207
194
|
return klass.new(configuration)
|
|
208
195
|
end
|
|
209
196
|
return nil
|
|
210
197
|
end
|
|
211
198
|
|
|
199
|
+
# rubocop:disable Naming/PredicatePrefix
|
|
212
200
|
##
|
|
213
201
|
# Check if the given test identifier belongs to the normal test cases or to
|
|
214
202
|
# one of the special ones (the test (suite) setups and teardowns)
|
|
215
203
|
#
|
|
216
204
|
# * +test_identifier+ - the test identifier to check against membership in
|
|
217
205
|
# the normal or special test case identifier sets
|
|
218
|
-
def is_spec_included?
|
|
219
|
-
full_path=File.expand_path(test_identifier)
|
|
206
|
+
def is_spec_included?(test_identifier)
|
|
207
|
+
full_path = File.expand_path(test_identifier)
|
|
220
208
|
return @configuration.tests.include?(full_path) || is_special?(test_identifier)
|
|
221
209
|
end
|
|
222
210
|
|
|
@@ -228,23 +216,24 @@ module Rutema
|
|
|
228
216
|
#
|
|
229
217
|
# * +test_identifier+ - the test identifier which shall be checked for being
|
|
230
218
|
# a special one
|
|
231
|
-
def is_special?
|
|
232
|
-
full_path=File.expand_path(test_identifier)
|
|
233
|
-
return full_path
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
219
|
+
def is_special?(test_identifier)
|
|
220
|
+
full_path = File.expand_path(test_identifier)
|
|
221
|
+
return full_path == @configuration.suite_setup ||
|
|
222
|
+
full_path == @configuration.suite_teardown ||
|
|
223
|
+
full_path == @configuration.setup ||
|
|
224
|
+
full_path == @configuration.teardown
|
|
237
225
|
end
|
|
238
226
|
end
|
|
239
227
|
|
|
228
|
+
# rubocop:enable Naming/PredicatePrefix
|
|
240
229
|
##
|
|
241
|
-
# Class functioning as a
|
|
230
|
+
# Class functioning as a de-multiplexer between the Engine and the various
|
|
242
231
|
# Reporters instances
|
|
243
232
|
#
|
|
244
233
|
# In stream mode the incoming queue is popped periodically and the messages
|
|
245
234
|
# are distributed to the queues of any subscribed event reporters. By default
|
|
246
235
|
# this includes Reporters::Collector which is then used at the end of a run to
|
|
247
|
-
# provide the collected data to all registered block mode reporters
|
|
236
|
+
# provide the collected data to all registered block mode reporters
|
|
248
237
|
class Dispatcher
|
|
249
238
|
##
|
|
250
239
|
# The interval between queue operations
|
|
@@ -257,19 +246,19 @@ module Rutema
|
|
|
257
246
|
# * +queue+ - the queue which will be shared between the Engine instance and
|
|
258
247
|
# the Reporter instances
|
|
259
248
|
# * +configuration+ - the Configuration instance of the rutema run
|
|
260
|
-
def initialize
|
|
249
|
+
def initialize(queue, configuration)
|
|
261
250
|
@queue = queue
|
|
262
251
|
@queues = {}
|
|
263
|
-
@streaming_reporters=[]
|
|
264
|
-
@block_reporters=[]
|
|
265
|
-
@collector=Rutema::Reporters::Collector.new(nil,self)
|
|
252
|
+
@streaming_reporters = []
|
|
253
|
+
@block_reporters = []
|
|
254
|
+
@collector = Rutema::Reporters::Collector.new(nil, self)
|
|
266
255
|
if configuration.reporters
|
|
267
|
-
instances=configuration.reporters.values.map{|v| instantiate_reporter(v,configuration) if v[:class] != Reporters::Summary}.compact
|
|
268
|
-
@streaming_reporters,
|
|
269
|
-
@block_reporters,
|
|
256
|
+
instances = configuration.reporters.values.map { |v| instantiate_reporter(v, configuration) if v[:class] != Reporters::Summary }.compact
|
|
257
|
+
@streaming_reporters, = instances.partition { |rep| rep.respond_to?(:update) }
|
|
258
|
+
@block_reporters, = instances.partition { |rep| rep.respond_to?(:report) }
|
|
270
259
|
end
|
|
271
|
-
@streaming_reporters
|
|
272
|
-
@configuration=configuration
|
|
260
|
+
@streaming_reporters << @collector
|
|
261
|
+
@configuration = configuration
|
|
273
262
|
end
|
|
274
263
|
|
|
275
264
|
##
|
|
@@ -281,8 +270,8 @@ module Rutema
|
|
|
281
270
|
#
|
|
282
271
|
# * +identifier+ - a unique identifier for the queue. If two identifiers
|
|
283
272
|
# collide the new subscriber will replace the earlier one
|
|
284
|
-
def subscribe
|
|
285
|
-
@queues[identifier]=Queue.new
|
|
273
|
+
def subscribe(identifier)
|
|
274
|
+
@queues[identifier] = Queue.new
|
|
286
275
|
return @queues[identifier]
|
|
287
276
|
end
|
|
288
277
|
|
|
@@ -292,10 +281,10 @@ module Rutema
|
|
|
292
281
|
# incoming queue
|
|
293
282
|
def run!
|
|
294
283
|
puts "Running #{@streaming_reporters.size} streaming reporters" if $DEBUG
|
|
295
|
-
@streaming_reporters.each
|
|
296
|
-
@thread=Thread.new do
|
|
297
|
-
|
|
298
|
-
dispatch
|
|
284
|
+
@streaming_reporters.each(&:run!)
|
|
285
|
+
@thread = Thread.new do
|
|
286
|
+
loop do
|
|
287
|
+
dispatch
|
|
299
288
|
sleep INTERVAL
|
|
300
289
|
end
|
|
301
290
|
end
|
|
@@ -303,11 +292,11 @@ module Rutema
|
|
|
303
292
|
|
|
304
293
|
##
|
|
305
294
|
# Call all block reporters' BlockReporter#report method
|
|
306
|
-
def report
|
|
295
|
+
def report(specs)
|
|
307
296
|
@block_reporters.each do |r|
|
|
308
|
-
r.report(specs
|
|
297
|
+
r.report(specs, @collector.states, @collector.errors)
|
|
309
298
|
end
|
|
310
|
-
Reporters::Summary.new(@configuration,self).report(specs
|
|
299
|
+
Reporters::Summary.new(@configuration, self).report(specs, @collector.states, @collector.errors)
|
|
311
300
|
end
|
|
312
301
|
|
|
313
302
|
##
|
|
@@ -316,11 +305,11 @@ module Rutema
|
|
|
316
305
|
# dispatch thread
|
|
317
306
|
def exit
|
|
318
307
|
puts "Exiting main dispatcher" if $DEBUG
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
308
|
+
return unless @thread
|
|
309
|
+
|
|
310
|
+
flush
|
|
311
|
+
@streaming_reporters.each(&:exit)
|
|
312
|
+
Thread.kill(@thread)
|
|
324
313
|
end
|
|
325
314
|
|
|
326
315
|
private
|
|
@@ -330,11 +319,11 @@ module Rutema
|
|
|
330
319
|
# incoming queue is empty
|
|
331
320
|
def flush
|
|
332
321
|
puts "Flushing queues" if $DEBUG
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
322
|
+
return unless @thread
|
|
323
|
+
|
|
324
|
+
until @queue.empty?
|
|
325
|
+
dispatch
|
|
326
|
+
sleep INTERVAL
|
|
338
327
|
end
|
|
339
328
|
end
|
|
340
329
|
|
|
@@ -349,10 +338,10 @@ module Rutema
|
|
|
349
338
|
#
|
|
350
339
|
# This either returns the new class instance or _nil_ if the passed hash
|
|
351
340
|
# did not contain a key +:class+
|
|
352
|
-
def instantiate_reporter
|
|
341
|
+
def instantiate_reporter(definition, configuration)
|
|
353
342
|
if definition[:class]
|
|
354
|
-
klass=definition[:class]
|
|
355
|
-
return klass.new(configuration,self)
|
|
343
|
+
klass = definition[:class]
|
|
344
|
+
return klass.new(configuration, self)
|
|
356
345
|
end
|
|
357
346
|
return nil
|
|
358
347
|
end
|
|
@@ -362,10 +351,10 @@ module Rutema
|
|
|
362
351
|
# empty) and distribute it to all subscribed Reporters::EventReporter
|
|
363
352
|
# instances
|
|
364
353
|
def dispatch
|
|
365
|
-
if @queue.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
354
|
+
return if @queue.empty?
|
|
355
|
+
|
|
356
|
+
data = @queue.pop
|
|
357
|
+
@queues.each_value { |q| q.push(data) } if data
|
|
369
358
|
end
|
|
370
359
|
end
|
|
371
360
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright (c) 2021 Vassilis Rizopoulos. All rights reserved.
|
|
2
2
|
|
|
3
3
|
module Rutema
|
|
4
|
-
STATUS_CODES=[:started
|
|
4
|
+
STATUS_CODES = [:not_executed, :started, :skipped, :success, :warning, :error].freeze
|
|
5
5
|
|
|
6
6
|
##
|
|
7
7
|
# Simple base for classes concerned with message passing to report test
|
|
@@ -32,19 +32,19 @@ module Rutema
|
|
|
32
32
|
# * +:text+ - the text of the message
|
|
33
33
|
# * +:timestamp+ - most often the timestamp of the creation of the message,
|
|
34
34
|
# defaults to +Time.now+
|
|
35
|
-
def initialize
|
|
36
|
-
@test=params.fetch(:test,"")
|
|
37
|
-
@test||=""
|
|
38
|
-
@text=params.fetch(:text,"")
|
|
39
|
-
@timestamp=params.fetch(:timestamp,Time.now)
|
|
35
|
+
def initialize(params)
|
|
36
|
+
@test = params.fetch(:test, "")
|
|
37
|
+
@test ||= ""
|
|
38
|
+
@text = params.fetch(:text, "")
|
|
39
|
+
@timestamp = params.fetch(:timestamp, Time.now)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
##
|
|
43
43
|
# Convert the instance to a convenient textual representation
|
|
44
44
|
def to_s
|
|
45
|
-
msg=""
|
|
46
|
-
msg<<"#{@test} " unless @test.empty?
|
|
47
|
-
msg
|
|
45
|
+
msg = ""
|
|
46
|
+
msg << "#{@test} " unless @test.empty?
|
|
47
|
+
msg << @text
|
|
48
48
|
return msg
|
|
49
49
|
end
|
|
50
50
|
end
|
|
@@ -55,13 +55,13 @@ module Rutema
|
|
|
55
55
|
# The reported on errors may concern the test specifications, parser errors or
|
|
56
56
|
# errors which occurred during test execution. Logic errors of rutema itself
|
|
57
57
|
# are not reported by means of this class.
|
|
58
|
-
class ErrorMessage<Message
|
|
58
|
+
class ErrorMessage < Message
|
|
59
59
|
##
|
|
60
60
|
# Convert the instance to a convenient textual representation
|
|
61
61
|
def to_s
|
|
62
|
-
msg="ERROR - "
|
|
63
|
-
msg<<"#{@test} " unless @test.empty?
|
|
64
|
-
msg
|
|
62
|
+
msg = "ERROR - "
|
|
63
|
+
msg << "#{@test} " unless @test.empty?
|
|
64
|
+
msg << @text
|
|
65
65
|
return msg
|
|
66
66
|
end
|
|
67
67
|
end
|
|
@@ -73,7 +73,7 @@ module Rutema
|
|
|
73
73
|
# These messages inform about the progress of test execution. Test errors are
|
|
74
74
|
# propagated through instances of this class as well. If it's an engine error
|
|
75
75
|
# (e.g. during parsing), then an ErrorMessage will be used in that case.
|
|
76
|
-
class RunnerMessage<Message
|
|
76
|
+
class RunnerMessage < Message
|
|
77
77
|
attr_accessor :duration, :status, :number, :out, :err, :is_special
|
|
78
78
|
|
|
79
79
|
##
|
|
@@ -85,58 +85,58 @@ module Rutema
|
|
|
85
85
|
# * "status" - the status of the respective step
|
|
86
86
|
# * +:timestamp+ - most often the timestamp of the creation of the message,
|
|
87
87
|
# defaults to +Time.now+
|
|
88
|
-
def initialize
|
|
89
|
-
super
|
|
90
|
-
@duration=params.fetch("duration",0)
|
|
91
|
-
@status=params.fetch("status"
|
|
92
|
-
@number=params.fetch("number",1)
|
|
93
|
-
@out=params.fetch("out","")
|
|
94
|
-
@err=params.fetch("err","")
|
|
95
|
-
@backtrace=params.fetch("backtrace",
|
|
96
|
-
@is_special=params.fetch("is_special","")
|
|
88
|
+
def initialize(params)
|
|
89
|
+
super
|
|
90
|
+
@duration = params.fetch("duration", 0)
|
|
91
|
+
@status = params.fetch("status", :none)
|
|
92
|
+
@number = params.fetch("number", 1)
|
|
93
|
+
@out = params.fetch("out", "")
|
|
94
|
+
@err = params.fetch("err", "")
|
|
95
|
+
@backtrace = params.fetch("backtrace", [])
|
|
96
|
+
@is_special = params.fetch("is_special", "")
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
##
|
|
100
100
|
# Convert the instance to a convenient textual representation
|
|
101
101
|
def to_s
|
|
102
|
-
msg="#{@test}:"
|
|
103
|
-
msg<<" #{@timestamp.strftime("%H:%M:%S")} :"
|
|
104
|
-
msg<<"#{@text}." unless @text.empty?
|
|
105
|
-
outpt=output
|
|
106
|
-
msg<<" Output
|
|
102
|
+
msg = "#{@test}:"
|
|
103
|
+
msg << " #{@timestamp.strftime("%H:%M:%S")} :"
|
|
104
|
+
msg << "#{@text}." unless @text.empty?
|
|
105
|
+
outpt = output
|
|
106
|
+
msg << " Output:\n#{outpt}" unless outpt.empty? || @status != :error
|
|
107
107
|
return msg
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
def output
|
|
111
|
-
msg=""
|
|
112
|
-
msg<<"#{@out}\n" unless @out.empty?
|
|
113
|
-
msg
|
|
114
|
-
msg<<"\n
|
|
111
|
+
msg = ""
|
|
112
|
+
msg << "#{@out}\n" unless @out.empty?
|
|
113
|
+
msg << @err unless @err.empty?
|
|
114
|
+
msg << "\n#{@backtrace.is_a?(Array) ? @backtrace.join("\n") : @backtrace}" unless @backtrace.empty?
|
|
115
115
|
return msg.chomp
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
-
#While executing tests the state of each test is collected in an
|
|
120
|
-
#instance of ReportState and the collection is at the end passed to the available block reporters
|
|
119
|
+
# While executing tests the state of each test is collected in an
|
|
120
|
+
# instance of ReportState and the collection is at the end passed to the available block reporters
|
|
121
121
|
#
|
|
122
|
-
#ReportState assumes the timestamp of the first message, the status of the last message
|
|
123
|
-
#and accumulates the duration reported by all messages in it's collection.
|
|
122
|
+
# ReportState assumes the timestamp of the first message, the status of the last message
|
|
123
|
+
# and accumulates the duration reported by all messages in it's collection.
|
|
124
124
|
class ReportState
|
|
125
125
|
attr_accessor :steps
|
|
126
126
|
attr_reader :test, :timestamp, :duration, :status, :is_special
|
|
127
|
-
|
|
128
|
-
def initialize
|
|
129
|
-
@test=message.test
|
|
130
|
-
@timestamp=message.timestamp
|
|
131
|
-
@duration=message.duration
|
|
132
|
-
@status=message.status
|
|
133
|
-
@steps=[message]
|
|
134
|
-
@is_special=message.is_special
|
|
127
|
+
|
|
128
|
+
def initialize(message)
|
|
129
|
+
@test = message.test
|
|
130
|
+
@timestamp = message.timestamp
|
|
131
|
+
@duration = message.duration
|
|
132
|
+
@status = message.status
|
|
133
|
+
@steps = [message]
|
|
134
|
+
@is_special = message.is_special
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
def <<(message)
|
|
138
|
-
@steps<<message
|
|
139
|
-
@duration+=message.duration
|
|
138
|
+
@steps << message
|
|
139
|
+
@duration += message.duration
|
|
140
140
|
@status = message.status unless message.status.nil? \
|
|
141
141
|
|| (!@status.nil? && STATUS_CODES.find_index(message.status) < STATUS_CODES.find_index(@status))
|
|
142
142
|
end
|
|
@@ -153,8 +153,8 @@ module Rutema
|
|
|
153
153
|
# * +identifier+ - in most cases this would be the name of a test or its
|
|
154
154
|
# specification file
|
|
155
155
|
# * +message+ - a short descriptive message detailing the error condition
|
|
156
|
-
def error
|
|
157
|
-
@queue.push(ErrorMessage.new(:test=>identifier
|
|
156
|
+
def error(identifier, message)
|
|
157
|
+
@queue.push(ErrorMessage.new(:test => identifier, :text => message, :timestamp => Time.now))
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
##
|
|
@@ -164,14 +164,14 @@ module Rutema
|
|
|
164
164
|
# queue. If it's of type Hash it will be passed to the initializer of
|
|
165
165
|
# RunnerMessage if it has both the keys :test and "status" or to the
|
|
166
166
|
# initializer of Message if not so.
|
|
167
|
-
def message
|
|
167
|
+
def message(message)
|
|
168
168
|
case message
|
|
169
169
|
when String
|
|
170
|
-
@queue.push(Message.new(:text=>message
|
|
170
|
+
@queue.push(Message.new(:text => message, :timestamp => Time.now))
|
|
171
171
|
when Hash
|
|
172
|
-
hm=Message.new(message)
|
|
173
|
-
hm=RunnerMessage.new(message) if message[:test] && message["status"]
|
|
174
|
-
hm.timestamp=Time.now
|
|
172
|
+
hm = Message.new(message)
|
|
173
|
+
hm = RunnerMessage.new(message) if message[:test] && message["status"]
|
|
174
|
+
hm.timestamp = Time.now
|
|
175
175
|
@queue.push(hm)
|
|
176
176
|
end
|
|
177
177
|
end
|
|
@@ -185,7 +185,7 @@ module Rutema
|
|
|
185
185
|
# * ParserError
|
|
186
186
|
# * ReportError
|
|
187
187
|
# * RunnerError
|
|
188
|
-
class RutemaError<RuntimeError
|
|
188
|
+
class RutemaError < RuntimeError
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
##
|