rutema 1.0.9 → 1.1.0

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.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.1.0 /2010-12
2
+ * Added Rutema::RakeTask class to allow integration of the test runner with rake
3
+ * Email reporting now suppresses _setup and _teardown entries unless it's configured as verbose. To do this add a :verbose=>true entry in the reporter configuration
4
+ * Fixed a bug, where on a setup spec failure the state of the actual spec was nil
5
+ * added YAML dump reporter
6
+ * Fixed a bug in the initialization of StepRunner that prevented use of --step
1
7
  == 1.0.9 / 2010-03-22
2
8
  * Fixed (hopefully) a nagging bug in activerecord reporter where it would crash if a step had status nil.
3
9
  * Fixed the same behaviour in the text reporter
data/Manifest.txt CHANGED
@@ -9,11 +9,14 @@ distro_test.sh
9
9
  lib/rutema/configuration.rb
10
10
  lib/rutema/gems.rb
11
11
  lib/rutema/model.rb
12
+ lib/rutema/rake.rb
12
13
  lib/rutema/reporter.rb
13
14
  lib/rutema/reporters/activerecord.rb
14
15
  lib/rutema/reporters/email.rb
15
16
  lib/rutema/reporters/standard_reporters.rb
16
17
  lib/rutema/reporters/text.rb
18
+ lib/rutema/reporters/yaml.rb
19
+ lib/rutema/reporters/couchdb.rb
17
20
  lib/rutema/specification.rb
18
21
  lib/rutema/system.rb
19
22
  selftest.sh
@@ -38,4 +41,5 @@ test/test_model.rb
38
41
  test/test_reporter.rb
39
42
  test/test_specification.rb
40
43
  test/test_system.rb
44
+ test/test_couchdb.rb
41
45
 
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  # -*- ruby -*-
3
3
  $:.unshift File.join(File.dirname(__FILE__),"lib")
4
4
  $:.unshift File.join(File.dirname(__FILE__),"ext")
@@ -17,11 +17,12 @@ Hoe.spec('rutema') do |p|
17
17
  p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
18
18
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
19
19
  p.extra_deps<<['patir',">=0.6.4"]
20
- p.extra_deps<<['highline']
21
- p.extra_deps<<['mailfactory']
22
- p.extra_deps<<['activerecord','2.3.4']
23
- p.extra_deps<<['ruport','1.6.1']
20
+ p.extra_deps<<['highline','1.5.2']
21
+ p.extra_deps<<['mailfactory','1.4.0']
22
+ p.extra_deps<<['activerecord','2.3.8']
23
+ p.extra_deps<<['ruport','1.6.3']
24
24
  p.extra_deps<<['acts_as_reportable','1.1.1']
25
+ p.extra_deps<<['couchrest','=0.37']
25
26
  p.spec_extras={:executables=>["rutemax","rutema_upgrader"],
26
27
  :default_executable=>"rutemax"}
27
28
  end
data/bin/rutema_upgrader CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2008-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  require 'rutema/system'
3
3
  require 'patir/base'
4
4
 
data/bin/rutemax CHANGED
@@ -1,4 +1,8 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  require 'rutema/gems'
3
3
  require 'rutema/system'
4
- Rutema::RutemaX.new(ARGV)
4
+ begin
5
+ Rutema::RutemaX.new(ARGV)
6
+ rescue
7
+ exit 1
8
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..")
3
3
 
4
4
  module Rutema
data/lib/rutema/gems.rb CHANGED
@@ -1,3 +1,4 @@
1
- gem 'activerecord','2.3.4'
1
+ gem 'activerecord','2.3.8'
2
2
  gem 'patir',">=0.6.4"
3
3
  gem 'acts_as_reportable','=1.1.1'
4
+ gem 'couchrest','=0.37'
data/lib/rutema/model.rb CHANGED
@@ -1,7 +1,9 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..")
3
3
  require 'active_record'
4
4
  require 'ruport/acts_as_reportable'
5
+ require 'patir/base'
6
+ require 'couchrest'
5
7
  #this fixes the AR Logger hack that annoys me sooooo much
6
8
  class Logger
7
9
  private
@@ -10,84 +12,218 @@ class Logger
10
12
  end
11
13
  end
12
14
  module Rutema
13
- #This is the ActiveRecord model for Rutema:
14
- #
15
- #A Run has n instances of executed scenarios - which in turn have n instances of executed steps -
16
- #and n instances of parse errors.
17
- module Model
18
- #This is the schema for the AR database used to store test results
15
+ module ActiveRecord
16
+ #Exception occuring when connecting to a database
17
+ class ConnectionError<RuntimeError
18
+ end
19
+ #This is the ActiveRecord model for Rutema:
19
20
  #
20
- #We store the RutemaConfiguration#context for every run so that reports for past runs can be recreated without running the actual tests again.
21
- class Schema<ActiveRecord::Migration
22
- def self.up
23
- create_table :runs do |t|
24
- t.column :context, :string
25
- end
21
+ #A Run has n instances of executed scenarios - which in turn have n instances of executed steps -
22
+ #and n instances of parse errors.
23
+ module Model
24
+ #This is the schema for the AR database used to store test results
25
+ #
26
+ #We store the RutemaConfiguration#context for every run so that reports for past runs can be recreated without running the actual tests again.
27
+ class Schema< ::ActiveRecord::Migration
28
+ def self.up
29
+ create_table :runs do |t|
30
+ t.column :context, :string
31
+ end
26
32
 
