rutema 2.0.0.pre5 → 2.0.0.pre6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,129 +1,133 @@
1
- # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
- module Rutema
3
- #Rutema supports two kinds of reporters.
4
- #
5
- #Block (from en bloc) reporters receive data via the report() method at the end of a Rutema run
6
- #while event reporters receive events continuously during a run via the update() method
7
- #
8
- #Nothing prevents you from creating a class that implements both behaviours
9
- module Reporters
10
- class BlockReporter
11
- def initialize configuration,dispatcher
12
- @configuration=configuration
13
- end
14
- def report specifications,states,errors
15
- end
16
- end
17
- class EventReporter
18
- def initialize configuration,dispatcher
19
- @configuration=configuration
20
- @queue=dispatcher.subscribe(self.object_id)
21
- end
22
-
23
- def run!
24
- @thread=Thread.new do
25
- while true do
26
- if @queue.size>0
27
- data=@queue.pop
28
- update(data) if data
29
- end
30
- sleep 0.1
31
- end
32
- end
33
- end
34
-
35
- def update data
36
- end
37
-
38
- def exit
39
- if @thread
40
- while @queue.size>0 do
41
- sleep 0.1
42
- end
43
- Thread.kill(@thread)
44
- end
45
- end
46
- end
47
-
48
- class Collector<EventReporter
49
- attr_reader :errors,:states
50
- def initialize params,dispatcher
51
- super(params,dispatcher)
52
- @errors=[]
53
- @states={}
54
- end
55
-
56
- def update data
57
- if data[:error]
58
- @errors<<data
59
- elsif data[:test] && data['status']
60
- test_state=@states.fetch(data[:test],{})
61
- test_state["timestamp"]||=data[:timestamp]
62
- duration=test_state.fetch("duration",0)+data["duration"]
63
- test_state["duration"]=duration
64
- test_state["status"]= data["status"]
65
- steps=test_state.fetch("steps",[])
66
- steps<<data
67
- test_state["steps"]=steps
68
-
69
- @states[data[:test]]=test_state
70
- end
71
- end
72
- end
73
-
74
- class Console<EventReporter
75
- def initialize configuration,dispatcher
76
- super(configuration,dispatcher)
77
- @mode=configuration.reporters.fetch(self.class,{})["mode"]
78
- end
79
- def update data
80
- if data[:error]
81
- puts ">ERROR: #{data.fetch(:test,"")} #{data[:error]}" unless @mode=="off"
82
- elsif data[:test]
83
- if data["phase"]
84
- puts ">#{data["phase"]} #{data[:test]}" unless @mode=="silent" || @mode=="off"
85
- elsif data[:message]
86
- puts ">#{data[:test]} #{data[:message]}" unless @mode=="silent" || @mode=="off"
87
- elsif data["status"]==:error
88
- if @mode!="off"
89
- puts ">FATAL: #{data[:test]}(#{data["number"]}) failed"
90
- puts data.fetch("out","")
91
- puts data.fetch("err","")
92
- end
93
- end
94
- elsif data[:message]
95
- puts ">#{data[:message]}" unless @mode=="silent" || @mode=="off"
96
- end
97
- end
98
- end
99
-
100
- class Summary<BlockReporter
101
- def initialize configuration,dispatcher
102
- super(configuration,dispatcher)
103
- @silent=configuration.reporters.fetch(self.class,{})["silent"]
104
- end
105
- def report specs,states,errors
106
- failures=[]
107
- states.each do |k,v|
108
- failures<<k if v.fetch("steps",[]).last['status']==:error
109
- end
110
- unless @silent
111
- puts "#{errors.size} errors. #{states.size} test cases executed. #{failures.size} failed"
112
- unless failures.empty?
113
- puts "Failures:"
114
- puts specs.map{|spec| " #{spec.name} - #{spec.filename}" if failures.include?(spec.name)}.compact.join("\n")
115
- end
116
- end
117
- return failures.size+errors.size
118
- end
119
- end
120
- end
121
-
122
- module Utilities
123
- require "fileutils"
124
- def self.write_file filename,content
125
- FileUtils.mkdir_p(File.dirname(filename),:verbose=>false)
126
- File.open(filename, 'wb') {|f| f.write(content) }
127
- end
128
- end
129
- end
1
+ # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
+ module Rutema
3
+ #Rutema supports two kinds of reporters.
4
+ #
5
+ #Block (from en bloc) reporters receive data via the report() method at the end of a Rutema run
6
+ #while event reporters receive events continuously during a run via the update() method
7
+ #
8
+ #Nothing prevents you from creating a class that implements both behaviours
9
+ module Reporters
10
+ class BlockReporter
11
+ def initialize configuration,dispatcher
12
+ @configuration=configuration
13
+ end
14
+ def report specifications,states,errors
15
+ end
16
+ end
17
+ class EventReporter
18
+ def initialize configuration,dispatcher
19
+ @configuration=configuration
20
+ @queue=dispatcher.subscribe(self.object_id)
21
+ end
22
+
23
+ def run!
24
+ @thread=Thread.new do
25
+ while true do
26
+ if @queue.size>0
27
+ data=@queue.pop
28
+ begin
29
+ update(data) if data
30
+ rescue
31
+ puts "#{self.class} failed with #{$!.message}"
32
+ raise
33
+ end
34
+ end
35
+ sleep 0.1
36
+ end
37
+ end
38
+ end
39
+
40
+ def update data
41
+ end
42
+
43
+ def exit
44
+ puts "Exiting #{self.class}" if $DEBUG
45
+ if @thread
46
+ puts "Reporter died with #{@queue.size} messages in the queue" unless @thread.alive?
47
+ while @queue.size>0 && @thread.alive? do
48
+ sleep 0.1
49
+ end
50
+ Thread.kill(@thread)
51
+ end
52
+ end
53
+ end
54
+
55
+ class Collector<EventReporter
56
+ attr_reader :errors,:states
57
+ def initialize params,dispatcher
58
+ super(params,dispatcher)
59
+ @errors=[]
60
+ @states={}
61
+ end
62
+
63
+ def update message
64
+ case message
65
+ when RunnerMessage
66
+ test_state=@states.fetch(message.test,{})
67
+ test_state["timestamp"]||=message.timestamp
68
+ duration=test_state.fetch("duration",0)+message.duration
69
+ test_state["duration"]=duration
70
+ test_state["status"]= message.status
71
+ steps=test_state.fetch("steps",[])
72
+ steps<<message
73
+ test_state["steps"]=steps
74
+ @states[message.test]=test_state
75
+ when ErrorMessage
76
+ @errors<<message
77
+ end
78
+ end
79
+ end
80
+
81
+ class Console<EventReporter
82
+ def initialize configuration,dispatcher
83
+ super(configuration,dispatcher)
84
+ @mode=configuration.reporters.fetch(self.class,{})["mode"]
85
+ end
86
+ def update message
87
+ unless @mode=="off"
88
+ case message
89
+ when RunnerMessage
90
+ if message.status == :error
91
+ puts "FATAL|#{message.to_s}"
92
+ else
93
+ puts message.to_s if @mode=="verbose"
94
+ end
95
+ when ErrorMessage
96
+ puts message.to_s
97
+ when Message
98
+ puts message.to_s if @mode=="verbose"
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ class Summary<BlockReporter
105
+ def initialize configuration,dispatcher
106
+ super(configuration,dispatcher)
107
+ @silent=configuration.reporters.fetch(self.class,{})["silent"]
108
+ end
109
+ def report specs,states,errors
110
+ failures=[]
111
+ states.each do |k,v|
112
+ failures<<k if v.fetch("steps",[]).last.status==:error
113
+ end
114
+ unless @silent
115
+ puts "#{errors.size} errors. #{states.size} test cases executed. #{failures.size} failed"
116
+ unless failures.empty?
117
+ puts "Failures:"
118
+ puts specs.map{|spec| " #{spec.name} - #{spec.filename}" if failures.include?(spec.name)}.compact.join("\n")
119
+ end
120
+ end
121
+ return failures.size+errors.size
122
+ end
123
+ end
124
+ end
125
+
126
+ module Utilities
127
+ require "fileutils"
128
+ def self.write_file filename,content
129
+ FileUtils.mkdir_p(File.dirname(filename),:verbose=>false)
130
+ File.open(filename, 'wb') {|f| f.write(content) }
131
+ end
132
+ end
133
+ end
@@ -1,84 +1,94 @@
1
- # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
-
3
- require_relative "framework"
4
-
5
- module Rutema
6
- module Runners
7
- class Default
8
- include Rutema::Messaging
9
- attr_reader :context
10
- attr_accessor :setup,:teardown
11
- def initialize context,queue
12
- @setup=nil
13
- @teardown=nil
14
- @context=context || Hash.new
15
- @queue = queue
16
- @number_of_runs=0
17
- end
18
-
19
- def run spec
20
- steps=[]
21
- status=:success
22
- state={'start_time'=>Time.now, "sequence_id"=>@number_of_runs,:test=>spec.name}
23
- message(:test=>spec.name,'phase'=>'started')
24
- if @setup
25
- message(:test=>spec.name,'phase'=>'setup')
26
- executed_steps,status=run_scenario("_setup_",@setup.scenario,@context)
27
- steps+=executed_steps
28
- end
29
- if status!=:error
30
- message(:test=>spec.name,'phase'=>'running')
31
- executed_steps,status=run_scenario(spec.name,spec.scenario,@context)
32
- steps+=executed_steps
33
- else
34
- message(:test=>spec.name,'number'=>0,'status'=>:error,'out'=>"Setup failed",'err'=>"",'duration'=>0)
35
- end
36
- state['status']=status
37
- if @teardown
38
- message(:test=>spec.name,'phase'=>'teardown')
39
- executed_steps,status=run_scenario("_teardown_",@teardown.scenario,@context)
40
- end
41
- message(:test=>spec.name,'phase'=>'finished')
42
- state["stop_time"]=Time.now
43
- state['steps']=steps
44
- @number_of_runs+=1
45
- return state
46
- end
47
-
48
- private
49
- def run_scenario name,scenario,meta
50
- executed_steps=[]
51
- status=:warning
52
- begin
53
- stps=scenario.steps
54
- if stps.empty?
55
- error(name,"Scenario #{name} contains no steps")
56
- status=:error
57
- else
58
- stps.each do |s|
59
- message(:test=>name,:message=>s.to_s)
60
- executed_steps<<run_step(s,meta)
61
- message(:test=>name,'number'=>s.number,'status'=>s.status,'out'=>s.output,'err'=>s.error,'duration'=>s.exec_time)
62
- status=s.status
63
- break if :error==s.status
64
- end
65
- end
66
- rescue
67
- error(name,$!.message)
68
- status=:error
69
- end
70
- return executed_steps,status
71
- end
72
- def run_step step,meta
73
- if step.has_cmd? && step.cmd.respond_to?(:run)
74
- step.cmd.run(meta)
75
- else
76
- message("No command associated with step '#{step.step_type}'. Step number is #{step.number}")
77
- step.status=:warning
78
- end
79
- step.status=:success if step.ignore?
80
- return step
81
- end
82
- end
83
- end
1
+ # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
+
3
+ require_relative "framework"
4
+
5
+ module Rutema
6
+ module Runners
7
+ class Default
8
+ include Rutema::Messaging
9
+ attr_reader :context
10
+ attr_accessor :setup,:teardown
11
+ def initialize context,queue
12
+ @setup=nil
13
+ @teardown=nil
14
+ @context=context || Hash.new
15
+ @queue = queue
16
+ @number_of_runs=0
17
+ end
18
+
19
+ def run spec
20
+ steps=[]
21
+ status=:success
22
+ state={'start_time'=>Time.now, "sequence_id"=>@number_of_runs,:test=>spec.name}
23
+ message(:test=>spec.name,:text=>'started')
24
+ if @setup
25
+ message(:test=>spec.name,:text=>'setup')
26
+ executed_steps,status=run_scenario("_setup_",@setup.scenario,@context)
27
+ steps+=executed_steps
28
+ end
29
+ if status!=:error
30
+ message(:test=>spec.name,:text=>'running')
31
+ executed_steps,status=run_scenario(spec.name,spec.scenario,@context)
32
+ steps+=executed_steps
33
+ else
34
+ message(:test=>spec.name,'number'=>0,'status'=>:error,'out'=>"Setup failed",'err'=>"",'duration'=>0)
35
+ end
36
+ state['status']=status
37
+ if @teardown
38
+ message(:test=>spec.name,:text=>'teardown')
39
+ executed_steps,status=run_scenario("_teardown_",@teardown.scenario,@context)
40
+ end
41
+ message(:test=>spec.name,:text=>'finished')
42
+ state["stop_time"]=Time.now
43
+ state['steps']=steps
44
+ @number_of_runs+=1
45
+ return state
46
+ end
47
+
48
+ private
49
+ def run_scenario name,scenario,meta
50
+ executed_steps=[]
51
+ status=:warning
52
+ begin
53
+ stps=scenario.steps
54
+ if stps.empty?
55
+ error(name,"Scenario #{name} contains no steps")
56
+ status=:error
57
+ else
58
+ stps.each do |s|
59
+ executed_steps<<run_step(s,meta)
60
+ message(:test=>name,:text=>s.to_s,'number'=>s.number,'status'=>s.status,'out'=>s.output,'err'=>s.error,'duration'=>s.exec_time)
61
+ status=s.status
62
+ break if :error==s.status
63
+ end
64
+ end
65
+ rescue
66
+ error(name,$!.message)
67
+ status=:error
68
+ end
69
+ return executed_steps,status
70
+ end
71
+ def run_step step,meta
72
+ if step.has_cmd? && step.cmd.respond_to?(:run)
73
+ step.cmd.run(meta)
74
+ else
75
+ message("No command associated with step '#{step.step_type}'. Step number is #{step.number}")
76
+ step.status=:warning
77
+ end
78
+ step.status=:success if step.ignore?
79
+ return step
80
+ end
81
+ end
82
+
83
+ class NoOp<Default
84
+ def run_step step,meta
85
+ unless step.has_cmd? && step.cmd.respond_to?(:run)
86
+ message("No command associated with step '#{step.step_type}'. Step number is #{step.number}")
87
+ step.status=:warning
88
+ end
89
+ step.status=:success if step.ignore?
90
+ return step
91
+ end
92
+ end
93
+ end
84
94
  end
