rutema 2.0.0.pre5 → 2.0.0.pre6

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.
@@ -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