27
- create_table :scenarios do |t|
28
- t.column :name, :string, :null=>false
29
- t.column :run_id,:integer, :null=>false
30
- t.column :attended,:bool, :null=>false
31
- t.column :status, :string,:null=>false
32
- t.column :number,:integer
33
- t.column :start_time, :datetime,:null=>false
34
- t.column :stop_time, :datetime
35
- t.column :version, :string
36
- t.column :title, :string
37
- t.column :description, :string
38
- end
33
+ create_table :scenarios do |t|
34
+ t.column :name, :string, :null=>false
35
+ t.column :run_id,:integer, :null=>false
36
+ t.column :attended,:bool, :null=>false
37
+ t.column :status, :string,:null=>false
38
+ t.column :number,:integer
39
+ t.column :start_time, :datetime,:null=>false
40
+ t.column :stop_time, :datetime
41
+ t.column :version, :string
42
+ t.column :title, :string
43
+ t.column :description, :string
44
+ end
45
+
46
+ create_table :steps do |t|
47
+ t.column :scenario_id,:integer, :null=>false
48
+ t.column :name, :string
49
+ t.column :number, :integer,:null=>false
50
+ t.column :status, :string,:null=>false
51
+ t.column :output, :text
52
+ t.column :error, :text
53
+ t.column :duration, :decimal
54
+ end
39
55
 
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, :decimal
56
+ create_table :parse_errors do |t|
57
+ t.column :filename, :string,:null=>false
58
+ t.column :error, :string
59
+ t.column :run_id,:integer, :null=>false
60
+ end
48
61
  end
62
+ end
63
+
64
+ class Run< ::ActiveRecord::Base
65
+ has_many :scenarios
66
+ has_many :parse_errors
67
+ serialize :context
68
+ acts_as_reportable
69
+ end
49
70
 
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
71
+ class Scenario< ::ActiveRecord::Base
72
+ belongs_to :run
73
+ has_many :steps
74
+ acts_as_reportable
75
+ end
76
+
77
+ class Step< ::ActiveRecord::Base
78
+ belongs_to :scenario
79
+ acts_as_reportable
80
+ end
81
+
82
+ class ParseError< ::ActiveRecord::Base
83
+ belongs_to :run
84
+ acts_as_reportable
85
+ end
86
+
87
+ class UpgradeV9toV10< ::ActiveRecord::Migration
88
+ def self.up
89
+ puts("Adding new columns")
90
+ add_column(:scenarios, :title, :string,{:default=>"title"})
91
+ add_column(:scenarios, :description, :string,{:default=>"description"})
92
+ puts("Updating existing scenario entries")
93
+ Rutema::Model::Scenario.find(:all).each do |sc|
94
+ puts "Updating scenario #{sc.id}"
95
+ sc.title="#{name}"
96
+ sc.description="#{name}"
97
+ end
54
98
  end
55
99
  end
56
100
  end
57
101
 
58
- class Run<ActiveRecord::Base
59
- has_many :scenarios
60
- has_many :parse_errors
61
- serialize :context
62
- acts_as_reportable
102
+ #Exports the contents of the database/model as a yaml dump
103
+ class Export
104
+ def initialize params
105
+ @logger = params[:logger]
106
+ @logger ||= Patir.setup_logger
107
+ @result_set_size = params[:result_set_size]
108
+ @result_set_size ||= 1000
109
+ @currently_on_no=0
110
+ database_configuration = params[:db]
111
+ raise "No database configuration defined, missing :db configuration key." unless database_configuration
112
+ ActiveRecord.connect(database_configuration,@logger)
113
+ end
114
+
115
+ def next
116
+ @logger.info("Found #{Model::Run.count} runs") if @currently_on_no==0
117
+ @logger.info("Exporting from #{@currently_on_no} to #{@currently_on_no+@result_set_size}")
118
+ export(@result_set_size)
119
+ end
120
+
121
+ def all
122
+ @logger.info("Found #{Model::Run.count} runs")
123
+ export(nil)
124
+ end
125
+ private
126
+ def export offset=nil
127
+ if offset
128
+ runs=Model::Run.find(:all,:order=>"id ASC",:limit=>@result_set_size,:offset=>@currently_on_no)
129
+ @currently_on_no+=offset
130
+ else
131
+ runs=Model::Run.find(:all)
132
+ end
133
+ return nil if runs.empty?
134
+ export=[]
135
+ runs.each do |run|
136
+ e={:parse_errors=>[],:scenarios=>[],:context=>run.context}
137
+ run.parse_errors.each { |pe| e[:parse_errors]<<{:filename=>pe.filename, :error=>pe.error} }
138
+ run.scenarios.each { |sc| e[:scenarios]<<export_scenario(sc) }
139
+ export<<e
140
+ @logger.debug("Exported #{run.id}")
141
+ end
142
+ return export
143
+ end
144
+
145
+ def export_scenario sc
146
+ scenario={:name=>sc[:name],
147
+ :attended=>sc[:attended],
148
+ :status=>sc[:status],
149
+ :number=>sc[:number],
150
+ :start_time=>sc[:start_time],
151
+ :stop_time=>sc[:stop_time],
152
+ :version=>sc[:version],
153
+ :title=>sc[:title],
154
+ :description=>sc[:description],
155
+ :steps=>[]
156
+ }
157
+ sc.steps.each do |step|
158
+ st={:name=>step[:name],
159
+ :number=>step[:number],
160
+ :status=>step[:status],
161
+ :output=>step[:output],
162
+ :error=>step[:error],
163
+ :duration=>step[:duration]
164
+ }
165
+ scenario[:steps]<<st
166
+ end
167
+ return scenario
168
+ end
169
+ end
170
+
171
+ #Establishes an ActiveRecord connection
172
+ def self.connect cfg,logger
173
+ conn=cnct(cfg,logger)
174
+ Model::Schema.migrate(:up) if perform_migration?(cfg)
63
175
  end
64
176
 
65
- class Scenario<ActiveRecord::Base
66
- belongs_to :run
67
- has_many :steps
68
- acts_as_reportable
177
+ private
178
+ #Establishes an active record connection using the cfg hash
179
+ #There is only a rudimentary check to ensure the integrity of cfg
180
+ def self.cnct cfg,logger
181
+ if cfg[:adapter] && cfg[:database]
182
+ logger.debug("Connecting to #{cfg[:database]}")
183
+ return ::ActiveRecord::Base.establish_connection(cfg)
184
+ else
185
+ raise ConnectionError,"Erroneous database configuration. Missing :adapter and/or :database"
186
+ end
69
187
  end
