rutema 1.3.0 → 2.0.0.pre
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 +7 -0
- data/History.txt +204 -194
- data/Manifest.txt +15 -48
- data/README.md +55 -61
- data/bin/rutema +7 -7
- data/lib/rutema/application.rb +61 -0
- data/lib/rutema/core/configuration.rb +195 -0
- data/lib/rutema/core/engine.rb +186 -0
- data/lib/rutema/core/framework.rb +28 -0
- data/lib/rutema/{objectmodel.rb → core/objectmodel.rb} +43 -48
- data/lib/rutema/core/parser.rb +35 -0
- data/lib/rutema/core/reporter.rb +105 -0
- data/lib/rutema/core/runner.rb +83 -0
- data/lib/rutema/elements/minimal.rb +47 -44
- data/lib/rutema/parsers/xml.rb +154 -186
- data/lib/rutema/version.rb +9 -0
- metadata +39 -108
- data/README.txt +0 -44
- data/Rakefile +0 -30
- data/examples/README.md +0 -17
- data/examples/config/database.rutema +0 -17
- data/examples/config/full.rutema +0 -27
- data/examples/config/minimal.rutema +0 -10
- data/examples/specs/T001.spec +0 -8
- data/examples/specs/T002.spec +0 -8
- data/examples/specs/T003.spec +0 -8
- data/examples/specs/T004.spec +0 -8
- data/examples/specs/T005.spec +0 -10
- data/examples/specs/T006.spec +0 -9
- data/examples/specs/check.spec +0 -8
- data/examples/specs/fail.spec +0 -9
- data/examples/specs/include.scenario +0 -5
- data/examples/specs/rutema.spec +0 -10
- data/examples/specs/setup.spec +0 -8
- data/examples/specs/teardown.spec +0 -8
- data/lib/rutema/configuration.rb +0 -173
- data/lib/rutema/models/activerecord.rb +0 -159
- data/lib/rutema/models/base.rb +0 -5
- data/lib/rutema/parsers/base.rb +0 -45
- data/lib/rutema/rake.rb +0 -62
- data/lib/rutema/reporters/activerecord.rb +0 -82
- data/lib/rutema/reporters/base.rb +0 -23
- data/lib/rutema/reporters/email.rb +0 -84
- data/lib/rutema/reporters/text.rb +0 -77
- data/lib/rutema/runners/default.rb +0 -157
- data/lib/rutema/runners/step.rb +0 -23
- data/lib/rutema/system.rb +0 -302
- data/test/data/duplicate_name.spec +0 -8
- data/test/data/no_title.spec +0 -5
- data/test/data/sample.spec +0 -8
- data/test/data/test_identifiers.rutema +0 -7
- data/test/test_activerecord.rb +0 -0
- data/test/test_configuration.rb +0 -43
- data/test/test_objectmodel.rb +0 -82
- data/test/test_parsers.rb +0 -131
- data/test/test_reporters.rb +0 -115
- data/test/test_runners.rb +0 -70
- data/test/test_system.rb +0 -45
@@ -1,77 +0,0 @@
|
|
1
|
-
# Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
|
2
|
-
|
3
|
-
module Rutema
|
4
|
-
#This reporter creates a simple text summary of a test run
|
5
|
-
#
|
6
|
-
#The following configuration keys are used by TextReporter:
|
7
|
-
#
|
8
|
-
#:verbose - when true, the report contains info on setup and teardown specs. Optional. Default is false
|
9
|
-
class TextReporter
|
10
|
-
def initialize params=nil
|
11
|
-
@verbose=params[:verbose] if params
|
12
|
-
@verbose||=false
|
13
|
-
end
|
14
|
-
#Returns the text summary
|
15
|
-
#
|
16
|
-
#runner_states is an Array of Patir::CommandSequenceStatus containing the stati of the last run (so it contains all the Scenario stati for the loaded tests)
|
17
|
-
#
|
18
|
-
#parse_errors is an Array of {:filename,:error} hashes containing the errors encountered by the parser when loading the specifications
|
19
|
-
def report specifications,runner_states,parse_errors,configuration
|
20
|
-
return text_report(specifications,runner_states,parse_errors)
|
21
|
-
end
|
22
|
-
private
|
23
|
-
def text_report specifications,runner_states,parse_errors
|
24
|
-
msg=""
|
25
|
-
#Report on parse errors
|
26
|
-
msg<<"No parse errors" if parse_errors.empty?
|
27
|
-
msg<<"One parse error:" if parse_errors.size==1
|
28
|
-
msg<<"#{parse_errors.size} parse errors:" if parse_errors.size>1
|
29
|
-
parse_errors.each do |er|
|
30
|
-
msg<<"\n\tin #{er[:filename]} : #{er[:error]}"
|
31
|
-
end
|
32
|
-
msg<<"\n---"
|
33
|
-
#Report on scenarios
|
34
|
-
runner_states.compact!#make sure no nil elements make it through
|
35
|
-
msg<<"\nNo scenarios in this run" if runner_states.empty?
|
36
|
-
if @verbose
|
37
|
-
states=runner_states
|
38
|
-
else
|
39
|
-
states=runner_states.select{|state| state.sequence_name !~ /[_setup|_teardown]$/}
|
40
|
-
end
|
41
|
-
msg<<"\nOne scenario in the current run" if states.size==1
|
42
|
-
msg<<"\n#{states.size} scenarios in the current run" if states.size>1
|
43
|
-
|
44
|
-
not_run = states.select{|state| state.status == :not_executed }.sort_by {|state| state.sequence_id.to_i}
|
45
|
-
errors = states.select{|state| state.status == :error }.sort_by {|state| state.sequence_id.to_i}
|
46
|
-
warnings = states.select{|state| state.status == :warning }.sort_by {|state| state.sequence_id.to_i}
|
47
|
-
successes = states.select{|state| state.status == :success }.sort_by {|state| state.sequence_id.to_i}
|
48
|
-
msg<<"\n#{errors.size} errors, #{warnings.size} warnings, #{successes.size} successes, #{not_run.size} not executed (setup failure)"
|
49
|
-
msg<<"\nErrors:" unless errors.empty?
|
50
|
-
msg<<scenario_summaries(errors,specifications)
|
51
|
-
msg<<"\nWarnings:" unless warnings.empty?
|
52
|
-
msg<<scenario_summaries(warnings,specifications)
|
53
|
-
msg<<"\nNot executed:" unless not_run.empty?
|
54
|
-
not_run.each do |state|
|
55
|
-
if specifications[state.sequence_name]
|
56
|
-
msg<<"\n#{specifications[state.sequence_name].title}"
|
57
|
-
else
|
58
|
-
msg<<"\n#{state.sequence_name}"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
msg<<"\nSuccesses:" unless successes.empty?
|
62
|
-
msg<<scenario_summaries(successes,specifications)
|
63
|
-
return msg
|
64
|
-
end
|
65
|
-
|
66
|
-
def scenario_summaries scenarios,specifications
|
67
|
-
msg=""
|
68
|
-
unless scenarios.empty?
|
69
|
-
scenarios.each do |state|
|
70
|
-
msg<<"\n#{specifications[state.sequence_name].title}" if specifications[state.sequence_name]
|
71
|
-
msg<<"\n#{state.summary}\n---"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
return msg
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,157 +0,0 @@
|
|
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
|
data/lib/rutema/runners/step.rb
DELETED
@@ -1,23 +0,0 @@
|
|
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
DELETED
@@ -1,302 +0,0 @@
|
|
1
|
-
# Copyright (c) 2007-2012 Vassilis Rizopoulos. All rights reserved.
|
2
|
-
$:.unshift File.join(File.dirname(__FILE__),"..")
|
3
|
-
require 'patir/command'
|
4
|
-
require 'patir/base'
|
5
|
-
require 'rutema/configuration'
|
6
|
-
|
7
|
-
require 'rutema/parsers/base'
|
8
|
-
|
9
|
-
require 'rutema/runners/default'
|
10
|
-
require 'rutema/runners/step'
|
11
|
-
|
12
|
-
require 'rutema/reporters/text'
|
13
|
-
|
14
|
-
module Rutema
|
15
|
-
#This module defines the version numbers for the library
|
16
|
-
module Version
|
17
|
-
MAJOR=1
|
18
|
-
MINOR=3
|
19
|
-
TINY=0
|
20
|
-
STRING=[ MAJOR, MINOR, TINY ].join( "." )
|
21
|
-
end
|
22
|
-
#This class coordinates parsing, execution and reporting of test specifications
|
23
|
-
class Coordinator
|
24
|
-
attr_accessor :configuration,:parse_errors,:parsed_files
|
25
|
-
attr_reader :test_states
|
26
|
-
def initialize configuration,logger=nil
|
27
|
-
@logger=logger
|
28
|
-
@logger||=Patir.setup_logger
|
29
|
-
@parse_errors=Array.new
|
30
|
-
@configuration=configuration
|
31
|
-
@parser=instantiate_class(@configuration.parser)
|
32
|
-
raise "Could not instantiate parser" unless @parser
|
33
|
-
@reporters=@configuration.reporters.collect{ |reporter| instantiate_class(reporter) }
|
34
|
-
@reporters.compact!
|
35
|
-
#this will hold any specifications that are succesfully parsed.
|
36
|
-
@specifications=Hash.new
|
37
|
-
@parsed_files=Array.new
|
38
|
-
@test_states=Hash.new
|
39
|
-
end
|
40
|
-
#Runs a set of tests
|
41
|
-
#
|
42
|
-
#mode can be :all, :attended, :unattended or a test filename
|
43
|
-
def run mode
|
44
|
-
@runner||=create_runner
|
45
|
-
@configuration.context[:start_time]=Time.now
|
46
|
-
@logger.info("Run started in mode '#{mode}'")
|
47
|
-
begin
|
48
|
-
case mode
|
49
|
-
when :all
|
50
|
-
@runner.attended=true
|
51
|
-
specs=parse_all_specifications
|
52
|
-
run_scenarios(specs)
|
53
|
-
when :attended
|
54
|
-
@runner.attended=true
|
55
|
-
specs=parse_all_specifications
|
56
|
-
run_scenarios(specs.select{|s| s.scenario && s.scenario.attended?})
|
57
|
-
when :unattended
|
58
|
-
specs=parse_all_specifications
|
59
|
-
run_scenarios(specs.select{|s| s.scenario && !s.scenario.attended?})
|
60
|
-
when String
|
61
|
-
@runner.attended=true
|
62
|
-
spec=parse_specification(mode)
|
63
|
-
run_test(spec) if spec
|
64
|
-
else
|
65
|
-
@logger.fatal("Don't know how to run '#{mode}'")
|
66
|
-
raise "Don't know how to run '#{mode}'"
|
67
|
-
end
|
68
|
-
rescue
|
69
|
-
@logger.debug($!)
|
70
|
-
@logger.fatal("Runner error: #{$!.message}")
|
71
|
-
raise
|
72
|
-
end
|
73
|
-
@configuration.context[:end_time]=Time.now
|
74
|
-
@logger.info("Run completed in #{@configuration.context[:end_time]-@configuration.context[:start_time]}s")
|
75
|
-
end
|
76
|
-
|
77
|
-
#Parses all specification files defined in the configuration
|
78
|
-
def parse_all_specifications
|
79
|
-
@configuration.tests.collect do |t|
|
80
|
-
begin
|
81
|
-
spec=parse_specification(t)
|
82
|
-
rescue
|
83
|
-
@logger.debug($!)
|
84
|
-
@logger.error($!.message)
|
85
|
-
end
|
86
|
-
end.compact
|
87
|
-
end
|
88
|
-
#Delegates reporting to all configured reporters spawning one thread per reporter
|
89
|
-
#
|
90
|
-
#It then joins the threads and returns when all of them are finished.
|
91
|
-
def report
|
92
|
-
#get the states from the runner
|
93
|
-
@runner.states.each do |k,v|
|
94
|
-
if v
|
95
|
-
@test_states[k]=v
|
96
|
-
else
|
97
|
-
@logger.warn("State for #{k} is nil")
|
98
|
-
end
|
99
|
-
end
|
100
|
-
threads=Array.new
|
101
|
-
#get the runner stati and the configuration and give it to the reporters
|
102
|
-
@reporters.each do |reporter|
|
103
|
-
threads<<Thread.new(reporter,@specifications,@test_states.values,@parse_errors,@configuration) do |reporter,specs,status,perrors,configuration|
|
104
|
-
begin
|
105
|
-
@logger.debug(reporter.report(specs,status,perrors,configuration))
|
106
|
-
rescue RuntimeError
|
107
|
-
@logger.error("Error in #{reporter.class}: #{$!.message}")
|
108
|
-
@logger.debug($!)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
threads.each do |t|
|
113
|
-
@logger.debug("Joining #{t}")
|
114
|
-
t.join
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
#returns true if all scenarios in the last run were succesful
|
119
|
-
def last_run_a_success?
|
120
|
-
return @runner.success?
|
121
|
-
end
|
122
|
-
def to_s#:nodoc:
|
123
|
-
"Parsed #{@parsed_files.size} files\n#{TextReporter.new.report(@specifications,@runner.states.values,@parse_errors,@configuration)}"
|
124
|
-
end
|
125
|
-
private
|
126
|
-
def instantiate_class definition
|
127
|
-
if definition[:class]
|
128
|
-
#add the logger to the definition
|
129
|
-
definition[:logger]=@logger
|
130
|
-
#add the configuration to the definition
|
131
|
-
definition[:configuration]=@configuration
|
132
|
-
klass=definition[:class]
|
133
|
-
return klass.new(definition)
|
134
|
-
end
|
135
|
-
return nil
|
136
|
-
end
|
137
|
-
|
138
|
-
def create_runner
|
139
|
-
setup=nil
|
140
|
-
teardown=nil
|
141
|
-
if @configuration.setup
|
142
|
-
@logger.info("Parsing setup specification from '#{@configuration.setup}'")
|
143
|
-
setup=@parser.parse_setup(@configuration.setup).scenario
|
144
|
-
end
|
145
|
-
if @configuration.teardown
|
146
|
-
@logger.info("Parsing teardown specification from '#{@configuration.teardown}'")
|
147
|
-
teardown=@parser.parse_teardown(@configuration.teardown).scenario
|
148
|
-
end
|
149
|
-
if @configuration.use_step_by_step
|
150
|
-
@logger.info("Using StepRunner")
|
151
|
-
return StepRunner.new(@configuration.context,setup,teardown,@logger)
|
152
|
-
else
|
153
|
-
return Runner.new(@configuration.context,setup,teardown,@logger)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def parse_specification spec_identifier
|
158
|
-
spec=nil
|
159
|
-
begin
|
160
|
-
@parsed_files<<spec_identifier
|
161
|
-
@parsed_files.uniq!
|
162
|
-
spec=@parser.parse_specification(spec_identifier)
|
163
|
-
if @specifications[spec.name]
|
164
|
-
msg="Duplicate specification name '#{spec.name}' in '#{spec_identifier}'"
|
165
|
-
@logger.error(msg)
|
166
|
-
@parse_errors<<{:filename=>spec_identifier,:error=>msg}
|
167
|
-
@test_states[spec.name]=Patir::CommandSequenceStatus.new(spec.name,[])
|
168
|
-
else
|
169
|
-
@specifications[spec.name]=spec
|
170
|
-
@test_states[spec.name]=Patir::CommandSequenceStatus.new(spec.name,spec.scenario.steps)
|
171
|
-
end
|
172
|
-
rescue ParserError
|
173
|
-
@logger.error("Error parsing '#{spec_identifier}': #{$!.message}")
|
174
|
-
@parse_errors<<{:filename=>spec_identifier,:error=>$!.message}
|
175
|
-
end
|
176
|
-
return spec
|
177
|
-
end
|
178
|
-
|
179
|
-
def run_scenarios specs
|
180
|
-
specs.compact!
|
181
|
-
if specs.empty?
|
182
|
-
@logger.error("No tests to run")
|
183
|
-
else
|
184
|
-
if @configuration.check
|
185
|
-
@logger.info("Parsing check test '#{@configuration.check}'")
|
186
|
-
spec=parse_specification(@configuration.check)
|
187
|
-
if spec
|
188
|
-
@logger.info("Running check test '#{spec.to_s}'")
|
189
|
-
if run_test(spec,false).success?
|
190
|
-
specs.each{|s| run_test(s)}
|
191
|
-
else
|
192
|
-
@logger.error("Check test failed")
|
193
|
-
end
|
194
|
-
else
|
195
|
-
@logger.error("Error parsing check test")
|
196
|
-
end
|
197
|
-
else
|
198
|
-
specs.each{|s| run_test(s)}
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def run_test specification,run_setup=true
|
204
|
-
@logger.info("Running #{specification.name} - #{specification.title}")
|
205
|
-
if specification.scenario
|
206
|
-
status=@runner.run(specification.name,specification.scenario,run_setup)
|
207
|
-
else
|
208
|
-
@logger.warn("#{specification.name} has no scenario")
|
209
|
-
status=:not_executed
|
210
|
-
end
|
211
|
-
@test_states[specification.name]=status
|
212
|
-
return status
|
213
|
-
end
|
214
|
-
end
|
215
|
-
#The "executioner" application class
|
216
|
-
#
|
217
|
-
#Parses the commandline, sets up the configuration and launches Cordinator
|
218
|
-
class RutemaX
|
219
|
-
require 'optparse'
|
220
|
-
def initialize command_line_args
|
221
|
-
parse_command_line(command_line_args)
|
222
|
-
@logger=Patir.setup_logger(@log_file)
|
223
|
-
@logger.info("rutema v#{Version::STRING}")
|
224
|
-
begin
|
225
|
-
raise "No configuration file defined!" if !@config_file
|
226
|
-
@configuration=RutemaConfigurator.new(@config_file,@logger).configuration
|
227
|
-
@configuration.context[:config_file]=File.basename(@config_file)
|
228
|
-
@configuration.use_step_by_step=@step
|
229
|
-
Dir.chdir(File.dirname(@config_file)) do
|
230
|
-
@coordinator=Coordinator.new(@configuration,@logger)
|
231
|
-
application_flow
|
232
|
-
end
|
233
|
-
rescue Patir::ConfigurationException
|
234
|
-
@logger.debug($!)
|
235
|
-
@logger.fatal("Configuration error '#{$!.message}'")
|
236
|
-
raise "Configuration error '#{$!.message}'"
|
237
|
-
rescue
|
238
|
-
@logger.debug($!)
|
239
|
-
@logger.fatal("#{$!.message}")
|
240
|
-
raise
|
241
|
-
end
|
242
|
-
end
|
243
|
-
private
|
244
|
-
def parse_command_line args
|
245
|
-
args.options do |opt|
|
246
|
-
opt.on("Options:")
|
247
|
-
opt.on("--debug", "-d","Turns on debug messages") { $DEBUG=true }
|
248
|
-
opt.on("--config FILE", "-c FILE",String,"Loads the configuration from FILE") { |config_file| @config_file=config_file}
|
249
|
-
opt.on("--log FILE", "-l FILE",String,"Redirects the log output to FILE") { |log_file| @log_file=logfile}
|
250
|
-
opt.on("--check","Runs just the check test"){@check=true}
|
251
|
-
opt.on("--step","Runs test cases step by step"){@step=true}
|
252
|
-
opt.on("-v", "--version","Displays the version") { $stdout.puts("rutema v#{Version::STRING}");exit 0 }
|
253
|
-
opt.on("--help", "-h", "-?", "This text") { $stdout.puts opt; exit 0 }
|
254
|
-
opt.on("The commands are:")
|
255
|
-
opt.on("\tall - Runs all tests")
|
256
|
-
opt.on("\tattended - Runs all attended tests")
|
257
|
-
opt.on("\tunattended - Runs all unattended tests")
|
258
|
-
opt.on("You can also provide a specification filename in order to run a single test")
|
259
|
-
opt.parse!
|
260
|
-
#and now the rest
|
261
|
-
if args.empty?
|
262
|
-
@mode=:unattended
|
263
|
-
else
|
264
|
-
command=args.shift
|
265
|
-
case command
|
266
|
-
when "attended"
|
267
|
-
@mode=:attended
|
268
|
-
when "all"
|
269
|
-
@mode=:all
|
270
|
-
when "unattended"
|
271
|
-
@mode=:unattended
|
272
|
-
else
|
273
|
-
@mode=command
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def application_flow
|
280
|
-
if @check
|
281
|
-
#run just the check test
|
282
|
-
if @configuration.check
|
283
|
-
@coordinator.run(@configuration.check)
|
284
|
-
else
|
285
|
-
@logger.fatal("There is no check test defined in the configuration.")
|
286
|
-
raise "There is no check test defined in the configuration."
|
287
|
-
end
|
288
|
-
else
|
289
|
-
#run everything
|
290
|
-
@coordinator.run(@mode)
|
291
|
-
end
|
292
|
-
@logger.info("Report:\n#{@coordinator.to_s}")
|
293
|
-
@coordinator.report
|
294
|
-
if @coordinator.parse_errors.empty? && @coordinator.last_run_a_success?
|
295
|
-
@logger.info("All tests successful")
|
296
|
-
else
|
297
|
-
@logger.warn("Not all tests were successful")
|
298
|
-
raise "Not all tests were successful"
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|