rutema 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,10 +1,15 @@
1
+ == 0.3 / 2007-05-30
2
+ * Reporter implementations moved to own file
3
+ * Reporter interface changed (Runner stati now passed directly as a name indexed Hash, specifications passed as well)
4
+ * ActiveRecordReporter with SQLite DB added
5
+ * rutemah (the Historian) added in tools. The Historian reads from ActiveRecordReporter databases
6
+
1
7
  == 0.2 / 2007-05-21
2
8
  * bin/ files included in gem
3
9
  * rutemax: missing configuration file is now checked before passed to the system
10
+
4
11
  == 0.1 / 2007-05-21
5
12
  * A running system!
6
13
  * Basic XML parser with echo, command and prompt
7
14
  * email reporting
8
15
  * rutemax application
9
-
10
-
data/Manifest.txt CHANGED
@@ -3,15 +3,24 @@ Manifest.txt
3
3
  README.txt
4
4
  COPYING.txt
5
5
  Rakefile
6
+ bin/rutemax
7
+ bin/rutemah
6
8
  lib/rutema/configuration.rb
7
9
  lib/rutema/specification.rb
8
10
  lib/rutema/system.rb
11
+ lib/rutema/reporter.rb
12
+ lib/rutema/reporter_ar.rb
13
+ lib/rutema/historian.rb
14
+ test/test_configuration.rb
9
15
  test/test_specification.rb
10
16
  test/test_system.rb
17
+ test/test_historian.rb
18
+ test/test_reporter.rb
11
19
  test/samples/check.spec
12
20
  test/samples/setup.spec
13
21
  test/samples/teardown.spec
14
22
  test/samples/test.spec
15
23
  test/samples/tests/no_title.spec
16
24
  test/samples/tests/sample.spec
17
- test/samples/valid_config.rb
25
+ test/samples/valid_config.rb
26
+ test/samples/rutemah_config.rb
data/Rakefile CHANGED
@@ -14,10 +14,12 @@ Hoe.new('rutema', "#{Rutema::VERSION_MAJOR}.#{Rutema::VERSION_MINOR}") do |p|
14
14
  p.description = p.paragraphs_of('README.txt', 1..5).join("\n\n")
15
15
  p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
16
16
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
17
- p.extra_deps<<['patir',">=0.3"]
17
+ p.extra_deps<<['patir',">=0.4"]
18
18
  p.extra_deps<<['highline']
19
19
  p.extra_deps<<['mailfactory']
