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,154 +1,156 @@
1
- # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
- require 'rexml/document'
3
- require 'patir/command'
4
- require_relative '../core/parser'
5
- require_relative '../core/objectmodel'
6
- require_relative '../elements/minimal'
7
-
8
- module Rutema
9
- module Parsers
10
- #Rutema::Parsers::XML is a basic XML parser that is easily extended
11
- #
12
- #Derive your parser from this class and define for each element 'foo' that you want to parse
13
- #a method element_foo(step)
14
- #
15
- #The method will receive a Rutema::Step instance as a parameter which it should return
16
- class XML<SpecificationParser
17
- include Rutema::Elements::Minimal
18
- #:nodoc:
19
- ELEM_SPEC="specification"
20
- #:nodoc:
21
- ELEM_DESC="specification/description"
22
- #:nodoc:
23
- ELEM_TITLE="specification/title"
24
- #:nodoc:
25
- ELEM_SCENARIO="specification/scenario"
26
- #Parses __param__ and returns the Rutema::Specification instance
27
- #
28
- #param can be the filename of the specification or the contents of that file.
29
- #
30
- #Will throw Rutema::ParserError if something goes wrong
31
- def parse_specification param
32
- @parsed||=[]
33
- begin
34
- if File.exist?(param)
35
- txt=File.read(param)
36
- filename=File.expand_path(param)
37
- else
38
- txt=param
39
- filename=Dir.pwd
40
- end
41
- spec=parse_case(txt,filename)
42
- raise Rutema::ParserError,"Missing required attribute 'name' in specification element" unless spec.has_name? && !spec.name.empty?
43
- raise Rutema::ParserError,"Duplicate test name '#{spec.name}' in #{filename}" if @parsed.include?(spec.name)
44
- @parsed<<spec.name
45
- extension_handling(spec)
46
- end
47
- end
48
- private
49
- #Parses the XML specification of a testcase and creates the corresponding Rutema::Specification instance
50
- def parse_case xmltxt,filename
51
- spec=Rutema::Specification.new({})
52
- xmldoc=REXML::Document.new( xmltxt )
53
- validate_case(xmldoc)
54
- xmldoc.root.attributes.each do |attr,value|
55
- add_attribute(spec,attr,value)
56
- end
57
- spec.title=xmldoc.elements[ELEM_TITLE].text
58
- spec.title||=""
59
- spec.title.strip!
60
- spec.description=xmldoc.elements[ELEM_DESC].text
61
- spec.description||=""
62
- unless spec.description.empty?
63
- spec.description.strip!
64
- spec.description.gsub!(/\t/,'')
65
- end
66
- Dir.chdir(File.dirname(filename)) do
67
- spec.scenario=parse_scenario(xmldoc.elements[ELEM_SCENARIO].to_s) if xmldoc.elements[ELEM_SCENARIO]
68
- end
69
- spec.filename=filename
70
- return spec
71
- end
72
- #Validates the XML file from our point of view.
73
- def validate_case xmldoc
74
- raise Rutema::ParserError,"missing #{ELEM_SPEC} element in #{xmldoc}" unless xmldoc.elements[ELEM_SPEC]
75
- raise Rutema::ParserError,"missing #{ELEM_DESC} element in #{xmldoc}" unless xmldoc.elements[ELEM_DESC]
76
- raise Rutema::ParserError,"missing #{ELEM_TITLE} element in #{xmldoc}" unless xmldoc.elements[ELEM_TITLE]
77
- end
78
- #Parses the 'scenario' XML element and returns the Rutema::Scenario instance
79
- def parse_scenario xmltxt
80
- scenario=Rutema::Scenario.new([])
81
- xmldoc=REXML::Document.new( xmltxt )
82
- xmldoc.root.attributes.each do |attr,value|
83
- add_attribute(scenario,attr,value)
84
- end
85
- number=0
86
- xmldoc.root.elements.each do |el|
87
- step=parse_step(el.to_s)
88
- if step.step_type=="include_scenario"
89
- included_scenario=include_scenario(step)
90
- included_scenario.steps.each do |st|
91
- number+=1
92
- st.number=number
93
- st.included_in=step.file
94
- scenario.add_step(st)
95
- end
96
- else
97
- number+=1
98
- step.number=number
99
- scenario.add_step(step)
100
- end
101
- end
102
- return scenario
103
- end
104
- #Parses xml and returns the Rutema::Step instance
105
- def parse_step xmltxt
106
- xmldoc=REXML::Document.new( xmltxt )
107
- #any step element
108
- step=Rutema::Step.new()
109
- step.ignore=false
110
- xmldoc.root.attributes.each do |attr,value|
111
- add_attribute(step,attr,value)
112
- end
113
- step.text=xmldoc.root.text.strip if xmldoc.root.text
114
- step.step_type=xmldoc.root.name
115
- return step
116
- end
117
- def add_attribute element,attr,value
118
- if boolean?(value)
119
- element.attribute(attr,eval(value))
120
- else
121
- element.attribute(attr,value)
122
- end
123
- end
124
- def boolean? attribute_value
125
- return true if attribute_value=="true" || attribute_value=="false"
126
- return false
127
- end
128
- #handles <include_scenario> elements, adding the steps to the current scenario
129
- def include_scenario step
130
- raise Rutema::ParserError,"missing required attribute file in #{step}" unless step.has_file?
131
- raise Rutema::ParserError,"Cannot find #{File.expand_path(step.file)}" unless File.exist?(File.expand_path(step.file))
132
- step.file=File.expand_path(step.file)
133
- include_content=File.read(step.file)
134
- return parse_scenario(include_content)
135
- end
136
- def extension_handling spec
137
- #change into the directory the spec is in to handle relative paths correctly
138
- Dir.chdir(File.dirname(File.expand_path(spec.filename))) do |path|
139
- spec.scenario.steps.each do |step|
140
- #do we have a method to handle the element?
141
- if respond_to?(:"element_#{step.step_type}")
142
- begin
143
- self.send(:"element_#{step.step_type}",step)
144
- rescue
145
- raise ParserError, $!.message
146
- end
147
- end#begin
148
- end#each
149
- end#chdir
150
- return spec
151
- end
152
- end
153
- end
154
- end
1
+ # Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
2
+ require 'rexml/document'
3
+ require 'patir/command'
4
+ require_relative '../core/parser'
5
+ require_relative '../core/objectmodel'
6
+ require_relative '../elements/minimal'
7
+
8
+ module Rutema
9
+ module Parsers
10
+ #Rutema::Parsers::XML is a basic XML parser that is easily extended
11
+ #
12
+ #Derive your parser from this class and define for each element 'foo' that you want to parse
13
+ #a method element_foo(step)
14
+ #
15
+ #The method will receive a Rutema::Step instance as a parameter which it should return
16
+ class XML<SpecificationParser
17
+ include Rutema::Elements::Minimal
18
+ #:nodoc:
19
+ ELEM_SPEC="specification"
20
+ #:nodoc:
21
+ ELEM_DESC="specification/description"
22
+ #:nodoc:
23
+ ELEM_TITLE="specification/title"
24
+ #:nodoc:
25
+ ELEM_SCENARIO="specification/scenario"
26
+ #Parses __param__ and returns the Rutema::Specification instance
27
+ #
28
+ #param can be the filename of the specification or the contents of that file.
29
+ #
30
+ #Will throw Rutema::ParserError if something goes wrong
31
+ def parse_specification param
32
+ @parsed||=[]
33
+ begin
34
+ if File.exist?(param)
35
+ txt=File.read(param)
36
+ filename=File.expand_path(param)
37
+ else
38
+ txt=param
39
+ filename=Dir.pwd
40
+ end
41
+ spec=parse_case(txt,filename)
42
+ raise Rutema::ParserError,"Missing required attribute 'name' in specification element" unless spec.has_name? && !spec.name.empty?
43
+ raise Rutema::ParserError,"Duplicate test name '#{spec.name}' in #{filename}" if @parsed.include?(spec.name)
44
+ @parsed<<spec.name
45
+ extension_handling(spec)
46
+ rescue REXML::ParseException
47
+ raise Rutema::ParserError,$!.message
48
+ end
49
+ end
50
+ private
51
+ #Parses the XML specification of a testcase and creates the corresponding Rutema::Specification instance
52
+ def parse_case xmltxt,filename
53
+ spec=Rutema::Specification.new({})
54
+ xmldoc=REXML::Document.new( xmltxt )
55
+ validate_case(xmldoc)
56
+ xmldoc.root.attributes.each do |attr,value|
57
+ add_attribute(spec,attr,value)
58
+ end
59
+ spec.title=xmldoc.elements[ELEM_TITLE].text
60
+ spec.title||=""
61
+ spec.title.strip!
62
+ spec.description=xmldoc.elements[ELEM_DESC].text
63
+ spec.description||=""
64
+ unless spec.description.empty?
65
+ spec.description.strip!
66
+ spec.description.gsub!(/\t/,'')
67
+ end
68
+ Dir.chdir(File.dirname(filename)) do
69
+ spec.scenario=parse_scenario(xmldoc.elements[ELEM_SCENARIO].to_s) if xmldoc.elements[ELEM_SCENARIO]
70
+ end
71
+ spec.filename=filename
72
+ return spec
73
+ end
74
+ #Validates the XML file from our point of view.
75
+ def validate_case xmldoc
76
+ raise Rutema::ParserError,"missing #{ELEM_SPEC} element in #{xmldoc}" unless xmldoc.elements[ELEM_SPEC]
77
+ raise Rutema::ParserError,"missing #{ELEM_DESC} element in #{xmldoc}" unless xmldoc.elements[ELEM_DESC]
78
+ raise Rutema::ParserError,"missing #{ELEM_TITLE} element in #{xmldoc}" unless xmldoc.elements[ELEM_TITLE]
79
+ end
80
+ #Parses the 'scenario' XML element and returns the Rutema::Scenario instance
81
+ def parse_scenario xmltxt
82
+ scenario=Rutema::Scenario.new([])
83
+ xmldoc=REXML::Document.new( xmltxt )
84
+ xmldoc.root.attributes.each do |attr,value|
85
+ add_attribute(scenario,attr,value)
86
+ end
87
+ number=0
88
+ xmldoc.root.elements.each do |el|
89
+ step=parse_step(el.to_s)
90
+ if step.step_type=="include_scenario"
91
+ included_scenario=include_scenario(step)
92
+ included_scenario.steps.each do |st|
93
+ number+=1
94
+ st.number=number
95
+ st.included_in=step.file
96
+ scenario.add_step(st)
97
+ end
98
+ else
99
+ number+=1
100
+ step.number=number
101
+ scenario.add_step(step)
102
+ end
103
+ end
104
+ return scenario
105
+ end
106
+ #Parses xml and returns the Rutema::Step instance
107
+ def parse_step xmltxt
108
+ xmldoc=REXML::Document.new( xmltxt )
109
+ #any step element
110
+ step=Rutema::Step.new()
111
+ step.ignore=false
112
+ xmldoc.root.attributes.each do |attr,value|
113
+ add_attribute(step,attr,value)
114
+ end
115
+ step.text=xmldoc.root.text.strip if xmldoc.root.text
116
+ step.step_type=xmldoc.root.name
117
+ return step
118
+ end
119
+ def add_attribute element,attr,value
120
+ if boolean?(value)
121
+ element.attribute(attr,eval(value))
122
+ else
123
+ element.attribute(attr,value)
124
+ end
125
+ end
126
+ def boolean? attribute_value
127
+ return true if attribute_value=="true" || attribute_value=="false"
128
+ return false
129
+ end
130
+ #handles <include_scenario> elements, adding the steps to the current scenario
131
+ def include_scenario step
132
+ raise Rutema::ParserError,"missing required attribute file in #{step}" unless step.has_file?
133
+ raise Rutema::ParserError,"Cannot find #{File.expand_path(step.file)}" unless File.exist?(File.expand_path(step.file))
134
+ step.file=File.expand_path(step.file)
135
+ include_content=File.read(step.file)
136
+ return parse_scenario(include_content)
137
+ end
138
+ def extension_handling spec
139
+ #change into the directory the spec is in to handle relative paths correctly
140
+ Dir.chdir(File.dirname(File.expand_path(spec.filename))) do |path|
141
+ spec.scenario.steps.each do |step|
142
+ #do we have a method to handle the element?
143
+ if respond_to?(:"element_#{step.step_type}")
144
+ begin
145
+ self.send(:"element_#{step.step_type}",step)
146
+ rescue
147
+ raise ParserError, $!.message
148
+ end
149
+ end#begin
150
+ end#each
151
+ end#chdir
152
+ return spec
153
+ end
154
+ end
155
+ end
156
+ end
@@ -1,34 +1,34 @@
1
- # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
- require 'json'
3
- require_relative "../core/reporter"
4
-
5
- module Rutema
6
- module Reporters
7
- #Experimental reporter used to dump the data of a run on disk
8
- #
9
- #The following configuration keys are used by Rutema::Reporters::JSON
10
- #
11
- # filename - the filename to use to save the YAML dump. Default is 'rutema.results.json'
12
- class JSON<Rutema::Reporters::BlockReporter
13
- #Default report filename
14
- DEFAULT_FILENAME="rutema.results.json"
15
-
16
- def initialize configuration,dispatcher
17
- super(configuration,dispatcher)
18
- @filename=configuration.reporters.fetch(self.class,{}).fetch("filename",DEFAULT_FILENAME)
19
- end
20
- #We get all the data from a test run in here.
21
- def report specs,states,errors
22
- run_entry={}
23
- run_entry["specs"]=specs.size
24
- if @configuration && @configuration.context
25
- run_entry["context"]=@configuration.context
26
- end
27
- run_entry["errors"]=errors
28
- run_entry["states"]=states
29
-
30
- Rutema::Utilities.write_file(@filename,::JSON.dump(run_entry))
31
- end
32
- end
33
- end
34
- end
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
+ require 'json'
3
+ require_relative "../core/reporter"
4
+
5
+ module Rutema
6
+ module Reporters
7
+ #Experimental reporter used to dump the data of a run on disk
8
+ #
9
+ #The following configuration keys are used by Rutema::Reporters::JSON
10
+ #
11
+ # filename - the filename to use to save the YAML dump. Default is 'rutema.results.json'
12
+ class JSON<Rutema::Reporters::BlockReporter
13
+ #Default report filename
14
+ DEFAULT_FILENAME="rutema.results.json"
15
+
16
+ def initialize configuration,dispatcher
17
+ super(configuration,dispatcher)
18
+ @filename=configuration.reporters.fetch(self.class,{}).fetch("filename",DEFAULT_FILENAME)
19
+ end
20
+ #We get all the data from a test run in here.
21
+ def report specs,states,errors
22
+ run_entry={}
23
+ run_entry["specs"]=specs.size
24
+ if @configuration && @configuration.context
25
+ run_entry["context"]=@configuration.context
26
+ end
27
+ run_entry["errors"]=errors
28
+ run_entry["states"]=states
29
+
30
+ Rutema::Utilities.write_file(@filename,::JSON.dump(run_entry))
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,97 +1,101 @@
1
- # Copyright (c) 2015 Vassilis Rizopoulos. All rights reserved.
2
- require 'rexml/document'
3
- require_relative "../core/reporter"
4
-
5
- module Rutema
6
- module Reporters
7
- #This reporter generates an JUnit style XML result file that can be parsed by CI plugins
8
- #
9
- #It has been tested with Jenkins (>1.6.20)
10
- #
11
- #The following configuration keys are used by Rutema::Reporters::JUnit
12
- #
13
- # filename - the filename to use when saving the report. Default is 'rutema.results.junit.xml'
14
- #
15
- #Example configuration:
16
- #
17
- # require "rutema/reporters/junit"
18
- # cfg.reporter={:class=>Rutema::Reporters::JUnit,"filename"=>"rutema.junit.xml"}
19
- class JUnit<BlockReporter
20
- DEFAULT_FILENAME="rutema.results.junit.xml"
21
-
22
- def initialize configuration,dispatcher
23
- super(configuration,dispatcher)
24
- @filename=configuration.reporters.fetch(self.class,{}).fetch("filename",DEFAULT_FILENAME)
25
- end
26
- #We get all the data from a test run in here.
27
- def report specs,states,errors
28
- tests=[]
29
- number_of_failed=0
30
- total_duration=0
31
- states.each do |k,v|
32
- tests<<test_case(k,v)
33
- number_of_failed+=1 if v['status']!=:success
34
- total_duration+=v["duration"].to_f
35
- end
36
- crashes=errors.map{|error| crash(error[:test],error[:error])}
37
-
38
-
39
- #<testsuite disabled="0" errors="0" failures="1" hostname="" id=""
40
- #name="" package="" skipped="" tests="" time="" timestamp="">
41
- attributes={"id"=>@configuration.context[:config_name],
42
- "name"=>@configuration.context[:config_name],
43
- "errors"=>crashes.size,
44
- "failures"=>number_of_failed,
45
- "tests"=>specs.size,
46
- "time"=>total_duration,
47
- "timestamp"=>@configuration.context[:start_time]
48
- }
49
- element_suite=REXML::Element.new("testsuite")
50
- element_suite.add_attributes(attributes)
51
-
52
- crashes.each{|t| element_suite.add_element(t)}
53
- tests.each{|t| element_suite.add_element(t)}
54
- xmldoc=REXML::Document.new
55
- xmldoc<<REXML::XMLDecl.new
56
- xmldoc.add_element(element_suite)
57
-
58
- Rutema::Utilities.write_file(@filename,xmldoc.to_s)
59
- end
60
- private
61
- def test_case name,state
62
- #<testcase name="" time=""> => the results from executing a test method
63
- # <system-out> => data written to System.out during the test run
64
- # <system-err> => data written to System.err during the test run
65
- # <skipped/> => test was skipped
66
- # <failure> => test failed
67
- # <error> => test encountered an error
68
- #</testcase>
69
- element_test=REXML::Element.new("testcase")
70
- element_test.add_attributes("name"=>name,"time"=>state["duration"],"classname"=>@configuration.context[:config_name])
71
- if state['status']!=:success
72
- fail=REXML::Element.new("failure")
73
- fail.add_attribute("message","Step #{state["steps"].last["number"]} failed.")
74
- fail.text="Step #{state["steps"].last["number"]} failed."
75
- element_test.add_element(fail)
76
- out=REXML::Element.new("system-out")
77
- out.text=state["steps"].last["out"]
78
- element_test.add_element(out)
79
- err=REXML::Element.new("system-err")
80
- err.text=state["steps"].last["err"]
81
- element_test.add_element(err)
82
- end
83
- return element_test
84
- end
85
-
86
- def crash name,message
87
- failed=REXML::Element.new("testcase")
88
- failed.add_attributes("name"=>name,"classname"=>@configuration.context[:config_name],"time"=>0)
89
- msg=REXML::Element.new("error")
90
- msg.add_attribute("message",message)
91
- msg.text=message
92
- failed.add_element(msg)
93
- return failed
94
- end
95
- end
96
- end
97
- end
1
+ # Copyright (c) 2015 Vassilis Rizopoulos. All rights reserved.
2
+ require 'rexml/document'
3
+ require_relative "../core/reporter"
4
+
5
+ module Rutema
6
+ module Reporters
7
+ #This reporter generates an JUnit style XML result file that can be parsed by CI plugins
8
+ #
9
+ #It has been tested with Jenkins (>1.6.20)
10
+ #
11
+ #The following configuration keys are used by Rutema::Reporters::JUnit
12
+ #
13
+ # filename - the filename to use when saving the report. Default is 'rutema.results.junit.xml'
14
+ #
15
+ #Example configuration:
16
+ #
17
+ # require "rutema/reporters/junit"
18
+ # cfg.reporter={:class=>Rutema::Reporters::JUnit,"filename"=>"rutema.junit.xml"}
19
+ class JUnit<BlockReporter
20
+ DEFAULT_FILENAME="rutema.results.junit.xml"
21
+
22
+ def initialize configuration,dispatcher
23
+ super(configuration,dispatcher)
24
+ @filename=configuration.reporters.fetch(self.class,{}).fetch("filename",DEFAULT_FILENAME)
25
+ end
26
+ #We get all the data from a test run in here.
27
+ def report specs,states,errors
28
+ cnt=process_data(specs,states,errors)
29
+ Rutema::Utilities.write_file(@filename,cnt)
30
+ end
31
+ def process_data specs,states,errors
32
+ tests=[]
33
+ number_of_failed=0
34
+ total_duration=0
35
+ states.each do |k,v|
36
+ tests<<test_case(k,v)
37
+ number_of_failed+=1 if v['status']!=:success
38
+ total_duration+=v["duration"].to_f
39
+ end
40
+ #<testsuite disabled="0" errors="0" failures="1" hostname="" id=""
41
+ #name="" package="" skipped="" tests="" time="" timestamp="">
42
+ attributes={"id"=>@configuration.context[:config_name],
43
+ "name"=>@configuration.context[:config_name],
44
+ "errors"=>errors.size,
45
+ "failures"=>number_of_failed,
46
+ "tests"=>specs.size,
47
+ "time"=>total_duration,
48
+ "timestamp"=>@configuration.context[:start_time]
49
+ }
50
+ return junit_content(specs,attributes,errors)
51
+ end
52
+ private
53
+ def test_case name,state
54
+ #<testcase name="" time=""> => the results from executing a test method
55
+ # <system-out> => data written to System.out during the test run
56
+ # <system-err> => data written to System.err during the test run
57
+ # <skipped/> => test was skipped
58
+ # <failure> => test failed
59
+ # <error> => test encountered an error
60
+ #</testcase>
61
+ element_test=REXML::Element.new("testcase")
62
+ element_test.add_attributes("name"=>name,"time"=>state["duration"],"classname"=>@configuration.context[:config_name])
63
+ if state['status']!=:success
64
+ fail=REXML::Element.new("failure")
65
+ fail.add_attribute("message","Step #{state["steps"].last["number"]} failed.")
66
+ fail.text="Step #{state["steps"].last["number"]} failed."
67
+ element_test.add_element(fail)
68
+ out=REXML::Element.new("system-out")
69
+ out.text=state["steps"].last["out"]
70
+ element_test.add_element(out)
71
+ err=REXML::Element.new("system-err")
72
+ err.text=state["steps"].last["err"]
73
+ element_test.add_element(err)
74
+ end
75
+ return element_test
76
+ end
77
+ def crash name,message
78
+ failed=REXML::Element.new("testcase")
79
+ failed.add_attributes("name"=>name,"classname"=>@configuration.context[:config_name],"time"=>0)
80
+ msg=REXML::Element.new("error")
81
+ msg.add_attribute("message",message)
82
+ msg.text=message
83
+ failed.add_element(msg)
84
+ return failed
85
+ end
86
+ def junit_content tests,attributes,errors
87
+ element_suite=REXML::Element.new("testsuite")
88
+ element_suite.add_attributes(attributes)
89
+ errors.each{|error| element_suite.add_element(crash(error.test,error.text))}
90
+ tests.each{|t| element_suite.add_element(t)}
91
+ return document(element_suite).to_s
92
+ end
93
+ def document suite
94
+ xmldoc=REXML::Document.new
95
+ xmldoc<<REXML::XMLDecl.new
96
+ xmldoc.add_element(suite)
97
+ return xmldoc
98
+ end
99
+ end
100
+ end
101
+ end
@@ -1,9 +1,9 @@
1
- module Rutema
2
- #This module defines the version numbers for the library
3
- module Version
4
- MAJOR=2
5
- MINOR=0
6
- TINY="0.pre5"
7
- STRING=[ MAJOR, MINOR, TINY ].join( "." )
8
- end
1
+ module Rutema
2
+ #This module defines the version numbers for the library
3
+ module Version
4
+ MAJOR=2
5
+ MINOR=0
6
+ TINY="0.pre6"
7
+ STRING=[ MAJOR, MINOR, TINY ].join( "." )
8
+ end
9
9
  end