rutema 1.1.3 → 1.2.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.
Files changed (51) hide show
  1. data/.gemtest +0 -0
  2. data/History.txt +5 -0
  3. data/Manifest.txt +28 -23
  4. data/README.md +91 -0
  5. data/README.txt +2 -10
  6. data/Rakefile +6 -9
  7. data/bin/rutema +9 -0
  8. data/bin/rutemax +2 -0
  9. data/lib/rutema/configuration.rb +7 -8
  10. data/lib/rutema/elements/minimal.rb +45 -0
  11. data/lib/rutema/gems.rb +3 -3
  12. data/lib/rutema/models/activerecord.rb +164 -0
  13. data/lib/rutema/models/base.rb +5 -0
  14. data/lib/rutema/{specification.rb → objectmodel.rb} +4 -10
  15. data/lib/rutema/parsers/base.rb +29 -0
  16. data/lib/rutema/parsers/xml.rb +186 -0
  17. data/lib/rutema/reporters/activerecord.rb +9 -18
  18. data/lib/rutema/{reporter.rb → reporters/base.rb} +3 -7
  19. data/lib/rutema/reporters/email.rb +2 -5
  20. data/lib/rutema/reporters/text.rb +2 -2
  21. data/lib/rutema/reporters/yaml.rb +1 -2
  22. data/lib/rutema/runners/default.rb +157 -0
  23. data/lib/rutema/runners/step.rb +23 -0
  24. data/lib/rutema/system.rb +15 -420
  25. data/test/distro_test/config/full.rutema +2 -0
  26. data/test/distro_test/specs/check.spec +8 -0
  27. data/test/distro_test/specs/duplicate_name.spec +8 -0
  28. data/test/distro_test/specs/fail.spec +9 -0
  29. data/test/distro_test/specs/setup.spec +8 -0
  30. data/test/distro_test/specs/teardown.spec +8 -0
  31. data/test/rutema.rutema +1 -1
  32. data/test/rutema.spec +5 -5
  33. data/test/test_activerecord.rb +0 -0
  34. data/test/test_configuration.rb +7 -9
  35. data/test/test_couchdb.rb +14 -0
  36. data/test/{test_specification.rb → test_objectmodel.rb} +8 -11
  37. data/test/test_parsers.rb +136 -0
  38. data/test/test_rake.rb +2 -3
  39. data/test/{test_reporter.rb → test_reporters.rb} +0 -0
  40. data/test/test_runners.rb +72 -0
  41. data/test/test_system.rb +3 -166
  42. metadata +57 -62
  43. data/bin/rutema_upgrader +0 -81
  44. data/distro_test.sh +0 -6
  45. data/lib/rutema/model.rb +0 -231
  46. data/lib/rutema/reporters/couchdb.rb +0 -62
  47. data/lib/rutema/reporters/standard_reporters.rb +0 -7
  48. data/selftest.sh +0 -2
  49. data/test/data/sample09.db +0 -0
  50. data/test/migration.spec +0 -9
  51. data/test/test_model.rb +0 -62