20
- p.spec_extras={:executables=>["rutemax"],
20
+ p.extra_deps<<['activerecord']
21
+ p.extra_deps<<['ruport']
22
+ p.spec_extras={:executables=>["rutemax","rutemah"],
21
23
  :default_executable=>"rutemax"}
22
24
  end
23
25
 
data/bin/rutemah ADDED
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
2
+ begin
3
+ require 'rutema/historian'
4
+ rescue LoadError
5
+ require 'rubygems'
6
+ require 'rutema/historian'
7
+ end
8
+
9
+ Rutema::RutemaH.new(ARGV)
@@ -6,7 +6,7 @@ require 'patir/configuration'
6
6
 
7
7
  module Rutema
8
8
  #This module defines the "configuration directives" used in the configuration of RutemaX
9
- module RutemaConfiguration
9
+ module RutemaXConfiguration
10
10
  #Adds a path to a tools to the tools hash of the configuration
11
11
  #
12
12
  #Required keys:
@@ -58,6 +58,7 @@ module Rutema
58
58
 
59
59
  #Hash values for passing data to the system. It's supposed to be used in the reporters and contain
60
60
  #values such as verson numbers, tester names etc.
61
+ #
61
62
  def context_data= definition
62
63
  @context||=Hash.new
63
64
  raise Patir::ConfigurationException,"Only accepting hash values as context_data" unless definition.kind_of?(Hash)
@@ -110,9 +111,20 @@ module Rutema
110
111
  end
111
112
  end
112
113
 
114
+ #This module defines the "configuration directives" used in the configuration of RutemaH
115
+ module RutemaHConfiguration
116
+ #The configuration keys for the historian's database
117
+ def source= definition
118
+ if File.exists?(definition)
119
+ @source=File.expand_path(definition)
120
+ else
121
+ raise Patir::ConfigurationException,"DB file '#{definition}' not found"
122
+ end
123
+ end
124
+ end
113
125
  #This class reads a RutemaX configuration file
114
- class RutemaConfigurator<Patir::Configurator
115
- include RutemaConfiguration
126
+ class RutemaXConfigurator<Patir::Configurator
127
+ include RutemaXConfiguration
116
128
  def initialize config_file,logger=nil
117
129
  @reporters=Array.new
118
130
  @context=Hash.new
@@ -139,4 +151,18 @@ module Rutema
139
151
  return conf
140
152
  end
141
153
  end
154
+
155
+ #This class reads a RutemaH configuration file
156
+ class RutemaHConfigurator<RutemaXConfigurator
157
+ include RutemaHConfiguration
158
+ def initialize config_file,logger=nil
159
+ super(config_file,logger)
160
+ end
161
+
162
+ def configuration
163
+ cfg=super
164
+ cfg.source=@source
165
+ return cfg
166
+ end
167
+ end
142
168
  end
@@ -0,0 +1,94 @@
1
+ require 'rutema/reporter_ar'
2
+ require 'rutema/system'
3
+
4
+ require 'rubygems'
5
+ require "ruport"
6
+
7
+ module Rutema
8
+ #The "historian" application class
9
+ #
10
+ #RutemaH provides reports for test results over time using the data stored by the ActiveRecordReporter
11
+ class RutemaH
12
+ require 'optparse'
13
+ def initialize command_line_args
14
+ parse_command_line(command_line_args)
15
+ logger=Patir.setup_logger(@log_file)
16
+ begin
17
+ raise "No configuration file defined!" if !@config_file
18
+ configuration=RutemaHConfigurator.new(@config_file,logger).configuration
19
+ historian=Historian.new(configuration,logger)
20
+ historian.history(@command)
21
+ rescue Patir::ConfigurationException
22
+ logger.debug($!)
23
+ logger.fatal("Configuration error '#{$!.message}'")
24
+ exit 1
25
+ rescue
26
+ logger.debug($!)
27
+ logger.fatal("#{$!.message}")
28
+ exit 1
29
+ end
30
+ end
31
+ private
32
+ def parse_command_line args
33
+ args.options do |opt|
34
+ opt.on("Options:")
35
+ opt.on("--debug", "-d","Turns on debug messages") { $DEBUG=true }
36
+ opt.on("--config FILE", "-c FILE",String,"Loads the configuration from FILE") { |@config_file|}
37
+ opt.on("--log FILE", "-l FILE",String,"Redirects the log output to FILE") { |@log_file|}
38
+ opt.on("-V", "--version","Displays the version") { $stdout.puts("v#{VERSION_MAJOR}.#{VERSION_MINOR}");exit 0 }
39
+ opt.on("--help", "-h", "-?", "This text") { $stdout.puts opt; exit 0 }
40
+ opt.parse!
41
+ #and now the rest
42
+ if args.empty?
43
+ $stdout.puts opt
44
+ exit 0
45
+ else
46
+ @command=args.shift
47
+ end
48
+ end
49
+ end#parse_command_line
50
+ end
51
+
52
+ class Historian
53
+ def initialize configuration,logger=nil
54
+ @logger=logger
55
+ @logger||=Patir.setup_logger
56
+ @configuration=configuration
57
+ connect()
58
+ end
59
+
60
+ def history mode
61
+ case mode
62
+ when "all"
63
+ DB::Run.find(:all).each do |run|
64
+ puts "#{run.id}-----"
65
+ table=DB::Scenario.report_table(:all,:except=>["id","run_id","number"],:conditions => "run_id = '#{run.id}'")
66
+ puts beautify(table)
67
+ end
68
+ when String
69
+ per_spec(mode)
70
+ end
71
+ end
72
+ private
73
+ def beautify table
74
+ table.reorder("name","status","attended","version","start_time","stop_time")
75
+ table.replace_column("version") {|r| r.version ? r.version : "N/A"}
76
+ table.replace_column("attended") {|r| r.attended=="t" ? "yes" : "no"}
77
+ table.replace_column("start_time") {|r| r.stop_time ? r.start_time : nil}
78
+ return table
79
+ end
80
+ def per_spec spec_name
81
+ table=DB::Scenario.report_table(:all,:conditions=>"name = '#{spec_name}'",:except=>["id","run_id","number"])
82
+ if table.empty?
83
+ @logger.warn("No test run records found for #{spec_name}")
84
+ else
85
+ puts beautify(table)
86
+ end
87
+ end
88
+ def connect
89
+ ActiveRecord::Base.logger = @logger
90
+ @logger.info("Connecting with database '#{@configuration.source}'")
91
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database => @configuration.source)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,99 @@
1
+ # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
2
+ require 'rutema/specification'
3
+
4
+ require 'rubygems'
5
+ require 'mailfactory'
6
+
7
+ module Rutema
8
+ #Reporter is meant as a base class for reporter classes.
9
+ class Reporter
10
+ #params should be a Hash containing the parameters used to initialize the class
11
+ def initialize params
12
+ end
13
+
14
+ #Coordinator will pass the Rutema __configuration__ giving you access to the context which can contain data like headings and build numbers to use in the report. It will also pass the specifications used in the last run so that data like the title and the specification version can be used.
15
+ #
16
+ #runner_states is an Hash of Patir::CommandSeqeunceStatus indexed by the specification name containing the stati of the last run (so it contains all the Scenario stati for the loaded tests)
17
+ #
18
+ #parse_errors is an Array of {:filename,:error} hashes containing the errors encountered by the parser when loading the specifications
19
+ def report specifications,runner_states,parse_errors,configuration
20
+
21
+ end
22
+ end
23
+
24
+ #The following configuration keys are used by EmailReporter:
25
+ #
26
+ #:server - the smtp server to use
27
+ #
28
+ #:port - the port to use (defaults to 25)
29
+ #
30
+ #:sender - the sender of the email (defaults to rutema@domain)
31
+ #
32
+ #:recipients - an array of strings with the recipients of the report emails
33
+ #
34
+ #The :logger key is set by the Coordinator
35
+ #
36
+ #Customization keys:
37
+ #
38
+ #:subject - the string of this key will be prefixed as a subject for the email
39
+ class EmailReporter
40
+ attr_reader :last_message
41
+ def initialize definition
42
+ #get the logger
43
+ @logger=definition[:logger]
44
+ @logger||=Patir.setup_logger
45
+ #extract the parameters from the definition
46
+ #address and port of the smtp server
47
+ @server=definition[:server]
48
+ @port=definition[:port]
49
+ @port||=25
50
+ #the domain we're coming from
51
+ @domain=definition[:domain]
52
+ #construct the mail factory object
53
+ @mail = MailFactory.new()
54
+ @mail.from = definition[:sender]
55
+ @mail.from||="rutema@#{@domain}"
56
+ @recipients=definition[:recipients]
57
+ @mail.to=@recipients
58
+ #customize
59
+ @subject=definition[:subject]
60
+ @subject||=""
61
+ #this is a way to test without sending
62
+ @dummy=true if definition[:dummy]
63
+ @logger.info("Reporter '#{self.to_s}' registered")
64
+ end
65
+
66
+ def to_s
67
+ list=@recipients.join(', ')
68
+ "EmailReporter - #{@server}:#{@port} from #{@mail.from} to #{list}"
69
+ end
70
+
71
+ def report specifications,runner_states,parse_errors,configuration
72
+ @mail.subject = "#{@subject}"
73
+ @mail.text = Rutema.text_report(runner_states,parse_errors)
74
+ begin
75
+ if @mail.to.empty?
76
+ @logger.error("No recipients for the report mail")
77
+ else
78
+ #
79
+ #~ if @password
80
+ #~ #if a password is defined, use cram_md5 authentication
81
+ #~ else
82
+ Net::SMTP.start(@server, @port, @domain) {|smtp| smtp.sendmail(@mail.to_s(),@mail.from,mail_to)} unless @dummy
83
+ #~ end
84
+ end#recipients empty
85
+ rescue
86
+ @logger.error("Sending of email report failed: #{$!}")
87
+ end
88
+ @mail.to_s
89
+ end
90
+ end
91
+ private
92
+ def self.text_report runner_states,parse_errors
93
+ msg="Parse errors: #{parse_errors.size}"
94
+ parse_errors.each{|e| msg<<"\n\t#{e[:filename]}"}
95
+ msg<<"\nCurrent run:\nScenarios: #{runner_states.size}"
96
+ # msg<<"\n#{runner_status.summary}"
97
+ return msg
98
+ end
99
+ end
@@ -0,0 +1,149 @@
1
+ # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
2
+ require 'rutema/reporter'
3
+ require 'yaml'
4
+ require 'rubygems'
5
+ require 'active_record'
6
+ require 'ruport/acts_as_reportable'
7
+ require 'patir/command'
8
+
9
+ #this fixes the AR Logger hack that annoys me sooooo much
10
+ class Logger
11
+ private
12
+ def format_message(severity, datetime, progname, msg)
13
+ (@formatter || @default_formatter).call(severity, datetime, progname, msg)
14
+ end
15
+ end
16
+
17
+ module Rutema
18
+ #The DB module provides the ActiveRecord model for Rutema
19
+ module DB
20
+ #This is the schema for the AR database used to store test results
21
+ #
22
+ #We store the RutemaConfiguration#context for every run so that reports for past runs can be recreated without running the actual tests again.
23
+ class Schema<ActiveRecord::Migration
24
+ def self.up
25
+ create_table :runs do |t|
26
+ t.column :context, :string
27
+ end
28
+
29
+ create_table :scenarios do |t|
30
+ t.column :name, :string, :null=>false
31
+ t.column :run_id,:integer, :null=>false
32
+ t.column :attended,:bool, :null=>false
33
+ t.column :status, :string,:null=>false
34
+ t.column :number,:integer
35
+ t.column :start_time, :datetime,:null=>false
36
+ t.column :stop_time, :datetime
37
+ t.column :version, :string
38
+ end
39
+
40
+ create_table :steps do |t|
41
+ t.column :scenario_id,:integer, :null=>false
42
+ t.column :name, :string
43
+ t.column :number, :integer,:null=>false
44
+ t.column :status, :string,:null=>false
45
+ t.column :output, :text
46
+ t.column :error, :text
47
+ t.column :duration, :time
48
+ end
49
+
50
+ create_table :parse_errors do |t|
51
+ t.column :filename, :string,:null=>false
52
+ t.column :error, :string
53
+ t.column :run_id,:integer, :null=>false
54
+ end
55
+ end
56
+ end
57
+
58
+ class Run<ActiveRecord::Base
59
+ has_many :scenarios
60
+ has_many :parse_errors
61
+ acts_as_reportable
62
+ end
63
+
64
+ class Scenario<ActiveRecord::Base
65
+ belongs_to :run
66
+ has_many :steps
67
+ acts_as_reportable
68
+ end
69
+
70
+ class Step<ActiveRecord::Base
71
+ belongs_to :scenario
72
+ acts_as_reportable
73
+ end
74
+
75
+ class ParseError<ActiveRecord::Base
76
+ belongs_to :run
77
+ acts_as_reportable
78
+ end
79
+ end
80
+ #The ActiveRecordReporter will store the results of a test run in a database using ActiveRecord.
81
+ #
82
+ #The current implementation uses SQLite as the DBMS until we get enough time to implement the rest of the configuration.
83
+ #
84
+ #We store the RutemaConfiguration#context for every run so that reports for past runs can be recreated without running the actual tests again.
85
+ class ActiveRecordReporter<Reporter
86
+ def initialize definition
87
+ @definition=definition
88
+ @logger=definition[:logger]
89
+ @logger||=Patir.setup_logger
90
+ raise "No database file defined" unless definition[:dbfile]
91
+ connect
92
+ end
93
+
94
+ def report specifications,runner_states,parse_errors,configuration
95
+ run_entry=DB::Run.new
96
+ if configuration && configuration.context
97
+ run_entry.context=YAML.dump(configuration.context)
98
+ end
99
+ parse_errors.each do |pe|
100
+ er=DB::ParseError.new()
101
+ er.filename=pe[:filename]
102
+ er.error=pe[:error]
103
+ run_entry.parse_errors<<er
104
+ end
105
+ runner_states.each do |scenario|
106
+ sc=DB::Scenario.new
107
+ sc.name=scenario.sequence_name
108
+ sc.number=scenario.sequence_id
109
+ sc.start_time=scenario.start_time
110
+ sc.stop_time=scenario.stop_time
111
+ sc.status=scenario.status.to_s
112
+ #get the specification for this scenario
113
+ spec=specifications[scenario.sequence_name]
114
+ if spec
115
+ sc.version=spec.version
116
+ else
117
+ @logger.error("Could not find specification for #{scenario.sequence_name}")
118
+ end
119
+ if scenario.strategy==:attended
120
+ sc.attended=true
121
+ else
122
+ sc.attended=false
123
+ end
124
+ scenario.step_states.each do |number,step|
125
+ st=DB::Step.new
126
+ st.name=step[:name]
127
+ st.number=number
128
+ st.status=step[:status].to_s
129
+ st.output=step[:output]
130
+ st.error=step[:error]
131
+ st.duration=step[:duration]
132
+ sc.steps<<st
133
+ end
134
+ run_entry.scenarios<<sc
135
+ end
136
+ run_entry.save
137
+ end
138
+
139
+ private
140
+ def connect
141
+ ActiveRecord::Base.logger = @logger
142
+ @logger.info("Connecting with database '#{@definition[:dbfile]}'")
143
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
144
+ :database => @definition[:dbfile])
145
+ DB::Schema.migrate(:up) unless File.exists?(@definition[:dbfile])
146
+ end
147
+ end
148
+
149
+ end
@@ -57,6 +57,8 @@ module Rutema
57
57
  #