70
188
 
71
- class Step<ActiveRecord::Base
72
- belongs_to :scenario
73
- acts_as_reportable
189
+ def self.perform_migration? cfg
190
+ return true if cfg[:migrate]
191
+ #special case for sqlite3
192
+ if cfg[:adapter]=="sqlite3" && !File.exists?(cfg[:database])
193
+ return true
194
+ end
195
+ return false
74
196
  end
75
197
 
76
- class ParseError<ActiveRecord::Base
77
- belongs_to :run
78
- acts_as_reportable
198
+ end
199
+
200
+ module CouchDB
201
+ def self.connect cfg,logger
202
+ if cfg[:url] && cfg[:database]
203
+ if cfg[:user] && cfg[:password]
204
+ end
205
+ return CouchRest.database!("#{cfg[:url]}/#{cfg[:database]}")
206
+
207
+ else
208
+ raise ConnectionError,"Erroneous database configuration. Missing :url and/or :database"
209
+ end
79
210
  end
80
-
81
- class UpgradeV9toV10<ActiveRecord::Migration
82
- def self.up
83
- puts("Adding new columns")
84
- add_column(:scenarios, :title, :string,{:default=>"title"})
85
- add_column(:scenarios, :description, :string,{:default=>"description"})
86
- puts("Updating existing scenario entries")
87
- Rutema::Model::Scenario.find(:all).each do |sc|
88
- puts "Updating scenario #{sc.id}"
89
- sc.title="#{name}"
90
- sc.description="#{name}"
211
+ module Model
212
+ class Run <CouchRest::ExtendedDocument
213
+ unique_id :slug
214
+
215
+ timestamps!
216
+
217
+ view_by :slug, :descending=>true
218
+
219
+ property :slug, :read_only => true
220
+ property :context
221
+ property :scenarios
222
+ property :parse_errors
223
+
224
+ set_callback :save, :before, :generate_slug_from_payload
225
+ def generate_slug_from_payload
226
+ self['slug']=Digest::SHA1.hexdigest("#{self['context']},#{self['scenarios']}")
91
227
  end
92
228
  end
93
229
  end
@@ -0,0 +1,32 @@
1
+ require 'rutema/system'
2
+ require 'optparse'
3
+
4
+ module Rutema
5
+ class RakeTask
6
+ attr_accessor :config_file, :log_file, :step, :name
7
+ def initialize params=nil
8
+ params||={}
9
+ @config_file=params[:config]
10
+ @log_file=params[:log]
11
+ @name=params[:name]
12
+ yield self if block_given?
13
+
14
+ raise "No rutema configuration given" unless @config_file
15
+ args=['-c',@config_file]
16
+ args+=['-l',@log_file] if @log_file
17
+ args<<"all"
18
+ OptionParser::Arguable.extend_object(args)
19
+ if @name
20
+ desc "Executes the tests in #{File.basename(@config_file)}"
21
+ task :"rutema:#{@name}" do
22
+ Rutema::RutemaX.new(args)
23
+ end
24
+ else
25
+ desc "Executes the tests in #{File.basename(@config_file)}"
26
+ task :rutema do
27
+ Rutema::RutemaX.new(args)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..")
3
3
  require 'rutema/specification'
4
4
 
@@ -1,47 +1,15 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..","..")
3
3
  require 'yaml'
4
4
  require 'rutema/reporter'
5
5
  require 'rutema/model'
6
6
 
7
7
  module Rutema
8
- #Exception occuring when connecting to a database
9
- class ConnectionError<RuntimeError
10
- end
11
-
12
- module ActiveRecordConnections
13
- #Establishes an ActiveRecord connection
14
- def connect_to_active_record cfg,logger
15
- conn=connect(cfg,logger)
16
- Rutema::Model::Schema.migrate(:up) if perform_migration?(cfg)
17
- end
18
- private
19
- #Establishes an active record connection using the cfg hash
20
- #There is only a rudimentary check to ensure the integrity of cfg
21
- def connect cfg,logger
22
- if cfg[:adapter] && cfg[:database]
23
- logger.debug("Connecting to #{cfg[:database]}")
24
- return ActiveRecord::Base.establish_connection(cfg)
25
- else
26
- raise ConnectionError,"Erroneous database configuration. Missing :adapter and/or :database"
27
- end
28
- end
29
-
30
- def perform_migration? cfg
31
- return true if cfg[:migrate]
32
- #special case for sqlite3
33
- if cfg[:adapter]=="sqlite3" && !File.exists?(cfg[:database])
34
- return true
35
- end
36
- return false
37
- end
38
- end
39
-
40
8
  #The ActiveRecordReporter will store the results of a test run in a database using ActiveRecord.
41
9
  #
42
10
  #The DBMSs supported are dependent on the platform: either SQLite3 (MRI) or h2 (jruby)
43
11
  class ActiveRecordReporter
44
- include ActiveRecordConnections
12
+ include ActiveRecord
45
13
  #The required keys in this reporter's configuration are:
46
14
  # :db - the database configuration. A Hash with the DB adapter information
47
15
  # :db=>{:database=>"sample.rb"}
@@ -50,27 +18,27 @@ module Rutema
50
18
  @logger||=Patir.setup_logger
51
19
  database_configuration = definition[:db]
52
20
  raise "No database configuration defined, missing :db configuration key." unless database_configuration
53
- connect_to_active_record(database_configuration,@logger)
21
+ ActiveRecord.connect(database_configuration,@logger)
54
22
  @logger.info("Reporter #{self.to_s} registered")
55
23
  end