@@ -0,0 +1,157 @@
1
+ # Copyright (c) 2007-2011 Vassilis Rizopoulos. All rights reserved.
2
+ $:.unshift File.join(File.dirname(__FILE__),'..','..')
3
+
4
+ module Rutema
5
+ #Runner executes TestScenario instances and maintains the state of all scenarios run.
6
+ class Runner
7
+ attr_reader :states,:number_of_runs,:context
8
+ attr_accessor :setup,:teardown
9
+ attr_writer :attended
10
+
11
+ #setup and teardown are TestScenario instances that will run before and after each call
12
+ #to the scenario.
13
+ def initialize context=nil,setup=nil, teardown=nil,logger=nil
14
+ @setup=setup
15
+ @teardown=teardown
16
+ @attended=false
17
+ @logger=logger
18
+ @logger||=Patir.setup_logger
19
+ @states=Hash.new
20
+ @number_of_runs=0
21
+ @context=context || Hash.new
22
+ end
23
+
24
+ #Tells you if the system runs in the mode that expects user input
25
+ def attended?
26
+ return @attended
27
+ end
28
+ #Runs a scenario and stores the result internally
29
+ #
30
+ #Returns the result of the run as a Patir::CommandSequenceStatus
31
+ def run name,scenario, run_setup=true
32
+ @logger.debug("Starting run for #{name} with #{scenario.inspect}")
33
+ @context[:scenario_name]=name
34
+ #if setup /teardown is defined we need to execute them before and after
35
+ if @setup && run_setup
36
+ @logger.info("Setup for #{name}")
37
+ @states["#{name}_setup"]=run_scenario("#{name}_setup",@setup)
38
+ @states["#{name}_setup"].sequence_id="s#{@number_of_runs}"
39
+ if @states["#{name}_setup"].executed?
40
+ #do not execute the scenario unless the setup was succesful
41
+ if @states["#{name}_setup"].success?
42
+ @logger.info("Scenario for #{name}")
43
+ @states[name]=run_scenario(name,scenario)
44
+ @states[name].sequence_id="#{@number_of_runs}"
45
+ else
46
+ @states[name]=initialize_state(name,scenario)
47
+ @states[name].sequence_id="#{@number_of_runs}"
48
+ end
49
+ end
50
+ else
51
+ @logger.info("Scenario for #{name}")
52
+ @states[name]=run_scenario(name,scenario)
53
+ @states[name].sequence_id="#{@number_of_runs}"
54
+ end
55
+ #no setup means no teardown
56
+ if @teardown && run_setup
57
+ #always execute teardown
58
+ @logger.warn("Teardown for #{name}")
59
+ @states["#{name}_teardown"]=run_scenario("#{name}_teardown",@teardown)
60
+ @states["#{name}_teardown"].sequence_id="#{@number_of_runs}t"
61
+ end
62
+ @number_of_runs+=1
63
+ @context[:scenario_name]=nil
64
+ return @states[name]
65
+ end
66
+
67
+ #Returns the state of the scenario with the given name.
68
+ #
69
+ #Will return nil if no scenario is found under that name.
70
+ def [](name)
71
+ return @states[name]
72
+ end
73
+
74
+ #Resets the Runner's internal state
75
+ def reset
76
+ @states.clear
77
+ @number_of_runs=0
78
+ end
79
+
80
+ #returns true if all the scenarios in the last run were succesful or if nothing was run yet
81
+ def success?
82
+ @success=true
83
+ @states.each do |k,v|
84
+ @success&=(v.status!=:error)
85
+ end
86
+ return @success
87
+ end
88
+ private
89
+ def run_scenario name,scenario
90
+ state=initialize_state(name,scenario)
91
+ begin
92
+ if evaluate_attention(scenario,state)
93
+ stps=scenario.steps
94
+ if stps.empty?
95
+ @logger.warn("Scenario #{name} contains no steps")
96
+ state.status=:warning
97
+ else
98
+ stps.each do |s|
99
+ state.step=run_step(s)
100
+ break if :error==state.status
101
+ end
102
+ end
103
+ end
104
+ rescue
105
+ @logger.error("Encountered error in #{name}: #{$!.message}")
106
+ @logger.debug($!)
107
+ state.status=:error
108
+ end
109
+ state.stop_time=Time.now
110
+ state.sequence_id=@number_of_runs
111
+ return state
112
+ end
113
+ def initialize_state name,scenario
114
+ state=Patir::CommandSequenceStatus.new(name,scenario.steps)
115
+ end
116
+ def evaluate_attention scenario,state
117
+ if scenario.attended?
118
+ if !self.attended?
119
+ @logger.warn("Attended scenario cannot be run in unattended mode")
120
+ state.status=:warning
121
+ return false
122
+ end
123
+ state.strategy=:attended
124
+ else
125
+ state.strategy=:unattended
126
+ end
127
+ return true
128
+ end
129
+ def run_step step
130
+ @logger.info("Running step #{step.number} - #{step.name}")
131
+ if step.has_cmd? && step.cmd.respond_to?(:run)
132
+ step.cmd.run(@context)
133
+ msg=step.to_s
134
+ if !step.cmd.success?
135
+ msg<<"\n#{step.cmd.output}" unless step.cmd.output.empty?
136
+ msg<<"\n#{step.cmd.error}" unless step.cmd.error.empty?
137
+ end
138
+ else
139
+ @logger.warn("No command associated with step '#{step.step_type}'. Step number is #{step.number}")
140
+ end
141
+ step.status=:success if step.status==:error && step.ignore?
142
+ log_step_result(step,msg)
143
+ return step
144
+ end
145
+ def log_step_result step,msg
146
+ if step.status==:error
147
+ if step.ignore?
148
+ @logger.warn("Step failed but result is being ignored!\n#{msg}")
149
+ else
150
+ @logger.error(msg)
151
+ end
152
+ else
153
+ @logger.info(msg) if msg && !msg.empty?
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2007-2011 Vassilis Rizopoulos. All rights reserved.
2
+ $:.unshift File.join(File.dirname(__FILE__),'..','..')
3
+
4
+ require 'rutema/runners/default'
5
+
6
+ module Rutema
7
+ #StepRunner halts before every step and asks if it should be executed or not.
8
+ class StepRunner<Runner
9
+ def initialize setup=nil, teardown=nil,logger=nil
10
+ @questioner=HighLine.new
11
+ super(setup,teardown,logger)
12
+ end
13
+ def run_step step
14
+ if @questioner.agree("Execute #{step.to_s}?")
15
+ return super(step)
16
+ else
17
+ msg="#{step.number} - #{step.step_type} - #{step.status}"
18
+ @logger.info(msg)
19
+ return step
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/rutema/system.rb CHANGED
@@ -4,259 +4,27 @@ require 'rexml/document'
4
4
  require 'patir/configuration'