58
58
  #:requirements - An Array of String. The idea is that the strings can lead you back to the requirements specification that is tested here.
59
59
  #
60
+ #:version - The version of this specification
61
+ #
60
62
  #Default values are empty strings and arrays. (scenario is nil)
61
63
  def initialize *args
62
64
  params=args[0] if args
@@ -68,7 +70,7 @@ module Rutema
68
70
  @attributes[:title]||=""
69
71
  @attributes[:filename]||=""
70
72
  @attributes[:description]||=""
71
- @scenario=TestScenario.new
73
+ @scenario=TestScenario.new(@attributes[:version])
72
74
  @requirements||=Array.new
73
75
  end
74
76
  end
@@ -86,7 +88,8 @@ module Rutema
86
88
  include SpecificationElement
87
89
  attr_reader :steps
88
90
 
89
- def initialize
91
+ def initialize version=nil
92
+ @version=version
90
93
  @attended=false
91
94
  @steps=Array.new
92
95
  end
data/lib/rutema/system.rb CHANGED
@@ -4,22 +4,23 @@ require 'rexml/document'
4
4
 
5
5
  require 'rutema/specification'
6
6
  require 'rutema/configuration'
7
+ require 'rutema/reporter'
8
+
7
9
 
8
10
  require 'rubygems'