56
24
 
57
- #We get all the data for a Rutema::Model::Run entry in here.
25
+ #We get all the data for a Rutema::ActiveRecord::Model::Run entry in here.
58
26
  #
59
- #If the configuration is given and there is a context defined, this will be YAML-dumped into Rutema::Model::Run#context
27
+ #If the configuration is given and there is a context defined, this will be YAML-dumped into Rutema::ActiveRecord::Model::Run#context
60
28
  def report specifications,runner_states,parse_errors,configuration
61
- run_entry=Model::Run.new
29
+ run_entry=ActiveRecord::Model::Run.new
62
30
  if configuration && configuration.context
63
31
  run_entry.context=configuration.context
64
32
  end
65
33
  parse_errors.each do |pe|
66
- er=Model::ParseError.new()
34
+ er=ActiveRecord::Model::ParseError.new()
67
35
  er.filename=pe[:filename]
68
36
  er.error=pe[:error]
69
37
  run_entry.parse_errors<<er
70
38
  end
71
39
  runner_states.compact!
72
40
  runner_states.each do |scenario|
73
- sc=Model::Scenario.new
41
+ sc=ActiveRecord::Model::Scenario.new
74
42
  sc.name=scenario.sequence_name
75
43
  sc.number=scenario.sequence_id
76
44
  sc.start_time=scenario.start_time
@@ -93,7 +61,7 @@ module Rutema
93
61
  sc.attended=false
94
62
  end
95
63
  scenario.step_states.each do |number,step|
96
- st=Model::Step.new
64
+ st=ActiveRecord::Model::Step.new
97
65
  st.name=step[:name]
98
66
  st.number=number
99
67
  st.status="#{step[:status]}"
@@ -109,7 +77,7 @@ module Rutema
109
77
  end
110
78
 
111
79
  def to_s
112
- "ActiveRecordReporter using '#{@dbfile}'"
80
+ "ActiveRecordReporter"
113
81
  end
114
82
 
115
83
  private
@@ -0,0 +1,62 @@
1
+ require 'rutema/model'
2
+
3
+ module Rutema
4
+ class CouchDBReporter
5
+ def initialize definition
6
+ @logger=definition[:logger]
7
+ @logger||=Patir.setup_logger
8
+ database_configuration = definition[:db]
9
+ raise "No database configuration defined, missing :db configuration key." unless database_configuration
10
+ @database=Rutema::CouchDB.connect(database_configuration,@logger)
11
+ @logger.info("Reporter #{self.to_s} registered")
12
+ end
13
+
14
+ #We get all the data for a Rutema::CouchDB::Model::Run entry in here.
15
+ def report specifications,runner_states,parse_errors,configuration
16
+ run_entry=Rutema::CouchDB::Model::Run.new
17
+ run_entry.database=@database
18
+ if configuration && configuration.context
19
+ run_entry.context=configuration.context
20
+ end
21
+ run_entry.parse_errors=parse_errors
22
+ scenarios=[]
23
+ runner_states.compact!
24
+ runner_states.each { |scenario| scenarios<<format_scenario(scenario,specifications)}
25
+ run_entry.scenarios=scenarios
26
+ run_entry.save
27
+ "couchdb reporter done"
28
+ end
29
+
30
+ def to_s
31
+ "CouchDBReporter"
32
+ end
33
+ private
34
+ def format_scenario scenario,specifications
35
+ sc={}
36
+ sc[:name]=scenario.sequence_name
37
+ sc[:number]=scenario.sequence_id
38
+ sc[:start_time]=scenario.start_time
39
+ sc[:stop_time]=scenario.stop_time
40
+ sc[:status]=scenario.status.to_s
41
+ #get the specification for this scenario
42
+ spec=specifications[sc[:name]]
43
+ if spec
44
+ sc[:version]=spec.version if spec.has_version?
45
+ sc[:title]=spec.title
46
+ sc[:description]=spec.description
47
+ else
48
+ @logger.debug("Could not find specification for #{sc[:name]}")
49
+
50
+ sc[:title]=sc[:name]
51
+ sc[:description]=""
52
+ end
53
+ if scenario.strategy==:attended
54
+ sc[:attended]=true
55
+ else
56
+ sc[:attended]=false
57
+ end
58
+ sc[:steps]=scenario.step_states
59
+ return sc
60
+ end
61
+ end
62
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..","..")
3
3
  require 'net/smtp'
4
4
  require 'rutema/reporter'
@@ -24,6 +24,8 @@ module Rutema
24
24
  #Customization keys:
25
25
  #
26
26
  #:subject - the string of this key will be prefixed as a subject for the email
27
+ #
28
+ #:verbose - when true, the report contains info on setup and teardown specs. Optional. Default is false
27
29
  class EmailReporter
28
30
  attr_reader :last_message
29
31
  def initialize definition
@@ -47,6 +49,8 @@ module Rutema
47
49
  @subject||=""
48
50
  @footer=definition[:footer]
49
51
  @footer||=""
52
+ @verbose=definition[:verbose]
53
+ @verbose||=false
50
54
  @logger.info("Reporter '#{self.to_s}' registered")
51
55
  end
52
56
 
@@ -57,7 +61,7 @@ module Rutema
57
61
 
58
62
  def report specifications,runner_states,parse_errors,configuration
59
63
  @mail.subject = "#{@subject}"
60
- txt=TextReporter.new.report(specifications,runner_states,parse_errors,configuration)
64
+ txt=TextReporter.new(:verbose=>@verbose).report(specifications,runner_states,parse_errors,configuration)
61
65
  txt<<"\n\n#{@footer}"
62
66
  @mail.text = txt
63
67
  begin
@@ -1,6 +1,7 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..","..")
3
3
 
4
4
  require 'rutema/reporters/text'
5
5
  require 'rutema/reporters/email'