5
5
  require 'patir/command'
6
6
  require 'patir/base'
7
- require 'rutema/specification'
8
7
  require 'rutema/configuration'
9
- require 'rutema/reporters/standard_reporters'
8
+
9
+ require 'rutema/parsers/base'
10
+ require 'rutema/parsers/xml'
11
+
12
+ require 'rutema/runners/default'
13
+ require 'rutema/runners/step'
14
+
15
+ require 'rutema/reporters/activerecord'
16
+ require 'rutema/reporters/text'
17
+ require 'rutema/reporters/yaml'
18
+ require 'rutema/reporters/email'
10
19
 
11
20
  module Rutema
12
21
  #This module defines the version numbers for the library
13
22
  module Version
14
23
  MAJOR=1
15
- MINOR=1
16
- TINY=3
24
+ MINOR=2
25
+ TINY=0
17
26
  STRING=[ MAJOR, MINOR, TINY ].join( "." )
18
27
  end
19
- #The Elements module provides the namespace for the various modules adding parser functionality
20
- module Elements
21
- #Minimal offers a minimal(chic) set of elements for use in specifications
22
- #
23
- #These are:
24
- # echo
25
- # command
26
- # prompt
27
- module Minimal
28
- #echo prints a message on the screen:
29
- # <echo text="A meaningful message"/>
30
- # <echo>A meaningful message</echo>
31
- def element_echo step
32
- step.cmd=Patir::RubyCommand.new("echo"){|cmd| cmd.error="";cmd.output="#{step.text}";$stdout.puts(cmd.output) ;:success}
33
- end
34
- #prompt asks the user a yes/no question. Answering yes means the step is succesful.
35
- # <prompt text="Do you want fries with that?"/>
36
- #
37
- #A prompt element automatically makes a specification "attended"
38
- def element_prompt step
39
- step.attended=true
40
- step.cmd=Patir::RubyCommand.new("prompt") do |cmd|
41
- cmd.output=""
42
- cmd.error=""
43
- if HighLine.new.agree("#{step.text}")
44
- step.output="y"
45
- else
46
- raise "n"
47
- end#if
48
- end#do rubycommand
49
- end
50
- #command executes a shell command
51
- # <command cmd="useful_command.exe with parameters", working_directory="some/directory"/>
52
- def element_command step
53
- raise ParserError,"missing required attribute cmd in #{step}" unless step.has_cmd?
54
- wd=Dir.pwd
55
- wd=step.working_directory if step.has_working_directory?
56
- step.cmd=Patir::ShellCommand.new(:cmd=>step.cmd,:working_directory=>File.expand_path(wd))
57
- end
58
- end
59
- end
60
- #Is raised when an error is found in a specification
61
- class ParserError<RuntimeError
62
- end
63
-
64
- #Base class that bombs out when used.
65
- #
66
- #Initialze expects a hash and as a base implementation assigns :logger as the internal logger.
67
- #
68
- #By default the internal logger will log to the console if no logger is provided.
69
- class SpecificationParser
70
- attr_reader :configuration
71
- def initialize params
72
- @logger=params[:logger]
73
- @logger||=Patir.setup_logger
74
- @configuration=params[:configuration]
75
- @logger.warn("No system configuration provided to the parser") unless @configuration
76
- end
77
-
78
- def parse_specification param
79
- raise ParserError,"not implemented. You should derive a parser implementation from SpecificationParser!"
80
- end
81
- end
82
-
83
- #BaseXMLParser encapsulates all the XML parsing code
84
- class BaseXMLParser<SpecificationParser
85
- ELEM_SPEC="specification"
86
- ELEM_DESC="specification/description"
87
- ELEM_TITLE="specification/title"
88
- ELEM_SCENARIO="specification/scenario"
89
- ELEM_REQ="requirement"
90
- #Parses __param__ and returns the Rutema::TestSpecification instance
91
- #
92
- #param can be the filename of the specification or the contents of that file.
93
- #
94
- #Will throw ParserError if something goes wrong
95
- def parse_specification param
96
- @logger.debug("Loading #{param}")
97
- begin
98
- if File.exists?(param)
99
- #read the file
100
- txt=File.read(param)
101
- filename=File.expand_path(param)
102
- else
103
- filename=Dir.pwd
104
- #try to parse the parameter
105
- txt=param
106
- end
107
- spec=parse_case(txt,filename)
108
- raise "Missing required attribute 'name' in specification element" unless spec.has_name? && !spec.name.empty?
109
- return spec
110
- rescue
111
- @logger.debug($!)
112
- raise ParserError,"Error loading #{param}: #{$!.message}"
113
- end
114
- end
115
-
116
- private
117
- #Parses the XML specification of a testcase and creates the corresponding TestSpecification instance
118
- def parse_case xmltxt,filename
119
- #the testspec to return
120
- spec=TestSpecification.new
121
- #read the test spec
122
- xmldoc=REXML::Document.new( xmltxt )
123
- #validate it
124
- validate_case(xmldoc)
125
- #parse it
126
- el=xmldoc.elements[ELEM_SPEC]
127
- xmldoc.root.attributes.each do |attr,value|
128
- add_attribute(spec,attr,value)
129
- end
130
- #get the title
131
- spec.title=xmldoc.elements[ELEM_TITLE].text
132
- spec.title||=""
133
- spec.title.strip!
134
- #get the description
135
- #strip line feeds, cariage returns and remove all tabs
136
- spec.description=xmldoc.elements[ELEM_DESC].text
137
- spec.description||=""
138
- begin
139
- spec.description.strip!
140
- spec.description.gsub!(/\t/,'')
141
- end unless spec.description.empty?
142
- #get the requirements
143
- reqs=el.elements.select{|e| e.name==ELEM_REQ}
144
- reqs.collect!{|r| r.attributes["name"]}
145
- spec.requirements=reqs
146
- #Get the scenario
147
- Dir.chdir(File.dirname(filename)) do
148
- spec.scenario=parse_scenario(xmldoc.elements[ELEM_SCENARIO].to_s) if xmldoc.elements[ELEM_SCENARIO]
149
- end
150
- spec.filename=filename
151
- return spec
152
- end
153
- #Validates the XML file from our point of view.
154
- #
155
- #Checks for the existence of ELEM_SPEC, ELEM_DESC and ELEM_TITLE and raises ParserError if they're missing.
156
- def validate_case xmldoc
157
- raise ParserError,"missing #{ELEM_SPEC} element" unless xmldoc.elements[ELEM_SPEC]
158
- raise ParserError,"missing #{ELEM_DESC} element" unless xmldoc.elements[ELEM_DESC]
159
- raise ParserError,"missing #{ELEM_TITLE} element" unless xmldoc.elements[ELEM_TITLE]
160
- end
161
-
162
- #Parses the scenario XML element and returns the Rutema::TestScenario instance
163
- def parse_scenario xmltxt
164
- @logger.debug("Parsing scenario from #{xmltxt}")
165
- scenario=Rutema::TestScenario.new
166
- xmldoc=REXML::Document.new( xmltxt )
167
- xmldoc.root.attributes.each do |attr,value|
168
- add_attribute(scenario,attr,value)
169
- end
170
- number=0
171
- xmldoc.root.elements.each do |el|
172
- step=parse_step(el.to_s)
173
- if step.step_type=="include_scenario"
174
- included_scenario=include_scenario(step)
175
- included_scenario.steps.each do |st|
176
- @logger.debug("Adding included step #{st}")
177
- number+=1
178
- st.number=number
179
- st.included_in=step.file
180
- scenario.add_step(st)
181
- end
182
- else
183
- number+=1
184
- step.number=number
185
- scenario.add_step(step)
186
- end
187
- end
188
- return scenario
189
- end
190
-
191
- #Parses xml and returns the Rutema::TestStep instance
192
- def parse_step xmltxt
193
- xmldoc=REXML::Document.new( xmltxt )
194
- #any step element
195
- step=Rutema::TestStep.new()
196
- step.ignore=false
197
- xmldoc.root.attributes.each do |attr,value|
198
- add_attribute(step,attr,value)
199
- end
200
- step.text=xmldoc.root.text.strip if xmldoc.root.text
201
- step.step_type=xmldoc.root.name
202
- return step
203
- end
204
-
205
- def add_attribute element,attr,value
206
- if boolean?(value)
207
- element.attribute(attr,eval(value))
208
- else
209
- element.attribute(attr,value)
210
- end
211
- end
212
-
213
- def boolean? attribute_value
214
- return true if attribute_value=="true" || attribute_value=="false"
215
- return false
216
- end
217
-
218
- #handles <include_scenario> elements, adding the steps to the current scenario
219
- def include_scenario step
220
- @logger.debug("Including file from #{step}")
221
- raise ParserError,"missing required attribute file in #{step}" unless step.has_file?
222
- raise ParserError,"Cannot find #{File.expand_path(step.file)}" unless File.exists?(File.expand_path(step.file))
223
- #Load the scenario
224
- step.file=File.expand_path(step.file)
225
- include_content=File.read(step.file)
226
- @logger.debug(include_content)
227
- return parse_scenario(include_content)
228
- end
229
- end
230
- #The ExtensibleXMLParser allows you to easily add methods to handle specification elements.
231
- #
232
- #A method element_foo(step) allows you to add behaviour for foo scenario elements.
233
- #
234
- #The method will receive a Rutema::TestStep instance.
235
- class ExtensibleXMLParser<BaseXMLParser
236
- def parse_specification param
237
- spec = super(param)
238
- #change into the directory the spec is in to handle relative paths correctly
239
- Dir.chdir(File.dirname(File.expand_path(spec.filename))) do |path|
240
- #iterate through the steps
241
- spec.scenario.steps.each do |step|
242
- #do we have a method to handle the element?
243
- if respond_to?(:"element_#{step.step_type}")
244
- begin
245
- self.send(:"element_#{step.step_type}",step)
246
- rescue
247
- raise ParserError, $!.message
248
- end
249
- end
250
- end
251
- end
252
- return spec
253
- end
254
- end
255
- #MinimalXMLParser offers three runnable steps in the scenarios as defined in Rutema::Elements::Minimal
256
- class MinimalXMLParser<ExtensibleXMLParser
257
- include Rutema::Elements::Minimal
258
- end
259
-
260
28
  #This class coordinates parsing, execution and reporting of test specifications