9
11
  require 'highline'
10
- require 'mailfactory'
11
12
  require 'patir/command'
12
13
 
13
14
  module Rutema
14
15
  VERSION_MAJOR=0
15
- VERSION_MINOR=2
16
+ VERSION_MINOR=3
16
17
  #Is raised when an error is found in a specification
17
18
  class ParserError<RuntimeError
18
19
  end
19
20
 
20
21
  #Base class that bombs out when used....
21
22
  class SpecificationParser
22
- def parse_specification
23
+ def parse_specification param
23
24
  raise ParserError,"not implemented. You should derive a parser implementation from SpecificationParser!"
24
25
  end
25
26
  end
@@ -176,6 +177,7 @@ module Rutema
176
177
  end
177
178
  end
178
179
 
180
+ #This class coordinates parsing, execution and reporting of test specifications
179
181
  class Coordinator
180
182
  attr_accessor :configuration,:parse_errors,:parsed_files
181
183
  def initialize configuration,logger=nil
@@ -190,6 +192,8 @@ module Rutema
190
192
  @configuration.tests.collect!{|t| File.expand_path(t)}
191
193
  @runner=create_runner
192
194
  @parsed_files=Array.new
195
+ #this will hold any specifications that are succesfully parsed.
196
+ @specifications=Hash.new
193
197
  end
