rutema 2.0.1 → 2.0.2
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 +4 -2
- data/README.md +12 -12
- data/bin/rutema +4 -4
- data/lib/rutema/application.rb +34 -31
- data/lib/rutema/core/configuration.rb +123 -117
- data/lib/rutema/core/engine.rb +101 -113
- data/lib/rutema/core/framework.rb +54 -54
- data/lib/rutema/core/objectmodel.rb +101 -90
- data/lib/rutema/core/parser.rb +8 -8
- data/lib/rutema/core/reporter.rb +78 -68
- data/lib/rutema/core/runner.rb +116 -97
- data/lib/rutema/elements/minimal.rb +29 -25
- data/lib/rutema/parsers/xml.rb +100 -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 +7 -7
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,39 @@ module Rutema
|
|
|
182
171
|
end
|
|
183
172
|
end
|
|
184
173
|
|
|
185
|
-
##
|
|
186
|
-
#
|
|
187
174
|
def run_test(specification, is_special = false)
|
|
188
175
|
if specification.scenario
|
|
189
176
|
status = @runner.run(specification, is_special)["status"]
|
|
190
177
|
else
|
|
191
|
-
status
|
|
192
|
-
message(:test=>specification.name
|
|
178
|
+
status = :not_executed
|
|
179
|
+
message(:test => specification.name, :text => "No scenario", :status => status)
|
|
193
180
|
end
|
|
194
181
|
return status
|
|
195
182
|
end
|
|
196
183
|
|
|
197
|
-
##
|
|
198
184
|
# Instantiate a new class of a given type passing it a given configuration
|
|
199
185
|
# upon construction
|
|
200
186
|
#
|
|
201
187
|
# * +definition+ - class of which a new instance shall be instantiated
|
|
202
188
|
# * +configuration+ - Configuration instance which shall be passed to the
|
|
203
189
|
# initializer of the to be created instance
|
|
204
|
-
def instantiate_class
|
|
190
|
+
def instantiate_class(definition, configuration)
|
|
205
191
|
if definition[:class]
|
|
206
|
-
klass=definition[:class]
|
|
192
|
+
klass = definition[:class]
|
|
207
193
|
return klass.new(configuration)
|
|
208
194
|
end
|
|
209
195
|
return nil
|
|
210
196
|
end
|
|
211
197
|
|
|
198
|
+
# rubocop:disable Naming/PredicatePrefix
|
|
212
199
|
##
|
|
213
200
|
# Check if the given test identifier belongs to the normal test cases or to
|
|
214
201
|
# one of the special ones (the test (suite) setups and teardowns)
|
|
215
202
|
#
|
|
216
203
|
# * +test_identifier+ - the test identifier to check against membership in
|
|
217
204
|
# the normal or special test case identifier sets
|
|
218
|
-
def is_spec_included?
|
|
219
|
-
full_path=File.expand_path(test_identifier)
|
|
205
|
+
def is_spec_included?(test_identifier)
|
|
206
|
+
full_path = File.expand_path(test_identifier)
|
|
220
207
|
return @configuration.tests.include?(full_path) || is_special?(test_identifier)
|
|
221
208
|
end
|
|
222
209
|
|
|
@@ -228,23 +215,24 @@ module Rutema
|
|
|
228
215
|
#
|
|
229
216
|
# * +test_identifier+ - the test identifier which shall be checked for being
|
|
230
217
|
# a special one
|
|
231
|
-
def is_special?
|
|
232
|
-
full_path=File.expand_path(test_identifier)
|
|
233
|
-
return full_path
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
218
|
+
def is_special?(test_identifier)
|
|
219
|
+
full_path = File.expand_path(test_identifier)
|
|
220
|
+
return full_path == @configuration.suite_setup ||
|
|
221
|
+
full_path == @configuration.suite_teardown ||
|
|
222
|
+
full_path == @configuration.setup ||
|
|
223
|
+
full_path == @configuration.teardown
|
|
237
224
|
end
|
|
238
225
|
end
|
|
239
226
|
|
|
227
|
+
# rubocop:enable Naming/PredicatePrefix
|
|
240
228
|
##
|
|
241
|
-
# Class functioning as a
|
|
229
|
+
# Class functioning as a de-multiplexer between the Engine and the various
|
|
242
230
|
# Reporters instances
|
|
243
231
|
#
|
|
244
232
|
# In stream mode the incoming queue is popped periodically and the messages
|
|
245
233
|
# are distributed to the queues of any subscribed event reporters. By default
|
|
246
234
|
# 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
|
|
235
|
+
# provide the collected data to all registered block mode reporters
|
|
248
236
|
class Dispatcher
|
|
249
237
|
##
|
|
250
238
|
# The interval between queue operations
|
|
@@ -257,19 +245,19 @@ module Rutema
|
|
|
257
245
|
# * +queue+ - the queue which will be shared between the Engine instance and
|
|
258
246
|
# the Reporter instances
|
|
259
247
|
# * +configuration+ - the Configuration instance of the rutema run
|
|
260
|
-
def initialize
|
|
248
|
+
def initialize(queue, configuration)
|
|
261
249
|
@queue = queue
|
|
262
250
|
@queues = {}
|
|
263
|
-
@streaming_reporters=[]
|
|
264
|
-
@block_reporters=[]
|
|
265
|
-
@collector=Rutema::Reporters::Collector.new(nil,self)
|
|
251
|
+
@streaming_reporters = []
|
|
252
|
+
@block_reporters = []
|
|
253
|
+
@collector = Rutema::Reporters::Collector.new(nil, self)
|
|
266
254
|
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,
|
|
255
|
+
instances = configuration.reporters.values.map { |v| instantiate_reporter(v, configuration) if v[:class] != Reporters::Summary }.compact
|
|
256
|
+
@streaming_reporters, = instances.partition { |rep| rep.respond_to?(:update) }
|
|
257
|
+
@block_reporters, = instances.partition { |rep| rep.respond_to?(:report) }
|
|
270
258
|
end
|
|
271
|
-
@streaming_reporters
|
|
272
|
-
@configuration=configuration
|
|
259
|
+
@streaming_reporters << @collector
|
|
260
|
+
@configuration = configuration
|
|
273
261
|
end
|
|
274
262
|
|
|
275
263
|
##
|
|
@@ -281,8 +269,8 @@ module Rutema
|
|
|
281
269
|
#
|
|
282
270
|
# * +identifier+ - a unique identifier for the queue. If two identifiers
|
|
283
271
|
# collide the new subscriber will replace the earlier one
|
|
284
|
-
def subscribe
|
|
285
|
-
@queues[identifier]=Queue.new
|
|
272
|
+
def subscribe(identifier)
|
|
273
|
+
@queues[identifier] = Queue.new
|
|
286
274
|
return @queues[identifier]
|
|
287
275
|
end
|
|
288
276
|
|
|
@@ -292,10 +280,10 @@ module Rutema
|
|
|
292
280
|
# incoming queue
|
|
293
281
|
def run!
|
|
294
282
|
puts "Running #{@streaming_reporters.size} streaming reporters" if $DEBUG
|
|
295
|
-
@streaming_reporters.each
|
|
296
|
-
@thread=Thread.new do
|
|
297
|
-
|
|
298
|
-
dispatch
|
|
283
|
+
@streaming_reporters.each(&:run!)
|
|
284
|
+
@thread = Thread.new do
|
|
285
|
+
loop do
|
|
286
|
+
dispatch
|
|
299
287
|
sleep INTERVAL
|
|
300
288
|
end
|
|
301
289
|
end
|
|
@@ -303,11 +291,11 @@ module Rutema
|
|
|
303
291
|
|
|
304
292
|
##
|
|
305
293
|
# Call all block reporters' BlockReporter#report method
|
|
306
|
-
def report
|
|
294
|
+
def report(specs)
|
|
307
295
|
@block_reporters.each do |r|
|
|
308
|
-
r.report(specs
|
|
296
|
+
r.report(specs, @collector.states, @collector.errors)
|
|
309
297
|
end
|
|
310
|
-
Reporters::Summary.new(@configuration,self).report(specs
|
|
298
|
+
Reporters::Summary.new(@configuration, self).report(specs, @collector.states, @collector.errors)
|
|
311
299
|
end
|
|
312
300
|
|
|
313
301
|
##
|
|
@@ -316,11 +304,11 @@ module Rutema
|
|
|
316
304
|
# dispatch thread
|
|
317
305
|
def exit
|
|
318
306
|
puts "Exiting main dispatcher" if $DEBUG
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
307
|
+
return unless @thread
|
|
308
|
+
|
|
309
|
+
flush
|
|
310
|
+
@streaming_reporters.each(&:exit)
|
|
311
|
+
Thread.kill(@thread)
|
|
324
312
|
end
|
|
325
313
|
|
|
326
314
|
private
|
|
@@ -330,11 +318,11 @@ module Rutema
|
|
|
330
318
|
# incoming queue is empty
|
|
331
319
|
def flush
|
|
332
320
|
puts "Flushing queues" if $DEBUG
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
321
|
+
return unless @thread
|
|
322
|
+
|
|
323
|
+
until @queue.empty?
|
|
324
|
+
dispatch
|
|
325
|
+
sleep INTERVAL
|
|
338
326
|
end
|
|
339
327
|
end
|
|
340
328
|
|
|
@@ -349,10 +337,10 @@ module Rutema
|
|
|
349
337
|
#
|
|
350
338
|
# This either returns the new class instance or _nil_ if the passed hash
|
|
351
339
|
# did not contain a key +:class+
|
|
352
|
-
def instantiate_reporter
|
|
340
|
+
def instantiate_reporter(definition, configuration)
|
|
353
341
|
if definition[:class]
|
|
354
|
-
klass=definition[:class]
|
|
355
|
-
return klass.new(configuration,self)
|
|
342
|
+
klass = definition[:class]
|
|
343
|
+
return klass.new(configuration, self)
|
|
356
344
|
end
|
|
357
345
|
return nil
|
|
358
346
|
end
|
|
@@ -362,10 +350,10 @@ module Rutema
|
|
|
362
350
|
# empty) and distribute it to all subscribed Reporters::EventReporter
|
|
363
351
|
# instances
|
|
364
352
|
def dispatch
|
|
365
|
-
if @queue.
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
353
|
+
return if @queue.empty?
|
|
354
|
+
|
|
355
|
+
data = @queue.pop
|
|
356
|
+
@queues.each_value { |q| q.push(data) } if data
|
|
369
357
|
end
|
|
370
358
|
end
|
|
371
359
|
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
|
##
|