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,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