194
198
  #Runs a set of tests
195
199
  #
@@ -224,11 +228,10 @@ module Rutema
224
228
  #It then joins the threads and returns when all of them are finished.
225
229
  def report
226
230
  threads=Array.new
227
- runner_status=Patir::CommandSequenceStatus.new("",@runner.states.values)
228
231
  #get the runner stati and the configuration and give it to the reporters
229
232
  @reporters.each do |reporter|
230
- threads<<Thread.new(reporter,runner_status,@parse_errors,@configuration) do |reporter,status,perrors,configuration|
231
- @logger.debug(reporter.report(status,perrors,configuration))
233
+ threads<<Thread.new(reporter,@specifications,@runner.states.values,@parse_errors,@configuration) do |reporter,specs,status,perrors,configuration|
234
+ @logger.debug(reporter.report(specs,status,perrors,configuration))
232
235
  end
233
236
  end
234
237
  threads.each do |t|
@@ -238,8 +241,7 @@ module Rutema
238
241
  end
239
242
 
240
243
  def to_s
241
- runner_status=Patir::CommandSequenceStatus.new("",@runner.states.values)
242
- "Parsed #{@parsed_files.size} files\n#{Rutema.text_report(runner_status,@parse_errors)}"
244
+ "Parsed #{@parsed_files.size} files\n#{Rutema.text_report(@runner.states.values,@parse_errors)}"
243
245
  end
244
246
  private
245
247
  def instantiate_class definition
@@ -277,7 +279,8 @@ module Rutema
277
279
  begin
278
280
  @parsed_files<<filename
279
281
  @parsed_files.uniq!
280
- return @parser.parse_specification(spec_file)
282
+ spec=@parser.parse_specification(spec_file)
283
+ @specifications[spec.name]=spec
281
284
  rescue ParserError
282
285
  @logger.error("Error parsing '#{spec_file}': #{$!.message}")
283
286
  @parse_errors<<{:filename=>filename,:error=>$!.message}
@@ -385,6 +388,11 @@ module Rutema
385
388
  @logger.warn("Attended scenario cannot be run in unattended mode")
386
389
  state..status=:warning
387
390
  else
391
+ if scenario.attended?
392
+ state.strategy=:attended
393
+ else
394
+ state.strategy=:unattended
395
+ end
388
396
  stps=scenario.steps
389
397
  if stps.empty?
390
398
  @logger.warn("Scenario #{name} contains no steps")
@@ -435,7 +443,7 @@ module Rutema
435
443
  end
436
444
  end
437
445
 
438
- #The application class
446
+ #The "executioner" application class
439
447
  class RutemaX
440
448
  require 'optparse'
441
449
  def initialize command_line_args
@@ -443,7 +451,7 @@ module Rutema
443
451
  @logger=Patir.setup_logger(@log_file)
444
452
  begin
445
453
  raise "No configuration file defined!" if !@config_file
446
- @configuration=RutemaConfigurator.new(@config_file,@logger).configuration
454
+ @configuration=RutemaXConfigurator.new(@config_file,@logger).configuration
447
455
  @coordinator=Coordinator.new(@configuration,@logger)
448
456
  application_flow
449
457
  rescue Patir::ConfigurationException
@@ -490,6 +498,7 @@ module Rutema
490
498
  end