6
- require 'rutema/reporters/activerecord'
6
+ require 'rutema/reporters/activerecord'
7
+ require 'rutema/reporters/yaml'
@@ -1,7 +1,13 @@
1
1
  module Rutema
2
- #This reporter cerates a simple text summary of a test run
2
+ #This reporter creates a simple text summary of a test run
3
+ #
4
+ #The following configuration keys are used by TextReporter:
5
+ #
6
+ #:verbose - when true, the report contains info on setup and teardown specs. Optional. Default is false
3
7
  class TextReporter
4
- def initialize params=nil
8
+ def initialize params=nil
9
+ @verbose=params[:verbose] if params
10
+ @verbose||=false
5
11
  end
6
12
 
7
13
  #Returns the text summary
@@ -26,20 +32,30 @@ module Rutema
26
32
  #Report on scenarios
27
33
  runner_states.compact!#make sure no nil elements make it through
28
34
  msg<<"\nNo scenarios in this run" if runner_states.empty?
29
- msg<<"\nOne scenario in the current run" if runner_states.size==1
30
- msg<<"\n#{runner_states.size} scenarios in the current run" if runner_states.size>1
31
- not_run = runner_states.select{|state| state.status == :not_executed }.sort_by {|state| state.sequence_id.to_i}
32
- errors = runner_states.select{|state| state.status == :error }.sort_by {|state| state.sequence_id.to_i}
33
- warnings = runner_states.select{|state| state.status == :warning }.sort_by {|state| state.sequence_id.to_i}
34
- successes = runner_states.select{|state| state.status == :success }.sort_by {|state| state.sequence_id.to_i}
35
- msg<<"\n#{errors.size} errors, #{warnings.size} warnings, #{successes.size} successes"
35
+ if @verbose
36
+ states=runner_states
37
+ else
38
+ states=runner_states.select{|state| state.sequence_name !~ /[_setup|_teardown]$/}
39
+ end
40
+ msg<<"\nOne scenario in the current run" if states.size==1
41
+ msg<<"\n#{states.size} scenarios in the current run" if states.size>1
42
+
43
+ not_run = states.select{|state| state.status == :not_executed }.sort_by {|state| state.sequence_id.to_i}
44
+ errors = states.select{|state| state.status == :error }.sort_by {|state| state.sequence_id.to_i}
45
+ warnings = states.select{|state| state.status == :warning }.sort_by {|state| state.sequence_id.to_i}
46
+ successes = states.select{|state| state.status == :success }.sort_by {|state| state.sequence_id.to_i}
47
+ msg<<"\n#{errors.size} errors, #{warnings.size} warnings, #{successes.size} successes, #{not_run.size} not executed (setup failure)"
36
48
  msg<<"\nErrors:" unless errors.empty?
37
49
  msg<<scenario_summaries(errors,specifications)
38
50
  msg<<"\nWarnings:" unless warnings.empty?
39
51
  msg<<scenario_summaries(warnings,specifications)
40
52
  msg<<"\nNot executed:" unless not_run.empty?
41
53
  not_run.each do |state|
42
- msg<<"\n#{specifications[state.sequence_name].title}" if specifications[state.sequence_name]
54
+ if specifications[state.sequence_name]
55
+ msg<<"\n#{specifications[state.sequence_name].title}"
56
+ else
57
+ msg<<"\n#{state.sequence_name}"
58
+ end
43
59
  end
44
60
  msg<<"\nSuccesses:" unless successes.empty?
45
61
  msg<<scenario_summaries(successes,specifications)
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+
3
+ module Rutema
4
+
5
+ module YAML
6
+ #Experimental reporter used to dump the data of a run on disk
7
+ #
8
+ #The following configuration keys are used by YAML::Reporter:
9
+ #
10
+ #:filename - the filename to use to save the YAML dump. Default is 'rutema.yaml'
11
+ class Reporter
12
+ DEFAULT_FILENAME="rutema.yaml"
13
+
14
+ def initialize definition
15
+ @logger=definition[:logger]
16
+ @logger||=Patir.setup_logger
17
+ @filename=definition[:filename]
18
+ @filename||="rutema.yaml"
19
+ @logger.info("Reporter #{self.to_s} registered")
20
+ end
21
+
22
+ #We get all the data from a test run in here.
23
+ def report specifications,runner_states,parse_errors,configuration
24
+ run_entry={}
25
+ if configuration && configuration.context
26
+ run_entry[:context]=configuration.context
27
+ end
28
+ run_entry[:parse_errors]=parse_errors
29
+ runner_states.compact!
30
+ run_entry[:runner_states]=runner_states
31
+ File.open(@filename,"wb") {|f| f.write( ::YAML.dump(run_entry))}
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..")
3
3
  require 'rutema/reporters/standard_reporters'
4
4
  require 'patir/command'
data/lib/rutema/system.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
1
+ # Copyright (c) 2007-2010 Vassilis Rizopoulos. All rights reserved.
2
2
  $:.unshift File.join(File.dirname(__FILE__),"..")
3
3
  require 'rexml/document'
4
4
  require 'patir/configuration'
@@ -12,8 +12,8 @@ module Rutema
12
12
  #This module defines the version numbers for the library
13
13
  module Version
14
14
  MAJOR=1
15
- MINOR=0
16
- TINY=9
15
+ MINOR=1
16
+ TINY=0
17
17
  STRING=[ MAJOR, MINOR, TINY ].join( "." )
18
18
  end
19
19
  #The Elements module provides the namespace for the various modules adding parser functionality
@@ -304,12 +304,12 @@ module Rutema
304
304
  run_test(spec) if spec
305
305
  else
306
306
  @logger.fatal("Don't know how to run '#{mode}'")
307
- exit 1
307
+ raise "Don't know how to run '#{mode}'"
308
308
  end
309
309
  rescue
310
310
  @logger.debug($!)
311
311
  @logger.fatal("Runner error: #{$!.message}")