@@ -1,48 +1,48 @@
1
- # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
- require 'highline'
3
- module Rutema
4
- #The Elements module provides the namespace for the various modules adding parser functionality
5
- module Elements
6
- #Minimal offers a minimal(chic) set of elements for use in specifications
7
- #
8
- #These are:
9
- # echo
10
- # command
11
- # prompt
12
- module Minimal
13
- #echo prints a message on the screen:
14
- # <echo text="A meaningful message"/>
15
- # <echo>A meaningful message</echo>
16
- def element_echo step
17
- step.cmd=Patir::RubyCommand.new("echo"){|cmd| cmd.error="";cmd.output="#{step.text}";$stdout.puts(cmd.output) ;:success}
18
- return step
19
- end
20
- #prompt asks the user a yes/no question. Answering yes means the step is succesful.
21
- # <prompt text="Do you want fries with that?"/>
22
- #
23
- #A prompt element automatically makes a specification "attended"
24
- def element_prompt step
25
- step.attended=true
26
- step.cmd=Patir::RubyCommand.new("prompt") do |cmd|
27
- cmd.output=""
28
- cmd.error=""
29
- if HighLine.new.agree("#{step.text}")
30
- step.output="y"
31
- else
32
- raise "n"
33
- end#if
34
- end#do rubycommand
35
- return step
36
- end
37
- #command executes a shell command
38
- # <command cmd="useful_command.exe with parameters", working_directory="some/directory"/>
39
- def element_command step
40
- raise ParserError,"missing required attribute cmd in #{step}" unless step.has_cmd?
41
- wd=Dir.pwd
42
- wd=step.working_directory if step.has_working_directory?
43
- step.cmd=Patir::ShellCommand.new(:cmd=>step.cmd,:working_directory=>File.expand_path(wd))
44
- return step
45
- end
46
- end
47
- end
1
+ # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
+ require 'highline'
3
+ module Rutema
4
+ #The Elements module provides the namespace for the various modules adding parser functionality
5
+ module Elements
6
+ #Minimal offers a minimal(chic) set of elements for use in specifications
7
+ #
8
+ #These are:
9
+ # echo
10
+ # command
11
+ # prompt
12
+ module Minimal
13
+ #echo prints a message on the screen:
14
+ # <echo text="A meaningful message"/>
15
+ # <echo>A meaningful message</echo>
16
+ def element_echo step
17
+ step.cmd=Patir::RubyCommand.new("echo"){|cmd| cmd.error="";cmd.output="#{step.text}";$stdout.puts(cmd.output) ;:success}
18
+ return step
19
+ end
20
+ #prompt asks the user a yes/no question. Answering yes means the step is succesful.
21
+ # <prompt text="Do you want fries with that?"/>
22
+ #
23
+ #A prompt element automatically makes a specification "attended"
24
+ def element_prompt step
25
+ step.attended=true
26
+ step.cmd=Patir::RubyCommand.new("prompt") do |cmd|
27
+ cmd.output=""
28
+ cmd.error=""
29
+ if HighLine.new.agree("#{step.text}")
30
+ step.output="y"
31
+ else
32
+ raise "n"
33
+ end#if
34
+ end#do rubycommand
35
+ return step
36
+ end
37
+ #command executes a shell command
38
+ # <command cmd="useful_command.exe with parameters", working_directory="some/directory"/>
39
+ def element_command step
40
+ raise ParserError,"missing required attribute cmd in #{step}" unless step.has_cmd?
41
+ wd=Dir.pwd
42
+ wd=step.working_directory if step.has_working_directory?
43
+ step.cmd=Patir::ShellCommand.new(:cmd=>step.cmd,:working_directory=>File.expand_path(wd))
44
+ return step
45
+ end
46
+ end
47
+ end
48
48
  end