491
499
  end
492
500
  end
501
+
493
502
  def application_flow
494
503
  if @check
495
504
  #run just the check test
@@ -506,95 +515,5 @@ module Rutema
506
515
  @coordinator.report
507
516
  end
508
517
  end
509
- #Reporter is meant as a base class for reporter classes.
510
- class Reporter
511
- #params should be a Hash containing the parameters used to initialize the class
512
- def initialize params
513
- end
514
-
515
- #Coordinator will pass the Rutema __configuration__ giving you access to the context which can contain data like headings and version numbers to use in the report.
516
- #
517
- #runner_status is a Patir::CommandSequenceStatus containing the status of the last run (so it contains all the Scenario stati for the loaded tests)
518
- #
519
- #parse_errors is an Array of {:filename,:error} hashes containing the errors encounter by the parser when loading the specifications
520
- def report runner_status,parse_errors,configuration
521
-
522
- end
523
- end
524
518
 
525
- #The following configuration keys are used by EmailReporter:
526
- #
527
- #:server - the smtp server to use
528
- #
529
- #:port - the port to use (defaults to 25)
530
- #
531
- #:sender - the sender of the email (defaults to rutema@domain)
532
- #
533
- #:recipients - an array of strings with the recipients of the report emails
534
- #
535
- #The :logger key is set by the Coordinator
536
- #
537
- #Customization keys:
538
- #
539
- #:subject - the string of this key will be prefixed as a subject for the email
540
- class EmailReporter
541
- attr_reader :last_message
542
- def initialize definition
543
- #get the logger
544
- @logger=definition[:logger]
545
- @logger||=Patir.setup_logger
546
- #extract the parameters from the definition
547
- #address and port of the smtp server
548
- @server=definition[:server]
549
- @port=definition[:port]
550
- @port||=25
551
- #the domain we're coming from
552
- @domain=definition[:domain]
553
- #construct the mail factory object
554
- @mail = MailFactory.new()
555
- @mail.from = definition[:sender]
556
- @mail.from||="rutema@#{@domain}"
557
- @recipients=definition[:recipients]
558
- @mail.to=@recipients
559
- #customize
560
- @subject=definition[:subject]
561
- @subject||=""
562
- #this is a way to test without sending
563
- @dummy=true if definition[:dummy]
564
- @logger.info("Reporter '#{self.to_s}' registered")
565
- end
566
-
567
- def to_s
568
- list=@recipients.join(', ')
569
- "EmailReporter - #{@server}:#{@port} from #{@mail.from} to #{list}"
570
- end
571
-
572
- def report runner_status,parse_errors,configuration
573
- @mail.subject = "#{@subject}"
574
- @mail.text = Rutema.text_report(runner_status,parse_errors)
575
- begin
576
- if @mail.to.empty?
577
- @logger.error("No recipients for the report mail")
578
- else
579
- #
580
- #~ if @password
581
- #~ #if a password is defined, use cram_md5 authentication
582
- #~ else
583
- Net::SMTP.start(@server, @port, @domain) {|smtp| smtp.sendmail(@mail.to_s(),@mail.from,mail_to)} unless @dummy
584
- #~ end
585
- end#recipients empty
586
- rescue
587
- @logger.error("Sending of email report failed: #{$!}")
588
- end
589
- @mail.to_s
590
- end
591
- end
592
- private
593
- def self.text_report runner_status,parse_errors
594
- msg="Parse errors: #{parse_errors.size}"
595
- parse_errors.each{|e| msg<<"\n\t#{e[:filename]}"}
596
- msg<<"\nCurrent run:\nScenarios: #{runner_status.step_states.size}"
597
- msg<<"\n#{runner_status.summary}"
598
- return msg
599
- end
600
519
  end
@@ -0,0 +1,3 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ configuration.load_from_file("valid_config.rb")
3
+ configuration.source="../test.db"
@@ -5,7 +5,7 @@ require 'test/unit'
5
5
  module TestRutema
6
6
  require 'rutema/system'
7
7
 
8
- class TestRutemaConfigurator<Test::Unit::TestCase
8
+ class TestRutemaXConfigurator<Test::Unit::TestCase
9
9
  def setup
10
10
  @prev_dir=Dir.pwd
11
11
  Dir.chdir(File.dirname(__FILE__))
@@ -16,7 +16,7 @@ module TestRutema
16
16
  def test_configuration
17
17
  cfg=nil
18
18
  #load the valid configuration
19
- assert_nothing_raised() { cfg=Rutema::RutemaConfigurator.new("samples/valid_config.rb").configuration}
19
+ assert_nothing_raised() { cfg=Rutema::RutemaXConfigurator.new("samples/valid_config.rb").configuration}
20
20
  assert_not_nil(cfg.parser)
21
21
  assert_not_nil(cfg.reporters)
22
22
  assert_equal(1, cfg.reporters.size)