312
- exit 1
312
+ raise
313
313
  end
314
314
  @configuration.context[:end_time]=Time.now
315
315
  @logger.info("Run completed in #{@configuration.context[:end_time]-@configuration.context[:start_time]}s")
@@ -500,6 +500,9 @@ module Rutema
500
500
  @logger.info("Scenario for #{name}")
501
501
  @states[name]=run_scenario(name,scenario)
502
502
  @states[name].sequence_id="#{@number_of_runs}"
503
+ else
504
+ @states[name]=initialize_state(name,scenario)
505
+ @states[name].sequence_id="#{@number_of_runs}"
503
506
  end
504
507
  end
505
508
  else
@@ -542,18 +545,9 @@ module Rutema
542
545
  end
543
546
  private
544
547
  def run_scenario name,scenario
545
- state=Patir::CommandSequenceStatus.new(name,scenario.steps)
546
- begin
547
- attention_needed=scenario.attended?
548
- if attention_needed && !self.attended?
549
- @logger.warn("Attended scenario cannot be run in unattended mode")
550
- state.status=:warning
551
- else
552
- if attention_needed
553
- state.strategy=:attended
554
- else
555
- state.strategy=:unattended
556
- end
548
+ state=initialize_state(name,scenario)
549
+ begin
550
+ if evaluate_attention(scenario,state)
557
551
  stps=scenario.steps
558
552
  if stps.empty?
559
553
  @logger.warn("Scenario #{name} contains no steps")
@@ -574,6 +568,22 @@ module Rutema
574
568
  state.sequence_id=@number_of_runs
575
569
  return state
576
570
  end
571
+ def initialize_state name,scenario
572
+ state=Patir::CommandSequenceStatus.new(name,scenario.steps)
573
+ end
574
+ def evaluate_attention scenario,state
575
+ if scenario.attended?
576
+ if !self.attended?
577
+ @logger.warn("Attended scenario cannot be run in unattended mode")
578
+ state.status=:warning
579
+ return false
580
+ end
581
+ state.strategy=:attended
582
+ else
583
+ state.strategy=:unattended
584
+ end
585
+ return true
586
+ end
577
587
  def run_step step
578
588
  @logger.info("Running step #{step.number} - #{step.name}")
579
589
  if step.has_cmd? && step.cmd.respond_to?(:run)
@@ -601,13 +611,14 @@ module Rutema
601
611
  @logger.info(msg) if msg && !msg.empty?
602
612
  end
603
613
  end
614
+
604
615
  end
605
616
 
606
617
  #StepRunner halts before every step and asks if it should be executed or not.
607
618
  class StepRunner<Runner
608
- def initialize setup=nil, teardown=nil,logger=nil
619
+ def initialize context=nil,setup=nil, teardown=nil,logger=nil
609
620
  @questioner=HighLine.new
610
- super(setup,teardown,logger)
621
+ super(context,setup,teardown,logger)
611
622
  end
612
623
  def run_step step
613
624
  if @questioner.agree("Execute #{step.to_s}?")
@@ -641,11 +652,11 @@ module Rutema
641
652
  rescue Patir::ConfigurationException
642
653
  @logger.debug($!)
643
654
  @logger.fatal("Configuration error '#{$!.message}'")
644
- exit 1
655
+ raise "Configuration error '#{$!.message}'"
645
656
  rescue
646
657
  @logger.debug($!)
647
658
  @logger.fatal("#{$!.message}")
648
- exit 1
659
+ raise
649
660
  end
650
661
  end
651
662
  private
@@ -682,7 +693,7 @@ module Rutema
682
693
  @mode=File.expand_path(command)
683
694
  else
684
695
  $stderr.puts "Can't find '#{command}' and it does not match any known commands. Don't know what to do with it."
685
- exit 1
696
+ raise "Can't find '#{command}' and it does not match any known commands. Don't know what to do with it."
686
697
  end
687
698
  end
688
699
  end
@@ -696,7 +707,7 @@ module Rutema
696
707
  @coordinator.run(@configuration.check)
697
708
  else
698
709
  @logger.fatal("There is no check test defined in the configuration.")
699
- exit 1
710
+ raise "There is no check test defined in the configuration."
700
711
  end
701
712
  else
702
713
  #run everything
@@ -706,10 +717,9 @@ module Rutema
706
717
  @coordinator.report
707
718
  if @coordinator.parse_errors.empty? && @coordinator.last_run_a_success?
708
719
  @logger.info("All tests successful")
709
- exit 0
710
720
  else
711
721
  @logger.warn("Not all tests were successful")
712
- exit 1
722
+ raise "Not all tests were successful"
713
723
  end
714
724
  end
715
725
  end
