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.
- checksums.yaml +4 -4
- data/History.txt +220 -213
- data/Manifest.txt +17 -18
- data/README.md +55 -55
- data/bin/rutema +7 -7
- data/lib/rutema/application.rb +61 -60
- data/lib/rutema/core/configuration.rb +207 -194
- data/lib/rutema/core/engine.rb +192 -185
- data/lib/rutema/core/framework.rb +88 -27
- data/lib/rutema/core/objectmodel.rb +0 -0
- data/lib/rutema/core/parser.rb +34 -34
- data/lib/rutema/core/reporter.rb +133 -129
- data/lib/rutema/core/runner.rb +93 -83
- data/lib/rutema/elements/minimal.rb +47 -47
- data/lib/rutema/parsers/xml.rb +156 -154
- data/lib/rutema/reporters/json.rb +34 -34
- data/lib/rutema/reporters/junit.rb +101 -97
- data/lib/rutema/version.rb +8 -8
- metadata +5 -7
- data/.gemtest +0 -0
- data/lib/rutema/reporters/nunit.rb +0 -103
@@ -1,195 +1,208 @@
|
|
1
|
-
# Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
|
2
|
-
require 'ostruct'
|
3
|
-
require_relative 'parser'
|
4
|
-
require_relative 'reporter'
|
5
|
-
module Rutema
|
6
|
-
#This module defines the "configuration directives" used in the configuration of Rutema
|
7
|
-
#
|
8
|
-
#Example
|
9
|
-
#A configuration file needs as a minimum to define which parser to use and which tests to run.
|
10
|
-
#
|
11
|
-
#Since rutema configuration files are valid Ruby code, you can use the full power of the Ruby language including require directives
|
12
|
-
#
|
13
|
-
# require 'rake'
|
14
|
-
# configuration.parser={:class=>Rutema::MinimalXMLParser}
|
15
|
-
# configuration.tests=FileList['all/of/the/tests/**/*.*']
|
16
|
-
module ConfigurationDirectives
|
17
|
-
attr_reader :parser,:runner,:tools,:paths,:tests,:context,:check,:setup,:teardown
|
18
|
-
attr_accessor :reporters
|
19
|
-
#Adds a hash of values to the tools hash of the configuration
|
20
|
-
#
|
21
|
-
#This hash is then accessible in the parser and reporters as a property of the configuration instance
|
22
|
-
#
|
23
|
-
#Required keys:
|
24
|
-
# :name - the name to use for accessing the path in code
|
25
|
-
#Example:
|
26
|
-
# configure do |cfg|
|
27
|
-
# cfg.tool={:name=>"nunit",:path=>"/bin/nunit",:configuration=>{:important=>"info"}}
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
#The path to nunit can then be accessed in the parser as
|
31
|
-
# @configuration.tools.nunit[:path]
|
32
|
-
#
|
33
|
-
#This way you can pass configuration information for the tools you use
|
34
|
-
def tool= definition
|
35
|
-
raise ConfigurationException,"required key :name is missing from #{definition}" unless definition[:name]
|
36
|
-
@tools[definition[:name]]=definition
|
37
|
-
end
|
38
|
-
#Adds a path to the paths hash of the configuration
|
39
|
-
#
|
40
|
-
#Required keys:
|
41
|
-
# :name - the name to use for accessing the path in code
|
42
|
-
# :path - the path
|
43
|
-
#Example:
|
44
|
-
# cfg.path={:name=>"sources",:path=>"/src"}
|
45
|
-
def path= definition
|
46
|
-
raise ConfigurationException,"required key :name is missing from #{definition}" unless definition[:name]
|
47
|
-
raise ConfigurationException,"required key :path is missing from #{definition}" unless definition[:path]
|
48
|
-
@paths[definition[:name]]=definition[:path]
|
49
|
-
end
|
50
|
-
|
51
|
-
#Path to the setup specification. (optional)
|
52
|
-
#
|
53
|
-
#The setup test runs before every test.
|
54
|
-
def setup= path
|
55
|
-
@setup=check_path(path)
|
56
|
-
end
|
57
|
-
|
58
|
-
#Path to the teardown specification. (optional)
|
59
|
-
#
|
60
|
-
#The teardown test runs after every test.
|
61
|
-
def teardown= path
|
62
|
-
@teardown=check_path(path)
|
63
|
-
end
|
64
|
-
|
65
|
-
#Path to the check specification. (optional)
|
66
|
-
#
|
67
|
-
#The check test runs once in the beginning before all the tests.
|
68
|
-
#
|
69
|
-
#If it fails no tests are run.
|
70
|
-
def check= path
|
71
|
-
@check=check_path(path)
|
72
|
-
end
|
73
|
-
|
74
|
-
#Hash values for passing data to the system. It's supposed to be used in the reporters and contain
|
75
|
-
#values such as version numbers, tester names etc.
|
76
|
-
def context= definition
|
77
|
-
@context||=Hash.new
|
78
|
-
raise ConfigurationException,"Only accepting hash values as context_data" unless definition.kind_of?(Hash)
|
79
|
-
@context.merge!(definition)
|
80
|
-
end
|
81
|
-
|
82
|
-
#Adds the specification identifiers available to this instance of Rutema
|
83
|
-
#
|
84
|
-
#These will usually be files, but they can be anything.
|
85
|
-
#Essentially this is an Array of strings that mean something to your parser
|
86
|
-
def tests= array_of_identifiers
|
87
|
-
@tests+=array_of_identifiers.map{|f| full_path(f)}
|
88
|
-
end
|
89
|
-
|
90
|
-
#A hash defining the parser to use.
|
91
|
-
#
|
92
|
-
#The hash is passed as is to the parser constructor and each parser should define the necessary configuration keys.
|
93
|
-
#
|
94
|
-
#The only required key from the configurator's point fo view is :class which should be set to the fully qualified name of the class to use.
|
95
|
-
#
|
96
|
-
#Example:
|
97
|
-
# cfg.parser={:class=>Rutema::MinimalXMLParser}
|
98
|
-
def parser= definition
|
99
|
-
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
100
|
-
@parser=definition
|
101
|
-
end
|
102
|
-
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
1
|
+
# Copyright (c) 2007-2015 Vassilis Rizopoulos. All rights reserved.
|
2
|
+
require 'ostruct'
|
3
|
+
require_relative 'parser'
|
4
|
+
require_relative 'reporter'
|
5
|
+
module Rutema
|
6
|
+
#This module defines the "configuration directives" used in the configuration of Rutema
|
7
|
+
#
|
8
|
+
#Example
|
9
|
+
#A configuration file needs as a minimum to define which parser to use and which tests to run.
|
10
|
+
#
|
11
|
+
#Since rutema configuration files are valid Ruby code, you can use the full power of the Ruby language including require directives
|
12
|
+
#
|
13
|
+
# require 'rake'
|
14
|
+
# configuration.parser={:class=>Rutema::MinimalXMLParser}
|
15
|
+
# configuration.tests=FileList['all/of/the/tests/**/*.*']
|
16
|
+
module ConfigurationDirectives
|
17
|
+
attr_reader :parser,:runner,:tools,:paths,:tests,:context,:check,:setup,:teardown
|
18
|
+
attr_accessor :reporters
|
19
|
+
#Adds a hash of values to the tools hash of the configuration
|
20
|
+
#
|
21
|
+
#This hash is then accessible in the parser and reporters as a property of the configuration instance
|
22
|
+
#
|
23
|
+
#Required keys:
|
24
|
+
# :name - the name to use for accessing the path in code
|
25
|
+
#Example:
|
26
|
+
# configure do |cfg|
|
27
|
+
# cfg.tool={:name=>"nunit",:path=>"/bin/nunit",:configuration=>{:important=>"info"}}
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
#The path to nunit can then be accessed in the parser as
|
31
|
+
# @configuration.tools.nunit[:path]
|
32
|
+
#
|
33
|
+
#This way you can pass configuration information for the tools you use
|
34
|
+
def tool= definition
|
35
|
+
raise ConfigurationException,"required key :name is missing from #{definition}" unless definition[:name]
|
36
|
+
@tools[definition[:name]]=definition
|
37
|
+
end
|
38
|
+
#Adds a path to the paths hash of the configuration
|
39
|
+
#
|
40
|
+
#Required keys:
|
41
|
+
# :name - the name to use for accessing the path in code
|
42
|
+
# :path - the path
|
43
|
+
#Example:
|
44
|
+
# cfg.path={:name=>"sources",:path=>"/src"}
|
45
|
+
def path= definition
|
46
|
+
raise ConfigurationException,"required key :name is missing from #{definition}" unless definition[:name]
|
47
|
+
raise ConfigurationException,"required key :path is missing from #{definition}" unless definition[:path]
|
48
|
+
@paths[definition[:name]]=definition[:path]
|
49
|
+
end
|
50
|
+
|
51
|
+
#Path to the setup specification. (optional)
|
52
|
+
#
|
53
|
+
#The setup test runs before every test.
|
54
|
+
def setup= path
|
55
|
+
@setup=check_path(path)
|
56
|
+
end
|
57
|
+
|
58
|
+
#Path to the teardown specification. (optional)
|
59
|
+
#
|
60
|
+
#The teardown test runs after every test.
|
61
|
+
def teardown= path
|
62
|
+
@teardown=check_path(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
#Path to the check specification. (optional)
|
66
|
+
#
|
67
|
+
#The check test runs once in the beginning before all the tests.
|
68
|
+
#
|
69
|
+
#If it fails no tests are run.
|
70
|
+
def check= path
|
71
|
+
@check=check_path(path)
|
72
|
+
end
|
73
|
+
|
74
|
+
#Hash values for passing data to the system. It's supposed to be used in the reporters and contain
|
75
|
+
#values such as version numbers, tester names etc.
|
76
|
+
def context= definition
|
77
|
+
@context||=Hash.new
|
78
|
+
raise ConfigurationException,"Only accepting hash values as context_data" unless definition.kind_of?(Hash)
|
79
|
+
@context.merge!(definition)
|
80
|
+
end
|
81
|
+
|
82
|
+
#Adds the specification identifiers available to this instance of Rutema
|
83
|
+
#
|
84
|
+
#These will usually be files, but they can be anything.
|
85
|
+
#Essentially this is an Array of strings that mean something to your parser
|
86
|
+
def tests= array_of_identifiers
|
87
|
+
@tests+=array_of_identifiers.map{|f| full_path(f)}
|
88
|
+
end
|
89
|
+
|
90
|
+
#A hash defining the parser to use.
|
91
|
+
#
|
92
|
+
#The hash is passed as is to the parser constructor and each parser should define the necessary configuration keys.
|
93
|
+
#
|
94
|
+
#The only required key from the configurator's point fo view is :class which should be set to the fully qualified name of the class to use.
|
95
|
+
#
|
96
|
+
#Example:
|
97
|
+
# cfg.parser={:class=>Rutema::MinimalXMLParser}
|
98
|
+
def parser= definition
|
99
|
+
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
100
|
+
@parser=definition
|
101
|
+
end
|
102
|
+
|
103
|
+
#A hash defining the runner to use.
|
104
|
+
#
|
105
|
+
#The hash is passed as is to the runner constructor and each runner should define the necessary configuration keys.
|
106
|
+
#
|
107
|
+
#The only required key from the configurator's point fo view is :class which should be set to the fully qualified name of the class to use.
|
108
|
+
#
|
109
|
+
#Example:
|
110
|
+
# cfg.runner={:class=>Rutema::Runners::NoOp}
|
111
|
+
def runner= definition
|
112
|
+
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
113
|
+
@runner=definition
|
114
|
+
end
|
115
|
+
|
116
|
+
#Adds a reporter to the configuration.
|
117
|
+
#
|
118
|
+
#As with the parser, the only required configuration key is :class and the definition hash is passed to the class' constructor.
|
119
|
+
#
|
120
|
+
#Unlike the parser, you can define multiple reporters.
|
121
|
+
def reporter= definition
|
122
|
+
raise ConfigurationException,"required key :class is missing from #{definition}" unless definition[:class]
|
123
|
+
@reporters[definition[:class]]=definition
|
124
|
+
end
|
125
|
+
|
126
|
+
def init
|
127
|
+
@reporters={}
|
128
|
+
@context={}
|
129
|
+
@tests=[]
|
130
|
+
@tools=OpenStruct.new
|
131
|
+
@paths=OpenStruct.new
|
132
|
+
end
|
133
|
+
private
|
134
|
+
#Checks if a path exists and raises a ConfigurationException if not
|
135
|
+
def check_path path
|
136
|
+
path=File.expand_path(path)
|
137
|
+
raise ConfigurationException,"#{path} does not exist" unless File.exist?(path)
|
138
|
+
return path
|
139
|
+
end
|
140
|
+
#Gives back a string of key=value,key=value for a hash
|
141
|
+
def definition_string definition
|
142
|
+
msg=Array.new
|
143
|
+
definition.each{|k,v| msg<<"#{k}=#{v}"}
|
144
|
+
return msg.join(",")
|
145
|
+
end
|
146
|
+
|
147
|
+
def full_path filename
|
148
|
+
return File.expand_path(filename) if File.exist?(filename)
|
149
|
+
return filename
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class ConfigurationException<RuntimeError
|
154
|
+
end
|
155
|
+
|
156
|
+
class Configuration
|
157
|
+
include ConfigurationDirectives
|
158
|
+
attr_reader :filename
|
159
|
+
def initialize config_file
|
160
|
+
@filename=config_file
|
161
|
+
init
|
162
|
+
load_configuration(@filename)
|
163
|
+
end
|
164
|
+
|
165
|
+
def configure
|
166
|
+
if block_given?
|
167
|
+
yield self
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
#Loads the configuration from a file
|
172
|
+
#
|
173
|
+
#Use this to chain configuration files together
|
174
|
+
#==Example
|
175
|
+
#Say you have on configuration file "first.rutema" that contains all the generic directives and several others that change only one or two things.
|
176
|
+
#
|
177
|
+
#You can import the first.rutema file in the other configurations with
|
178
|
+
# import("first.rutema")
|
179
|
+
def import filename
|
180
|
+
fnm = File.expand_path(filename)
|
181
|
+
if File.exist?(fnm)
|
182
|
+
load_configuration(fnm)
|
183
|
+
else
|
184
|
+
raise ConfigurationException, "Import error: Can't find #{fnm}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
private
|
188
|
+
def load_configuration filename
|
189
|
+
begin
|
190
|
+
cfg_txt=File.read(filename)
|
191
|
+
cwd=File.expand_path(File.dirname(filename))
|
192
|
+
#evaluate in the working directory to enable relative paths in configuration
|
193
|
+
Dir.chdir(cwd){eval(cfg_txt,binding(),filename,__LINE__)}
|
194
|
+
rescue ConfigurationException
|
195
|
+
#pass it on, do not wrap again
|
196
|
+
raise
|
197
|
+
rescue SyntaxError
|
198
|
+
#Just wrap the exception so we can differentiate
|
199
|
+
raise ConfigurationException.new,"Syntax error in the configuration file '#{filename}':\n#{$!.message}"
|
200
|
+
rescue NoMethodError
|
201
|
+
raise ConfigurationException.new,"Encountered an unknown directive in configuration file '#{filename}':\n#{$!.message}"
|
202
|
+
rescue
|
203
|
+
#Just wrap the exception so we can differentiate
|
204
|
+
raise ConfigurationException.new,"#{$!.message}"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
195
208
|
end
|