@@ -29,7 +29,7 @@ module TestRutema
29
29
  assert_not_nil(cfg.context)
30
30
  end
31
31
  def test_specification_paths
32
- cfg=Rutema::RutemaConfigurator.new("samples/valid_config.rb").configuration
32
+ cfg=Rutema::RutemaXConfigurator.new("samples/valid_config.rb").configuration
33
33
  assert_not_nil(cfg.tests)
34
34
  end
35
35
  end
@@ -0,0 +1,32 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+ $:.unshift File.join(File.dirname(__FILE__),"..","ext")
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+ require 'fileutils'
6
+ require 'rutema/historian'
7
+ #$DEBUG=true
8
+ module TestRutema
9
+ class TestHistorian<Test::Unit::TestCase
10
+ DB_FILE="test.db"
11
+ def setup
12
+ @prev_dir=Dir.pwd
13
+ Dir.chdir(File.dirname(__FILE__))
14
+ @configuration=OpenStruct.new
15
+ @configuration.source=DB_FILE
16
+ #FileUtils.rm_rf(DB_FILE)
17
+ end
18
+ def teardown
19
+ Dir.chdir(@prev_dir)
20
+ end
21
+
22
+ def test_history
23
+ assert_nothing_raised() do
24
+ h=Rutema::Historian.new(@configuration)
25
+ h.history(:all)
26
+ h.history("test1")
27
+ h.history("test5")
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,74 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+ $:.unshift File.join(File.dirname(__FILE__),"..","ext")
3
+ require 'test/unit'
4
+ require 'ostruct'
5
+ require 'fileutils'
6
+ require 'rutema/reporter'
7
+ require 'rutema/reporter_ar'
8
+ #$DEBUG=true
9
+ module TestRutema
10
+ class MockCommand
11
+ include Patir::Command
12
+ def initialize number
13
+ @number=number
14
+ end
15
+ end
16
+ class TestActiveRecordReporter<Test::Unit::TestCase
17
+ DB_FILE="test.db"
18
+ def setup
19
+ @prev_dir=Dir.pwd
20
+ Dir.chdir(File.dirname(__FILE__))
21
+ @parse_errors=[{:filename=>"f.spec",:error=>"error"}]
22
+ test1=Patir::CommandSequenceStatus.new("test1")
23
+ test1.sequence_id=1
24
+ test1.strategy=:attended
25
+ test2=Patir::CommandSequenceStatus.new("test2")
26
+ test2.sequence_id=2
27
+ test2.strategy=:unattended
28
+ test1.step=MockCommand.new(1)
29
+ test2.step=MockCommand.new(2)
30
+ test2.step=MockCommand.new(3)
31
+ @status=[test1,test2]
32
+ FileUtils.rm_rf(DB_FILE)
33
+ end
34
+ def teardown
35
+ Dir.chdir(@prev_dir)
36
+ end
37
+
38
+ def test_report
39
+ spec1=OpenStruct.new(:name=>"test1")
40
+ spec2=OpenStruct.new(:name=>"test2",:version=>"10")
41
+ specs={"test1"=>spec1,
42
+ "test2"=>spec2
43
+ }
44
+ definition={:dbfile=>DB_FILE}
45
+ r=Rutema::ActiveRecordReporter.new(definition)
46
+ #without configuration
47
+ assert_nothing_raised() { r.report(specs,@status,@parse_errors,nil) }
48
+ configuration=OpenStruct.new
49
+ #without context member
50
+ assert_nothing_raised() { r.report(specs,@status,@parse_errors,configuration) }
51
+ #with a nil context
52
+ configuration.context=nil
53
+ assert_nothing_raised() { r.report(specs,@status,@parse_errors,configuration) }
54
+ #with some context
55
+ configuration.context="context"
56
+ assert_nothing_raised() { r.report(specs,@status,@parse_errors,configuration) }
57
+ end
58
+ end
59
+ class TestEmailReporter<Test::Unit::TestCase
60
+ def setup
61
+ @parse_errors=[{:filename=>"f.spec",:error=>"error"}]
62
+ st=Patir::CommandSequenceStatus.new("test_seq")
63
+ st.step=MockCommand.new(1)
64
+ st.step=MockCommand.new(2)
65
+ st.step=MockCommand.new(3)
66
+ @status=[st]
67
+ end
68
+ def test_new
69
+ definition={:server=>"localhost",:port=>25,:recipients=>["test"],:sender=>"rutema",:subject=>"test",:dummy=>true}
70
+ r=Rutema::EmailReporter.new(definition)
71
+ assert_nothing_raised() { puts r.report(nil,@status,@parse_errors,nil) }
72
+ end
73
+ end
74
+ end
data/test/test_system.rb CHANGED
@@ -6,12 +6,6 @@ require 'ostruct'
6
6
  #$DEBUG=true