261
29
  class Coordinator
262
30
  attr_accessor :configuration,:parse_errors,:parsed_files
@@ -358,7 +126,7 @@ module Rutema
358
126
  def last_run_a_success?
359
127
  return @runner.success?
360
128
  end
361
- def to_s
129
+ def to_s#:nodoc:
362
130
  "Parsed #{@parsed_files.size} files\n#{TextReporter.new.report(@specifications,@runner.states.values,@parse_errors,@configuration)}"
363
131
  end
364
132
  private
@@ -457,178 +225,6 @@ module Rutema
457
225
  return status
458
226
  end
459
227
  end
460
-
461
- #Runner executes TestScenario instances and maintains the state of all scenarios run.
462
- class Runner
463
- attr_reader :states,:number_of_runs,:context
464
- attr_accessor :setup,:teardown
465
- attr_writer :attended
466
-
467
- #setup and teardown are TestScenario instances that will run before and after each call
468
- #to the scenario.
469
- def initialize context=nil,setup=nil, teardown=nil,logger=nil
470
- @setup=setup
471
- @teardown=teardown
472
- @attended=false
473
- @logger=logger
474
- @logger||=Patir.setup_logger
475
- @states=Hash.new
476
- @number_of_runs=0
477
- @context=context || Hash.new
478
- end
479
-
480
- #Tells you if the system runs in the mode that expects user input
481
- def attended?
482
- return @attended
483
- end
484
- #Runs a scenario and stores the result internally
485
- #
486
- #Returns the result of the run as a Patir::CommandSequenceStatus
487
- def run name,scenario, run_setup=true
488
- @logger.debug("Starting run for #{name} with #{scenario.inspect}")
489
- @context[:scenario_name]=name
490
- #if setup /teardown is defined we need to execute them before and after
491
- if @setup && run_setup
492
- @logger.info("Setup for #{name}")
493
- @states["#{name}_setup"]=run_scenario("#{name}_setup",@setup)
494
- @states["#{name}_setup"].sequence_id="s#{@number_of_runs}"
495
- if @states["#{name}_setup"].executed?
496
- #do not execute the scenario unless the setup was succesful
497
- if @states["#{name}_setup"].success?
498
- @logger.info("Scenario for #{name}")
499
- @states[name]=run_scenario(name,scenario)
500
- @states[name].sequence_id="#{@number_of_runs}"
501
- else
502
- @states[name]=initialize_state(name,scenario)
503
- @states[name].sequence_id="#{@number_of_runs}"
504
- end
505
- end
506
- else
507
- @logger.info("Scenario for #{name}")
508
- @states[name]=run_scenario(name,scenario)
509
- @states[name].sequence_id="#{@number_of_runs}"
510
- end
511
- #no setup means no teardown
512
- if @teardown && run_setup
513
- #always execute teardown
514
- @logger.warn("Teardown for #{name}")
515
- @states["#{name}_teardown"]=run_scenario("#{name}_teardown",@teardown)
516
- @states["#{name}_teardown"].sequence_id="#{@number_of_runs}t"
517
- end
518
- @number_of_runs+=1
519
- @context[:scenario_name]=nil
520
- return @states[name]
521
- end
522
-
523
- #Returns the state of the scenario with the given name.
524
- #
525
- #Will return nil if no scenario is found under that name.
526
- def [](name)
527
- return @states[name]
528
- end
529
-
530
- #Resets the Runner's internal state
531
- def reset
532
- @states.clear
533
- @number_of_runs=0
534
- end
535
-
536
- #returns true if all the scenarios in the last run were succesful or if nothing was run yet
537
- def success?
538
- @success=true
539
- @states.each do |k,v|
540
- @success&=(v.status!=:error)
541
- end
542
- return @success
543
- end
544
- private
545
- def run_scenario name,scenario
546
- state=initialize_state(name,scenario)
547
- begin
548
- if evaluate_attention(scenario,state)
549
- stps=scenario.steps
550
- if stps.empty?
551
- @logger.warn("Scenario #{name} contains no steps")
552
- state.status=:warning
553
- else
554
- stps.each do |s|
555
- state.step=run_step(s)
556
- break if :error==state.status
557
- end
558
- end
559
- end
560
- rescue
561
- @logger.error("Encountered error in #{name}: #{$!.message}")
562
- @logger.debug($!)
563
- state.status=:error
564
- end
565
- state.stop_time=Time.now
566
- state.sequence_id=@number_of_runs
567
- return state
568
- end
569
- def initialize_state name,scenario
570
- state=Patir::CommandSequenceStatus.new(name,scenario.steps)
571
- end
572
- def evaluate_attention scenario,state
573
- if scenario.attended?
574
- if !self.attended?
575
- @logger.warn("Attended scenario cannot be run in unattended mode")
576
- state.status=:warning
577
- return false
578
- end
579
- state.strategy=:attended
580
- else
581
- state.strategy=:unattended
582
- end
583
- return true
584
- end
585
- def run_step step
586
- @logger.info("Running step #{step.number} - #{step.name}")
587
- if step.has_cmd? && step.cmd.respond_to?(:run)
588
- step.cmd.run(@context)
589
- msg=step.to_s
590
- if !step.cmd.success?
591
- msg<<"\n#{step.cmd.output}" unless step.cmd.output.empty?
592
- msg<<"\n#{step.cmd.error}" unless step.cmd.error.empty?
593
- end
594
- else
595
- @logger.warn("No command associated with step '#{step.step_type}'. Step number is #{step.number}")
596
- end
597
- step.status=:success if step.status==:error && step.ignore?
598
- log_step_result(step,msg)
599
- return step
600
- end
601
- def log_step_result step,msg
602
- if step.status==:error
603
- if step.ignore?
604
- @logger.warn("Step failed but result is being ignored!\n#{msg}")
605
- else
606
- @logger.error(msg)
607
- end
608
- else
609
- @logger.info(msg) if msg && !msg.empty?
610
- end
611
- end
612
-
613
- end
614
-
615
- #StepRunner halts before every step and asks if it should be executed or not.
616
- class StepRunner<Runner
617
- def initialize context=nil,setup=nil, teardown=nil,logger=nil
618
- @questioner=HighLine.new
619
- super(context,setup,teardown,logger)
620
- end
621
- def run_step step
622
- if @questioner.agree("Execute #{step.to_s}?")
623
- return super(step)
624
- else
625
- msg="#{step.number} - #{step.step_type} - #{step.status}"
626
- @logger.info(msg)
627
- return step
628
- end
629
- end
630
- end
631
-
632
228
  #The "executioner" application class
633
229
  #
634
230
  #Parses the commandline, sets up the configuration and launches Cordinator
@@ -640,7 +236,7 @@ module Rutema
640
236
  @logger.info("rutemax v#{Version::STRING}")
641
237
  begin
642
238
  raise "No configuration file defined!" if !@config_file
643
- @configuration=RutemaXConfigurator.new(@config_file,@logger).configuration
239
+ @configuration=RutemaConfigurator.new(@config_file,@logger).configuration
644
240
  @configuration.context[:config_file]=File.basename(@config_file)
645
241
  @configuration.use_step_by_step=@step
646
242
  Dir.chdir(File.dirname(@config_file)) do
@@ -721,5 +317,4 @@ module Rutema
721
317
  end
722
318
  end
723
319
  end
724
-
725
320
  end