@@ -0,0 +1,60 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+ require 'rubygems'
3
+ require 'rutema/gems'
4
+ require 'test/unit'
5
+ require 'ostruct'
6
+ require 'rutema/reporters/couchdb'
7
+ require 'patir/command'
8
+ require 'mocha'
9
+ #$DEBUG=true
10
+ module TestRutema
11
+ class MockCommand
12
+ include Patir::Command
13
+ def initialize number
14
+ @number=number
15
+ end
16
+ end
17
+
18
+ class TestCouchDBModel<Test::Unit::TestCase
19
+ end
20
+
21
+ class TestCouchDBReporter<Test::Unit::TestCase
22
+ CFG={:db=>{:url=>"http://localhost:5984", :database=>"rutema_test_sandbox"}}
23
+ def setup
24
+ @parse_errors=[{:filename=>"f.spec",:error=>"error"}]
25
+ st=Patir::CommandSequenceStatus.new("test_seq")
26
+ st.step=MockCommand.new(1)
27
+ st.step=MockCommand.new(2)
28
+ st.step=MockCommand.new(3)
29
+ @status=[st]
30
+ end
31
+
32
+ def test_no_errors
33
+ spec=mock
34
+ r=Rutema::CouchDBReporter.new(CFG)
35
+ assert_nothing_raised() { r.report({"test"=>spec},[runner_state_mock()],[],nil) }
36
+ end
37
+
38
+ def test_a_bit_of_everything
39
+ spec=mock
40
+ spec.expects(:has_version?).returns(false)
41
+ spec.expects(:title).returns("T")
42
+ spec.expects(:description).returns("cool test")
43
+
44
+ r=Rutema::CouchDBReporter.new(CFG)
45
+ assert_nothing_raised() { r.report({"1"=>spec},[runner_state_mock,runner_state_mock(1,:error)],[],nil) }
46
+ end
47
+
48
+ def runner_state_mock n=0,status=:success,step_states=[]
49
+ rs=mock()
50
+ rs.expects(:sequence_name).returns("#{n}")
51
+ rs.expects(:sequence_id).returns("seq_id#{n}")
52
+ rs.expects(:start_time).returns(Time.now-3600)
53
+ rs.expects(:stop_time).returns(Time.now)
54
+ rs.expects(:status).returns(status)
55
+ rs.expects(:strategy).returns(:attended)
56
+ rs.expects(:step_states).returns(step_states)
57
+ return rs
58
+ end
59
+ end
60
+ end
data/test/test_model.rb CHANGED
@@ -1,21 +1,16 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
-
2
+ require 'rubygems'
3
3
  require 'test/unit'
4
4
  require 'rutema/model'
5
5
  require 'fileutils'
6
6
  require 'rubygems'
7
7
  require 'rutema/gems'
8
- require 'active_record/fixtures'
9
8
 
10
9
  module TestRutema
11
- class TestModel<Test::Unit::TestCase
10
+ class TestActiveRecordModel<Test::Unit::TestCase
12
11
  def setup
13
- if RUBY_PLATFORM =~ /java/
14
- ActiveRecord::Base.establish_connection(:adapter => "jdbch2",:database =>"db/h2")
15
- else
16
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database =>":memory:")
17
- end
18
- Rutema::Model::Schema.up
12
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database =>":memory:")
13
+ Rutema::ActiveRecord::Model::Schema.up
19
14
  end
20
15
  def teardown
21
16
  ActiveRecord::Base.remove_connection
@@ -24,15 +19,15 @@ module TestRutema
24
19
  #test the CRUD operations
25
20
  def test_create_read_update_delete
26
21
  #create
27
- r=Rutema::Model::Run.new
22
+ r=Rutema::ActiveRecord::Model::Run.new
28
23
  context={:tester=>"automatopoulos",:version=>"latest"}
29
24
  r.context=context
30
- sc=Rutema::Model::Scenario.new(:name=>"TC000",:attended=>false,:status=>"success",:start_time=>Time.now)
31
- sc.steps<<Rutema::Model::Step.new(:name=>"echo",:number=>1,:status=>"success",:output=>"testing is nice",:error=>"",:duration=>1)
25
+ sc=Rutema::ActiveRecord::Model::Scenario.new(:name=>"TC000",:attended=>false,:status=>"success",:start_time=>Time.now)
26
+ sc.steps<<Rutema::ActiveRecord::Model::Step.new(:name=>"echo",:number=>1,:status=>"success",:output=>"testing is nice",:error=>"",:duration=>1)
32
27
  r.scenarios<<sc
33
28
  assert(r.save, "Failed to save.")
34
29
  #read
35
- run=Rutema::Model::Run.find(r.id)
30
+ run=Rutema::ActiveRecord::Model::Run.find(r.id)
36
31
  assert_equal(context,run.context)
37
32
  assert_equal(sc.name, run.scenarios[0].name)
38
33
  #update
@@ -41,7 +36,27 @@ module TestRutema
41
36
  assert(run.save, "Failed to update.")
42
37
  #delete
43
38
  assert(run.destroy, "Failed to delete.")
44
- assert_raise(ActiveRecord::RecordNotFound) {Rutema::Model::Run.find(r.id)}
39
+ assert_raise(ActiveRecord::RecordNotFound) {Rutema::ActiveRecord::Model::Run.find(r.id)}
40
+ end
41
+ end
42
+
43
+ class TestCouchDBModel<Test::Unit::TestCase
44
+ def setup
45
+ @db=CouchRest.database!("http://localhost:5984/rutema_test")
46
+ end
47
+
48
+ def test_couchdb_model
49
+ run=Rutema::CouchDB::Model::Run.new
50
+ run.database=@db
51
+ run.context="context"
52
+ run.scenarios=["1","2","#{self.object_id}"]
53
+ assert_nothing_raised() { run.save }
54
+
55
+ r=Rutema::CouchDB::Model::Run.get(run.slug)
56
+ assert_equal(run.slug, r.slug)
57
+
45
58
  end
59
+
60
+
46
61
  end
47
62
  end
Binary file
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rutema
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 0
10
+ version: 1.1.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Vassilis Rizopoulos
@@ -9,99 +15,136 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-04-07 00:00:00 +03:00
18
+ date: 2010-12-20 00:00:00 +02:00
13
19
  default_executable: rutemax
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: patir
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 0
32
+ - 6
33
+ - 4
23
34
  version: 0.6.4
24
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
25
37
  - !ruby/object:Gem::Dependency
26
38
  name: highline
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
30
42
  requirements:
31
- - - ">="
43
+ - - "="
32
44
  - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
45
+ hash: 7
46
+ segments:
47
+ - 1
48
+ - 5
49
+ - 2
50
+ version: 1.5.2
51
+ type: :runtime
52
+ version_requirements: *id002
35
53
  - !ruby/object:Gem::Dependency
36
54
  name: mailfactory
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
40
58
  requirements:
41
- - - ">="
59
+ - - "="
42
60
  - !ruby/object:Gem::Version