7
7
  module TestRutema
8
8
  require 'rutema/system'
9
- class MockCommand
10
- include Patir::Command
11
- def initialize number
12
- @number=number
13
- end
14
- end
15
9
  class TestBaseXMlParser<Test::Unit::TestCase
16
10
  SAMPLE_SPEC=<<EOT
17
11
  <specification name="sample">
@@ -104,18 +98,4 @@ EOT
104
98
  end
105
99
  end
106
100
 
107
- class TestEmailReporter<Test::Unit::TestCase
108
- def setup
109
- @parse_errors=[{:filename=>"f.spec",:error=>"error"}]
110
- @status=Patir::CommandSequenceStatus.new("test_seq")
111
- @status.step=MockCommand.new(1)
112
- @status.step=MockCommand.new(2)
113
- @status.step=MockCommand.new(3)
114
- end
115
- def test_new
116
- definition={:server=>"localhost",:port=>25,:recipients=>["test"],:sender=>"rutema",:subject=>"test",:dummy=>true}
117
- r=Rutema::EmailReporter.new(definition)
118
- assert_nothing_raised() { puts r.report(@status,@parse_errors,nil) }
119
- end
120
- end
121
101
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.1
3
3
  specification_version: 1
4
4
  name: rutema
5
5
  version: !ruby/object:Gem::Version
6
- version: "0.2"
7
- date: 2007-05-21 00:00:00 +02:00
6
+ version: "0.3"
7
+ date: 2007-05-30 00:00:00 +02:00
8
8
  summary: rutema is a test execution and management framework for heterogeneous testing environments
9
9
  require_paths:
10
10
  - lib
@@ -34,11 +34,19 @@ files:
34
34
  - README.txt
35
35
  - COPYING.txt
36
36
  - Rakefile
37
+ - bin/rutemax
38
+ - bin/rutemah
37
39
  - lib/rutema/configuration.rb
38
40
  - lib/rutema/specification.rb
39
41
  - lib/rutema/system.rb
42
+ - lib/rutema/reporter.rb
43
+ - lib/rutema/reporter_ar.rb
44
+ - lib/rutema/historian.rb
45
+ - test/test_configuration.rb
40
46
  - test/test_specification.rb
41
47
  - test/test_system.rb
48
+ - test/test_historian.rb
49
+ - test/test_reporter.rb
42
50
  - test/samples/check.spec
43
51
  - test/samples/setup.spec
44
52
  - test/samples/teardown.spec
@@ -46,16 +54,24 @@ files:
46
54
  - test/samples/tests/no_title.spec
47
55
  - test/samples/tests/sample.spec
48
56
  - test/samples/valid_config.rb
57
+ - test/samples/rutemah_config.rb
49
58
  test_files:
50
59
  - test/test_configuration.rb
60
+ - test/test_historian.rb
61
+ - test/test_reporter.rb
51
62
  - test/test_specification.rb
52
63
  - test/test_system.rb
53
- rdoc_options: []
54
-
55
- extra_rdoc_files: []
56
-
64
+ rdoc_options:
65
+ - --main
66
+ - README.txt
67
+ extra_rdoc_files:
68
+ - History.txt
69
+ - Manifest.txt
70
+ - README.txt
71
+ - COPYING.txt
57
72
  executables:
58
73
  - rutemax
74
+ - rutemah
59
75
  extensions: []
60
76
 
61
77
  requirements: []
@@ -68,7 +84,7 @@ dependencies:
68
84
  requirements:
69
85
  - - ">="
70
86
  - !ruby/object:Gem::Version
71
- version: "0.3"
87
+ version: "0.4"
72
88
  version:
73
89
  - !ruby/object:Gem::Dependency
74
90
  name: highline
@@ -88,6 +104,24 @@ dependencies:
88
104
  - !ruby/object:Gem::Version
89
105
  version: 0.0.0
90
106
  version:
107
+ - !ruby/object:Gem::Dependency
108
+ name: activerecord
109
+ version_requirement:
110
+ version_requirements: !ruby/object:Gem::Version::Requirement
111
+ requirements:
112
+ - - ">"
113
+ - !ruby/object:Gem::Version
114
+ version: 0.0.0
115
+ version:
116
+ - !ruby/object:Gem::Dependency
117
+ name: ruport
118
+ version_requirement:
119
+ version_requirements: !ruby/object:Gem::Version::Requirement
120
+ requirements:
121
+ - - ">"
122
+ - !ruby/object:Gem::Version
123
+ version: 0.0.0
124
+ version:
91
125
  - !ruby/object:Gem::Dependency
92
126
  name: hoe
93
127
  version_requirement:
@@ -95,5 +129,5 @@ dependencies:
95
129
  requirements:
96
130
  - - ">="
97
131
  - !ruby/object:Gem::Version
98
- version: 1.2.0
132
+ version: 1.2.1
99
133
  version: