rutema 1.3.0 → 2.0.0.pre

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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +204 -194
  3. data/Manifest.txt +15 -48
  4. data/README.md +55 -61
  5. data/bin/rutema +7 -7
  6. data/lib/rutema/application.rb +61 -0
  7. data/lib/rutema/core/configuration.rb +195 -0
  8. data/lib/rutema/core/engine.rb +186 -0
  9. data/lib/rutema/core/framework.rb +28 -0
  10. data/lib/rutema/{objectmodel.rb → core/objectmodel.rb} +43 -48
  11. data/lib/rutema/core/parser.rb +35 -0
  12. data/lib/rutema/core/reporter.rb +105 -0
  13. data/lib/rutema/core/runner.rb +83 -0
  14. data/lib/rutema/elements/minimal.rb +47 -44
  15. data/lib/rutema/parsers/xml.rb +154 -186
  16. data/lib/rutema/version.rb +9 -0
  17. metadata +39 -108
  18. data/README.txt +0 -44
  19. data/Rakefile +0 -30
  20. data/examples/README.md +0 -17
  21. data/examples/config/database.rutema +0 -17
  22. data/examples/config/full.rutema +0 -27
  23. data/examples/config/minimal.rutema +0 -10
  24. data/examples/specs/T001.spec +0 -8
  25. data/examples/specs/T002.spec +0 -8
  26. data/examples/specs/T003.spec +0 -8
  27. data/examples/specs/T004.spec +0 -8
  28. data/examples/specs/T005.spec +0 -10
  29. data/examples/specs/T006.spec +0 -9
  30. data/examples/specs/check.spec +0 -8
  31. data/examples/specs/fail.spec +0 -9
  32. data/examples/specs/include.scenario +0 -5
  33. data/examples/specs/rutema.spec +0 -10
  34. data/examples/specs/setup.spec +0 -8
  35. data/examples/specs/teardown.spec +0 -8
  36. data/lib/rutema/configuration.rb +0 -173
  37. data/lib/rutema/models/activerecord.rb +0 -159
  38. data/lib/rutema/models/base.rb +0 -5
  39. data/lib/rutema/parsers/base.rb +0 -45
  40. data/lib/rutema/rake.rb +0 -62
  41. data/lib/rutema/reporters/activerecord.rb +0 -82
  42. data/lib/rutema/reporters/base.rb +0 -23
  43. data/lib/rutema/reporters/email.rb +0 -84
  44. data/lib/rutema/reporters/text.rb +0 -77
  45. data/lib/rutema/runners/default.rb +0 -157
  46. data/lib/rutema/runners/step.rb +0 -23
  47. data/lib/rutema/system.rb +0 -302
  48. data/test/data/duplicate_name.spec +0 -8
  49. data/test/data/no_title.spec +0 -5
  50. data/test/data/sample.spec +0 -8
  51. data/test/data/test_identifiers.rutema +0 -7
  52. data/test/test_activerecord.rb +0 -0
  53. data/test/test_configuration.rb +0 -43
  54. data/test/test_objectmodel.rb +0 -82
  55. data/test/test_parsers.rb +0 -131
  56. data/test/test_reporters.rb +0 -115
  57. data/test/test_runners.rb +0 -70
  58. data/test/test_system.rb +0 -45
@@ -1,159 +0,0 @@
1
- # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
- $:.unshift File.join(File.dirname(__FILE__),'..','..')
3
- require 'rutema/models/base'
4
- require 'active_record'
5
-
6
- #this fixes the AR Logger hack that annoys me sooooo much
7
- class Logger
8
- private
9
- def format_message(severity, datetime, progname, msg)
10
- (@formatter || @default_formatter).call(severity, datetime, progname, msg)
11
- end
12
- end
13
- module Rutema
14
- module ActiveRecord
15
- #This is the schema for the AR database used to store test results
16
- #
17
- #We store the RutemaConfiguration#context for every run so that reports for past runs can be recreated without running the actual tests again.
18
- class Schema< ::ActiveRecord::Migration
19
- def self.up
20
- create_table :runs do |t|
21
- t.column :context, :string
22
- end
23
-
24
- create_table :scenarios do |t|
25
- t.column :name, :string, :null=>false
26
- t.column :run_id,:integer, :null=>false
27
- t.column :attended,:bool, :null=>false
28
- t.column :status, :string,:null=>false
29
- t.column :number,:integer
30
- t.column :start_time, :datetime,:null=>false
31
- t.column :stop_time, :datetime
32
- t.column :version, :string
33
- t.column :title, :string
34
- t.column :description, :string
35
- end
36
-
37
- create_table :steps do |t|
38
- t.column :scenario_id,:integer, :null=>false
39
- t.column :name, :string
40
- t.column :number, :integer,:null=>false
41
- t.column :status, :string,:null=>false
42
- t.column :output, :text
43
- t.column :error, :text
44
- t.column :duration, :decimal
45
- end
46
-
47
- create_table :parse_errors do |t|
48
- t.column :filename, :string,:null=>false
49
- t.column :error, :string
50
- t.column :run_id,:integer, :null=>false
51
- end
52
- end
53
- end
54
- class Run< ::ActiveRecord::Base
55
- has_many :scenarios
56
- has_many :parse_errors
57
- serialize :context
58
- end
59
- class Scenario< ::ActiveRecord::Base
60
- belongs_to :run
61
- has_many :steps
62
- end
63
- class Step< ::ActiveRecord::Base
64
- belongs_to :scenario
65
- end
66
- class ParseError< ::ActiveRecord::Base
67
- belongs_to :run
68
- end
69
- #Exports the contents of the database/model as a yaml dump
70
- class Export
71
- def initialize params
72
- @logger = params[:logger]
73
- @logger ||= Patir.setup_logger
74
- @result_set_size = params[:result_set_size]
75
- @result_set_size ||= 1000
76
- @currently_on_no=0
77
- database_configuration = params[:db]
78
- raise "No database configuration defined, missing :db configuration key." unless database_configuration
79
- ActiveRecord.connect(database_configuration,@logger)
80
- end
81
- def next
82
- @logger.info("Found #{Run.count} runs") if @currently_on_no==0
83
- @logger.info("Exporting from #{@currently_on_no} to #{@currently_on_no+@result_set_size}")
84
- export(@result_set_size)
85
- end
86
- def all
87
- @logger.info("Found #{Run.count} runs")
88
- export(nil)
89
- end
90
- private
91
- def export offset=nil
92
- if offset
93
- runs=Run.find(:all,:order=>"id ASC",:limit=>@result_set_size,:offset=>@currently_on_no)
94
- @currently_on_no+=offset
95
- else
96
- runs=Run.find(:all)
97
- end
98
- return nil if runs.empty?
99
- export=[]
100
- runs.each do |run|
101
- e={:parse_errors=>[],:scenarios=>[],:context=>run.context}
102
- run.parse_errors.each { |pe| e[:parse_errors]<<{:filename=>pe.filename, :error=>pe.error} }
103
- run.scenarios.each { |sc| e[:scenarios]<<export_scenario(sc) }
104
- export<<e
105
- @logger.debug("Exported #{run.id}")
106
- end
107
- return export
108
- end
109
- def export_scenario sc
110
- scenario={:name=>sc[:name],
111
- :attended=>sc[:attended],
112
- :status=>sc[:status],
113
- :number=>sc[:number],
114
- :start_time=>sc[:start_time],
115
- :stop_time=>sc[:stop_time],
116
- :version=>sc[:version],
117
- :title=>sc[:title],
118
- :description=>sc[:description],
119
- :steps=>[]
120
- }
121
- sc.steps.each do |step|
122
- st={:name=>step[:name],
123
- :number=>step[:number],
124
- :status=>step[:status],
125
- :output=>step[:output],
126
- :error=>step[:error],
127
- :duration=>step[:duration]
128
- }
129
- scenario[:steps]<<st
130
- end
131
- return scenario
132
- end
133
- end
134
- #Establishes an ActiveRecord connection
135
- def self.connect cfg,logger
136
- conn=cnct(cfg,logger)
137
- Schema.migrate(:up) if perform_migration?(cfg)
138
- end
139
- private
140
- #Establishes an active record connection using the cfg hash
141
- #There is only a rudimentary check to ensure the integrity of cfg
142
- def self.cnct cfg,logger
143
- if cfg[:adapter] && cfg[:database]
144
- logger.debug("Connecting to #{cfg[:database]}")
145
- return ::ActiveRecord::Base.establish_connection(cfg)
146
- else
147
- raise Rutema::ConnectionError,"Erroneous database configuration. Missing :adapter and/or :database"
148
- end
149
- end
150
- def self.perform_migration? cfg
151
- return true if cfg[:migrate]
152
- #special case for sqlite3
153
- if cfg[:adapter]=="sqlite3" && !File.exists?(cfg[:database])
154
- return true
155
- end
156
- return false
157
- end
158
- end
159
- end
@@ -1,5 +0,0 @@
1
- module Rutema
2
- #Exception occuring when connecting to a database
3
- class ConnectionError<RuntimeError
4
- end
5
- end
@@ -1,45 +0,0 @@
1
- # Copyright (c) 2007-2011 Vassilis Rizopoulos. All rights reserved.
2
- $:.unshift File.join(File.dirname(__FILE__),'..','..')
3
-
4
- module Rutema
5
- #Is raised when an error is found in a specification
6
- class ParserError<RuntimeError
7
- end
8
- #Base class that bombs out when used.
9
- #
10
- #By default the internal logger will log to the console if no logger is provided.
11
- class SpecificationParser
12
- attr_reader :configuration
13
- #Expects a hash with at least {:configuration, :logger}
14
- #
15
- #At the end validate_configuration is called
16
- def initialize params
17
- @configuration=params[:configuration]
18
- @logger=params[:logger]
19
- unless @logger
20
- @logger=Patir.setup_logger
21
- @configuration||={}
22
- @configuration[:logger]=@logger
23
- end
24
- @logger.warn("No system configuration provided to the parser") unless @configuration
25
- validate_configuration
26
- end
27
- #parses a specification
28
- def parse_specification param
29
- raise ParserError,"not implemented. You should derive a parser implementation from SpecificationParser!"
30
- end
31
- #parses the setup script. By default calls parse_specification
32
- def parse_setup param
33
- parse_specification(param)
34
- end
35
- #parses the teardown script. By default calls parse_specification
36
- def parse_teardown param
37
- parse_specification(param)
38
- end
39
- #The parser stores it's configuration in @configuration
40
- #
41
- #To avoid validating the configuration in element_ methods repeatedly, do all configuration validation here
42
- def validate_configuration
43
- end
44
- end
45
- end
data/lib/rutema/rake.rb DELETED
@@ -1,62 +0,0 @@
1
- require 'rutema/system'
2
- require 'optparse'
3
- require 'rake'
4
-
5
- module Rutema
6
- #Integrates rutema with rake.
7
- #
8
- #You can pass a hash with the parameters or use the block syntax:
9
- # RakeTask.new do |rt|
10
- # rt.config_file="config.rutema"
11
- # rt.dependencies=[]
12
- # rt.add_dependency("some_other_task")
13
- # rt.name="name"
14
- # rt.log_file="."
15
- # end
16
- class RakeTask
17
- attr_accessor :config_file, :log_file, :name
18
- attr_reader :rake_task
19
- #Params is a parameter hash.
20
- #
21
- #Valid parameters are:
22
- #
23
- #:config_file => path to the configuration file
24
- #
25
- #:log_file => path to the file where the log is saved. If missing then the logger prints in stdout
26
- #
27
- #:name => the name for the rutema task. If missing then the task is named rutema, otherwise it will be rutema:name
28
- #
29
- #:dependencies => an array of dependencies for the task
30
- def initialize params=nil
31
- params||={}
32
- @config_file=params[:config_file]
33
- @log_file=params[:log]
34
- @name=params[:name]
35
- @dependencies=params[:dependencies]
36
- @dependencies||=[]
37
- yield self if block_given?
38
- @dependencies||=[]
39
- raise "No rutema configuration given, :config_file is nil" unless @config_file
40
- args=['-c',@config_file]
41
- args+=['-l',@log_file] if @log_file
42
- args<<"all"
43
- OptionParser::Arguable.extend_object(args)
44
- if @name
45
- desc "Executes the tests in #{File.basename(@config_file)}"
46
- @rake_task=task :"rutema:#{@name}" => @dependencies do
47
- Rutema::RutemaX.new(args)
48
- end
49
- else
50
- desc "Executes the tests in #{File.basename(@config_file)}"
51
- @rake_task=task :rutema => @dependencies do
52
- Rutema::RutemaX.new(args)
53
- end
54
- end
55
- end
56
- #Adds a dependency to the rutema task created
57
- def add_dependency dependency
58
- @dependencies<<dependency
59
- task @rake_task => [dependency] if @rake_task
60
- end
61
- end
62
- end
@@ -1,82 +0,0 @@
1
- # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
- require 'rutema/models/activerecord'
3
-
4
- module Rutema
5
- #The ActiveRecordReporter will store the results of a test run in a database using ActiveRecord.
6
- class ActiveRecordReporter
7
- #The required keys in this reporter's configuration are:
8
- # :db - the database configuration. A Hash with the DB adapter information
9
- # :db=>{:database=>"sample.rb"}
10
- def initialize definition
11
- @logger=definition[:logger]
12
- @logger||=Patir.setup_logger
13
- database_configuration = definition[:db]
14
- raise "No database configuration defined, missing :db configuration key." unless database_configuration
15
- $:.unshift File.join(File.dirname(__FILE__),"..","..")
16
- require 'rutema/models/activerecord'
17
- Rutema::ActiveRecord.connect(database_configuration,@logger)
18
- @logger.info("Reporter #{self.to_s} registered")
19
- end
20
- #We get all the data for a Rutema::ActiveRecord::Run entry in here.
21
- #
22
- #If the configuration is given and there is a context defined, this will be YAML-dumped into Rutema::ActiveRecord::Run#context
23
- def report specifications,runner_states,parse_errors,configuration
24
- run_entry=Rutema::ActiveRecord::Run.new
25
- if configuration && configuration.context
26
- run_entry.context=configuration.context
27
- end
28
- parse_errors.each do |pe|
29
- er=Rutema::ActiveRecord::ParseError.new()
30
- er.filename=pe[:filename]
31
- er.error=pe[:error]
32
- run_entry.parse_errors<<er
33
- end
34
- runner_states.compact!
35
- runner_states.each do |scenario|
36
- sc=Rutema::ActiveRecord::Scenario.new
37
- sc.name=scenario.sequence_name
38
- sc.number=scenario.sequence_id
39
- sc.start_time=scenario.start_time
40
- sc.stop_time=scenario.stop_time
41
- sc.status=scenario.status.to_s
42
- #get the specification for this scenario
43
- spec=specifications[scenario.sequence_name]
44
- if spec
45
- sc.version=spec.version if spec.has_version?
46
- sc.title=spec.title
47
- sc.description=spec.description
48
- else
49
- @logger.debug("Could not find specification for #{scenario.sequence_name}")
50
- sc.title=scenario.sequence_name
51
- sc.description=""
52
- end
53
- if scenario.strategy==:attended
54
- sc.attended=true
55
- else
56
- sc.attended=false
57
- end
58
- scenario.step_states.each do |number,step|
59
- st=Rutema::ActiveRecord::Step.new
60
- st.name=step[:name]
61
- st.number=number
62
- st.status="#{step[:status]}"
63
- st.output=sanitize(step[:output])
64
- st.error=sanitize(step[:error])
65
- st.duration=step[:duration]
66
- sc.steps<<st
67
- end
68
- run_entry.scenarios<<sc
69
- end
70
- run_entry.save!
71
- "activerecord reporter done"
72
- end
73
- def to_s#:nodoc:
74
- "ActiveRecordReporter"
75
- end
76
- private
77
- def sanitize text
78
- return text.gsub("\000","") if text
79
- return ""
80
- end
81
- end
82
- end
@@ -1,23 +0,0 @@
1
- # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
- $:.unshift File.join(File.dirname(__FILE__),"..")
3
- module Rutema
4
- #Reporter is meant as a base class for reporter classes. Which means that it is here for ducumentation purposes.
5
- #
6
- #In order to create act as a Reporter for Rutema a class only need to implement the #report method
7
- class Reporter
8
- #params should be a Hash containing the parameters used to initialize the class
9
- def initialize params
10
- end
11
-
12
- #Coordinator will pass the Rutema __configuration__ giving you access to the context which can contain data like
13
- #headings and build numbers to use in the report.
14
- #
15
- #It will also pass the specifications used in the last run so that data like the title and the specification version can be used.
16
- #
17
- #runner_states is an Array of Patir::CommandSequenceStatus containing the stati of the last run (so it contains all the Scenario stati for the loaded tests)
18
- #
19
- #parse_errors is an Array of {:filename,:error} hashes containing the errors encountered by the parser when loading the specifications
20
- def report specifications,runner_states,parse_errors,configuration
21
- end
22
- end
23
- end
@@ -1,84 +0,0 @@
1
- # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
- $:.unshift File.join(File.dirname(__FILE__),"..","..")
3
- require 'net/smtp'
4
- require 'mailfactory'
5
- require 'rutema/reporters/text'
6
-
7
- module Rutema
8
- #The following configuration keys are used by EmailReporter:
9
- #
10
- #:server - the smtp server to use
11
- #
12
- #:port - the port to use (defaults to 25)
13
- #
14
- #:domain - the domain the mail is coming from
15
- #
16
- #:sender - the sender of the email (defaults to rutema@domain)
17
- #
18
- #:recipients - an array of strings with the recipients of the report emails
19
- #
20
- #The :logger key is set by the Coordinator
21
- #
22
- #Customization keys:
23
- #
24
- #:subject - the string of this key will be prefixed as a subject for the email
25
- #
26
- #:verbose - when true, the report contains info on setup and teardown specs. Optional. Default is false
27
- class EmailReporter
28
- attr_reader :last_message
29
- def initialize definition
30
- #get the logger
31
- @logger=definition[:logger]
32
- @logger||=Patir.setup_logger
33
- #extract the parameters from the definition
34
- #address and port of the smtp server
35
- @server=definition[:server]
36
- @port=definition[:port]
37
- @port||=25
38
- #the domain we're coming from
39
- @domain=definition[:domain]
40
- #construct the mail factory object
41
- @mail = MailFactory.new()
42
- @mail.from = definition[:sender]
43
- @mail.from||="rutema@#{@domain}"
44
- @recipients=definition[:recipients]
45
- #customize
46
- @subject=definition[:subject]
47
- @subject||=""
48
- @footer=definition[:footer]
49
- @footer||=""
50
- @verbose=definition[:verbose]
51
- @verbose||=false
52
- @logger.info("Reporter '#{self.to_s}' registered")
53
- end
54
- def to_s#:nodoc:
55
- list=@recipients.join(', ')
56
- "EmailReporter - #{@server}:#{@port} from #{@mail.from} to #{list}"
57
- end
58
-
59
- def report specifications,runner_states,parse_errors,configuration
60
- @mail.subject = "#{@subject}"
61
- txt=TextReporter.new(:verbose=>@verbose).report(specifications,runner_states,parse_errors,configuration)
62
- txt<<"\n\n#{@footer}"
63
- @mail.text = txt
64
- begin
65
- if @recipients.empty?
66
- @logger.error("No recipients for the report mail")
67
- else
68
- #
69
- #~ if @password
70
- #~ #if a password is defined, use cram_md5 authentication
71
- #~ else
72
- @logger.info("Emailing through #{@server}:#{@port}(#{@domain})")
73
- Net::SMTP.start(@server, @port, @domain) {|smtp| smtp.send_message(@mail.to_s(),@mail.from,@recipients)}
74
- #~ end
75
- end#recipients empty
76
- rescue
77
- @logger.debug($!)
78
- @logger.error("Sending of email report failed: #{$!}")
79
- @logger.debug("Tried to sent to #{@recipients}")
80
- end
81
- @mail.to_s
82
- end
83
- end
84
- end