43
- version: "0"
44
- version:
61
+ hash: 7
62
+ segments:
63
+ - 1
64
+ - 4
65
+ - 0
66
+ version: 1.4.0
67
+ type: :runtime
68
+ version_requirements: *id003
45
69
  - !ruby/object:Gem::Dependency
46
70
  name: activerecord
47
- type: :runtime
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
50
74
  requirements:
51
75
  - - "="
52
76
  - !ruby/object:Gem::Version
53
- version: 2.3.4
54
- version:
77
+ hash: 19
78
+ segments:
79
+ - 2
80
+ - 3
81
+ - 8
82
+ version: 2.3.8
83
+ type: :runtime
84
+ version_requirements: *id004
55
85
  - !ruby/object:Gem::Dependency
56
86
  name: ruport
57
- type: :runtime
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
87
+ prerelease: false
88
+ requirement: &id005 !ruby/object:Gem::Requirement
89
+ none: false
60
90
  requirements:
61
91
  - - "="
62
92
  - !ruby/object:Gem::Version
63
- version: 1.6.1
64
- version:
93
+ hash: 9
94
+ segments:
95
+ - 1
96
+ - 6
97
+ - 3
98
+ version: 1.6.3
99
+ type: :runtime
100
+ version_requirements: *id005
65
101
  - !ruby/object:Gem::Dependency
66
102
  name: acts_as_reportable
67
- type: :runtime
68
- version_requirement:
69
- version_requirements: !ruby/object:Gem::Requirement
103
+ prerelease: false
104
+ requirement: &id006 !ruby/object:Gem::Requirement
105
+ none: false
70
106
  requirements:
71
107
  - - "="
72
108
  - !ruby/object:Gem::Version
109
+ hash: 17
110
+ segments:
111
+ - 1
112
+ - 1
113
+ - 1
73
114
  version: 1.1.1
74
- version:
115
+ type: :runtime
116
+ version_requirements: *id006
75
117
  - !ruby/object:Gem::Dependency
76
- name: rubyforge
77
- type: :development
78
- version_requirement:
79
- version_requirements: !ruby/object:Gem::Requirement
118
+ name: couchrest
119
+ prerelease: false
120
+ requirement: &id007 !ruby/object:Gem::Requirement
121
+ none: false
80
122
  requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: 2.0.3
84
- version:
85
- - !ruby/object:Gem::Dependency
86
- name: gemcutter
87
- type: :development
88
- version_requirement:
89
- version_requirements: !ruby/object:Gem::Requirement
90
- requirements:
91
- - - ">="
123
+ - - "="
92
124
  - !ruby/object:Gem::Version
93
- version: 0.3.0
94
- version:
125
+ hash: 65
126
+ segments:
127
+ - 0
128
+ - 37
129
+ version: "0.37"
130
+ type: :runtime
131
+ version_requirements: *id007
95
132
  - !ruby/object:Gem::Dependency
96
133
  name: hoe
97
- type: :development
98
- version_requirement:
99
- version_requirements: !ruby/object:Gem::Requirement
134
+ prerelease: false
135
+ requirement: &id008 !ruby/object:Gem::Requirement
136
+ none: false
100
137
  requirements:
101
138
  - - ">="
102
139
  - !ruby/object:Gem::Version
103
- version: 2.5.0
104
- version:
140
+ hash: 47
141
+ segments:
142
+ - 2
143
+ - 8
144
+ - 0
145
+ version: 2.8.0
146
+ type: :development
147
+ version_requirements: *id008
105
148
  description: |-
106
149
  == DESCRIPTION:
107
150
  rutema is a test execution tool with a twist.
@@ -151,11 +194,14 @@ files:
151
194
  - lib/rutema/configuration.rb
152
195
  - lib/rutema/gems.rb
153
196
  - lib/rutema/model.rb
197
+ - lib/rutema/rake.rb
154
198
  - lib/rutema/reporter.rb
155
199
  - lib/rutema/reporters/activerecord.rb
156
200
  - lib/rutema/reporters/email.rb
157
201
  - lib/rutema/reporters/standard_reporters.rb
158
202
  - lib/rutema/reporters/text.rb
203
+ - lib/rutema/reporters/yaml.rb
204
+ - lib/rutema/reporters/couchdb.rb
159
205
  - lib/rutema/specification.rb
160
206
  - lib/rutema/system.rb
161
207
  - selftest.sh
@@ -180,6 +226,7 @@ files:
180
226
  - test/test_reporter.rb
181
227
  - test/test_specification.rb
182
228
  - test/test_system.rb
229
+ - test/test_couchdb.rb
183
230
  has_rdoc: true
184
231
  homepage:
185
232
  licenses: []
@@ -191,26 +238,33 @@ rdoc_options:
191
238
  require_paths:
192
239
  - lib
193
240
  required_ruby_version: !ruby/object:Gem::Requirement
241
+ none: false
194
242
  requirements:
195
243
  - - ">="
196
244
  - !ruby/object:Gem::Version
245
+ hash: 3
246
+ segments:
247
+ - 0
197
248
  version: "0"
198
- version:
199
249
  required_rubygems_version: !ruby/object:Gem::Requirement
250
+ none: false
200
251
  requirements:
201
252
  - - ">="
202
253
  - !ruby/object:Gem::Version
254
+ hash: 3
255
+ segments:
256
+ - 0
203
257
  version: "0"
204
- version:
205
258
  requirements: []
206
259
 
207
260
  rubyforge_project: patir
208
- rubygems_version: 1.3.5
261
+ rubygems_version: 1.3.7
209
262
  signing_key:
210
263
  specification_version: 3
211
264
  summary: rutema is a test execution and management framework for heterogeneous testing environments
212
265
  test_files:
213
266
  - test/test_configuration.rb
267
+ - test/test_couchdb.rb
214
268
  - test/test_model.rb
215
269
  - test/test_reporter.rb
216
270
  - test/test_specification.rb