rutema 0.3 → 0.4
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 +12 -0
- data/Manifest.txt +14 -0
- data/README.txt +6 -1
- data/Rakefile +2 -1
- data/bin/rutemaweb +9 -0
- data/lib/rutema/historian.rb +38 -14
- data/lib/rutema/model.rb +78 -0
- data/lib/rutema/reporter_ar.rb +13 -83
- data/lib/rutema/system.rb +51 -35
- data/lib/rutemaweb/htdocs/bg_menu.gif +0 -0
- data/lib/rutemaweb/htdocs/bg_submenu.gif +0 -0
- data/lib/rutemaweb/htdocs/index.html +50 -0
- data/lib/rutemaweb/htdocs/run_error.png +0 -0
- data/lib/rutemaweb/htdocs/run_ok.png +0 -0
- data/lib/rutemaweb/htdocs/run_warn.png +0 -0
- data/lib/rutemaweb/htdocs/step_error.png +0 -0
- data/lib/rutemaweb/htdocs/step_ok.png +0 -0
- data/lib/rutemaweb/htdocs/step_warn.png +0 -0
- data/lib/rutemaweb/htdocs/style.css +102 -0
- data/lib/rutemaweb/htdocs/tie_logo.gif +0 -0
- data/lib/rutemaweb/rutemaweb.rb +240 -0
- data/test/test_historian.rb +39 -10
- data/test/test_model.rb +35 -0
- data/test/test_reporter.rb +2 -4
- data/test/test_system.rb +12 -1
- metadata +27 -2
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 0.4 / 2007-07-05
|
2
|
+
* rutemaweb, a web interface for the db contents added
|
3
|
+
* uses WEBRick, Camping and Ruport
|
4
|
+
* offers views on all runs in the System, detailed scenario views and ccenario-over-time views
|
5
|
+
* Runner now rescues all failures in scenarios
|
6
|
+
* Bugfix in setting status of attended scenario in unattended mode
|
7
|
+
* Better ruport usage in the historian
|
8
|
+
* rutemah added to the gem and manifest
|
9
|
+
* rutemax help message complete with commands
|
10
|
+
* split the AR reporter and the model
|
11
|
+
* expanded the unit tests
|
12
|
+
|
1
13
|
== 0.3 / 2007-05-30
|
2
14
|
* Reporter implementations moved to own file
|
3
15
|
* Reporter interface changed (Runner stati now passed directly as a name indexed Hash, specifications passed as well)
|
data/Manifest.txt
CHANGED
@@ -5,12 +5,26 @@ COPYING.txt
|
|
5
5
|
Rakefile
|
6
6
|
bin/rutemax
|
7
7
|
bin/rutemah
|
8
|
+
bin/rutemaweb
|
8
9
|
lib/rutema/configuration.rb
|
9
10
|
lib/rutema/specification.rb
|
10
11
|
lib/rutema/system.rb
|
11
12
|
lib/rutema/reporter.rb
|
12
13
|
lib/rutema/reporter_ar.rb
|
13
14
|
lib/rutema/historian.rb
|
15
|
+
lib/rutema/model.rb
|
16
|
+
lib/rutemaweb/htdocs/bg_menu.gif
|
17
|
+
lib/rutemaweb/htdocs/bg_submenu.gif
|
18
|
+
lib/rutemaweb/htdocs/run_error.png
|
19
|
+
lib/rutemaweb/htdocs/run_ok.png
|
20
|
+
lib/rutemaweb/htdocs/run_warn.png
|
21
|
+
lib/rutemaweb/htdocs/step_error.png
|
22
|
+
lib/rutemaweb/htdocs/step_ok.png
|
23
|
+
lib/rutemaweb/htdocs/step_warn.png
|
24
|
+
lib/rutemaweb/htdocs/style.css
|
25
|
+
lib/rutemaweb/htdocs/tie_logo.gif
|
26
|
+
lib/rutemaweb/htdocs/index.html
|
27
|
+
lib/rutemaweb/rutemaweb.rb
|
14
28
|
test/test_configuration.rb
|
15
29
|
test/test_specification.rb
|
16
30
|
test/test_system.rb
|
data/README.txt
CHANGED
@@ -95,4 +95,9 @@ You can redistribute it and/or modify it under either the terms of the GPL
|
|
95
95
|
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
96
96
|
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
97
97
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
98
|
-
PURPOSE.
|
98
|
+
PURPOSE.
|
99
|
+
|
100
|
+
== CREDITS
|
101
|
+
RutemaWeb uses icons from
|
102
|
+
Fast Icon (Dirceu Veiga)
|
103
|
+
Homepage: http://www.fasticon.com
|
data/Rakefile
CHANGED
@@ -19,7 +19,8 @@ Hoe.new('rutema', "#{Rutema::VERSION_MAJOR}.#{Rutema::VERSION_MINOR}") do |p|
|
|
19
19
|
p.extra_deps<<['mailfactory']
|
20
20
|
p.extra_deps<<['activerecord']
|
21
21
|
p.extra_deps<<['ruport']
|
22
|
-
p.
|
22
|
+
p.extra_deps<<['camping']
|
23
|
+
p.spec_extras={:executables=>["rutemax","rutemah","rutemaweb"],
|
23
24
|
:default_executable=>"rutemax"}
|
24
25
|
end
|
25
26
|
|
data/bin/rutemaweb
ADDED
data/lib/rutema/historian.rb
CHANGED
@@ -31,12 +31,17 @@ module Rutema
|
|
31
31
|
private
|
32
32
|
def parse_command_line args
|
33
33
|
args.options do |opt|
|
34
|
+
opt.on("Usage:")
|
35
|
+
opt.on("rutemah [options] -c CONFIG command")
|
34
36
|
opt.on("Options:")
|
35
37
|
opt.on("--debug", "-d","Turns on debug messages") { $DEBUG=true }
|
36
38
|
opt.on("--config FILE", "-c FILE",String,"Loads the configuration from FILE") { |@config_file|}
|
37
39
|
opt.on("--log FILE", "-l FILE",String,"Redirects the log output to FILE") { |@log_file|}
|
38
40
|
opt.on("-V", "--version","Displays the version") { $stdout.puts("v#{VERSION_MAJOR}.#{VERSION_MINOR}");exit 0 }
|
39
41
|
opt.on("--help", "-h", "-?", "This text") { $stdout.puts opt; exit 0 }
|
42
|
+
opt.on("Commands are:")
|
43
|
+
opt.on("all - lists all entries in the database")
|
44
|
+
opt.on("\"testname\" - lists all tests runs for the given test name")
|
40
45
|
opt.parse!
|
41
46
|
#and now the rest
|
42
47
|
if args.empty?
|
@@ -47,6 +52,16 @@ module Rutema
|
|
47
52
|
end
|
48
53
|
end
|
49
54
|
end#parse_command_line
|
55
|
+
private
|
56
|
+
def application_flow
|
57
|
+
logger=Patir.setup_logger(@log_file)
|
58
|
+
if @config_file
|
59
|
+
cfg=RutemaHConfigurator.new(@config_file,logger).configuration()
|
60
|
+
puts Historian.new(cfg,logger).history(@command)
|
61
|
+
else
|
62
|
+
logger.error("No configuration file specified")
|
63
|
+
end
|
64
|
+
end
|
50
65
|
end
|
51
66
|
|
52
67
|
class Historian
|
@@ -60,35 +75,44 @@ module Rutema
|
|
60
75
|
def history mode
|
61
76
|
case mode
|
62
77
|
when "all"
|
63
|
-
|
64
|
-
|
65
|
-
table=DB::Scenario.report_table(:all,:except=>["id","run_id","number"],:conditions => "run_id = '#{run.id}'")
|
66
|
-
puts beautify(table)
|
67
|
-
end
|
78
|
+
table=Model::Scenario.report_table(:all)
|
79
|
+
ret=Ruport::Data::Grouping(beautify(table),:by=>"run_id")
|
68
80
|
when String
|
69
|
-
per_spec(mode)
|
81
|
+
ret=per_spec(mode)
|
70
82
|
end
|
83
|
+
return ret
|
71
84
|
end
|
72
85
|
private
|
73
86
|
def beautify table
|
74
|
-
table.reorder("name","status","attended","version","start_time","stop_time")
|
87
|
+
table.reorder("run_id","name","status","attended","version","start_time","stop_time")
|
75
88
|
table.replace_column("version") {|r| r.version ? r.version : "N/A"}
|
76
89
|
table.replace_column("attended") {|r| r.attended=="t" ? "yes" : "no"}
|
77
90
|
table.replace_column("start_time") {|r| r.stop_time ? r.start_time : nil}
|
78
91
|
return table
|
79
92
|
end
|
80
93
|
def per_spec spec_name
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
94
|
+
begin
|
95
|
+
table=Model::Scenario.report_table(:all,:conditions=>"name = '#{spec_name}'",:except=>["id","number"])
|
96
|
+
if table.empty?
|
97
|
+
@logger.warn("No test run records found for #{spec_name}")
|
98
|
+
nil
|
99
|
+
else
|
100
|
+
beautify(table)
|
101
|
+
end
|
102
|
+
rescue
|
103
|
+
@logger.debug($!)
|
104
|
+
@logger.error("Could not retrieve scenario data from the database")
|
86
105
|
end
|
87
106
|
end
|
88
107
|
def connect
|
89
108
|
ActiveRecord::Base.logger = @logger
|
90
|
-
|
91
|
-
|
109
|
+
begin
|
110
|
+
ActiveRecord::Base.connection
|
111
|
+
@logger.info("Database connection available: #{ActiveRecord::Base.connection.to_s}")
|
112
|
+
rescue
|
113
|
+
@logger.info("Connecting with database '#{@configuration.source}'")
|
114
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database => @configuration.source)
|
115
|
+
end
|
92
116
|
end
|
93
117
|
end
|
94
118
|
end
|
data/lib/rutema/model.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'ruport/acts_as_reportable'
|
4
|
+
#this fixes the AR Logger hack that annoys me sooooo much
|
5
|
+
class Logger
|
6
|
+
private
|
7
|
+
def format_message(severity, datetime, progname, msg)
|
8
|
+
(@formatter || @default_formatter).call(severity, datetime, progname, msg)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
module Rutema
|
12
|
+
#This is the ActiveRecord model for Rutema:
|
13
|
+
#
|
14
|
+
#A Run has n instances of executed scenarios - which in turn have n instances of executed steps -
|
15
|
+
#and n instances of parse errors.
|
16
|
+
module Model
|
17
|
+
#This is the schema for the AR database used to store test results
|
18
|
+
#
|
19
|
+
#We store the RutemaConfiguration#context for every run so that reports for past runs can be recreated without running the actual tests again.
|
20
|
+
class Schema<ActiveRecord::Migration
|
21
|
+
def self.up
|
22
|
+
create_table :runs do |t|
|
23
|
+
t.column :context, :string
|
24
|
+
end
|
25
|
+
|
26
|
+
create_table :scenarios do |t|
|
27
|
+
t.column :name, :string, :null=>false
|
28
|
+
t.column :run_id,:integer, :null=>false
|
29
|
+
t.column :attended,:bool, :null=>false
|
30
|
+
t.column :status, :string,:null=>false
|
31
|
+
t.column :number,:integer
|
32
|
+
t.column :start_time, :datetime,:null=>false
|
33
|
+
t.column :stop_time, :datetime
|
34
|
+
t.column :version, :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, :time
|
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
|
+
|
55
|
+
class Run<ActiveRecord::Base
|
56
|
+
has_many :scenarios
|
57
|
+
has_many :parse_errors
|
58
|
+
serialize :context
|
59
|
+
acts_as_reportable
|
60
|
+
end
|
61
|
+
|
62
|
+
class Scenario<ActiveRecord::Base
|
63
|
+
belongs_to :run
|
64
|
+
has_many :steps
|
65
|
+
acts_as_reportable
|
66
|
+
end
|
67
|
+
|
68
|
+
class Step<ActiveRecord::Base
|
69
|
+
belongs_to :scenario
|
70
|
+
acts_as_reportable
|
71
|
+
end
|
72
|
+
|
73
|
+
class ParseError<ActiveRecord::Base
|
74
|
+
belongs_to :run
|
75
|
+
acts_as_reportable
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/rutema/reporter_ar.rb
CHANGED
@@ -1,87 +1,14 @@
|
|
1
1
|
# Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
|
2
|
-
require 'rutema/reporter'
|
3
2
|
require 'yaml'
|
3
|
+
require 'rutema/reporter'
|
4
|
+
require 'rutema/model'
|
4
5
|
require 'rubygems'
|
5
|
-
require 'active_record'
|
6
|
-
require 'ruport/acts_as_reportable'
|
7
6
|
require 'patir/command'
|
8
7
|
|
9
|
-
|
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
|
8
|
+
module Rutema
|
80
9
|
#The ActiveRecordReporter will store the results of a test run in a database using ActiveRecord.
|
81
10
|
#
|
82
11
|
#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
12
|
class ActiveRecordReporter<Reporter
|
86
13
|
def initialize definition
|
87
14
|
@definition=definition
|
@@ -90,20 +17,23 @@ module Rutema
|
|
90
17
|
raise "No database file defined" unless definition[:dbfile]
|
91
18
|
connect
|
92
19
|
end
|
93
|
-
|
20
|
+
|
21
|
+
#We get all the data for a Rutema::Model::Run entry in here.
|
22
|
+
#
|
23
|
+
#If the configuration is given and there is a context defined, this will be YAML-dumped into Rutema::Model::Run#context
|
94
24
|
def report specifications,runner_states,parse_errors,configuration
|
95
|
-
run_entry=
|
25
|
+
run_entry=Model::Run.new
|
96
26
|
if configuration && configuration.context
|
97
|
-
run_entry.context=
|
27
|
+
run_entry.context=configuration.context
|
98
28
|
end
|
99
29
|
parse_errors.each do |pe|
|
100
|
-
er=
|
30
|
+
er=Model::ParseError.new()
|
101
31
|
er.filename=pe[:filename]
|
102
32
|
er.error=pe[:error]
|
103
33
|
run_entry.parse_errors<<er
|
104
34
|
end
|
105
35
|
runner_states.each do |scenario|
|
106
|
-
sc=
|
36
|
+
sc=Model::Scenario.new
|
107
37
|
sc.name=scenario.sequence_name
|
108
38
|
sc.number=scenario.sequence_id
|
109
39
|
sc.start_time=scenario.start_time
|
@@ -122,7 +52,7 @@ module Rutema
|
|
122
52
|
sc.attended=false
|
123
53
|
end
|
124
54
|
scenario.step_states.each do |number,step|
|
125
|
-
st=
|
55
|
+
st=Model::Step.new
|
126
56
|
st.name=step[:name]
|
127
57
|
st.number=number
|
128
58
|
st.status=step[:status].to_s
|
@@ -142,7 +72,7 @@ module Rutema
|
|
142
72
|
@logger.info("Connecting with database '#{@definition[:dbfile]}'")
|
143
73
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
|
144
74
|
:database => @definition[:dbfile])
|
145
|
-
|
75
|
+
Model::Schema.migrate(:up) unless File.exists?(@definition[:dbfile])
|
146
76
|
end
|
147
77
|
end
|
148
78
|
|
data/lib/rutema/system.rb
CHANGED
@@ -13,7 +13,7 @@ require 'patir/command'
|
|
13
13
|
|
14
14
|
module Rutema
|
15
15
|
VERSION_MAJOR=0
|
16
|
-
VERSION_MINOR=
|
16
|
+
VERSION_MINOR=4
|
17
17
|
#Is raised when an error is found in a specification
|
18
18
|
class ParserError<RuntimeError
|
19
19
|
end
|
@@ -176,7 +176,7 @@ module Rutema
|
|
176
176
|
return spec
|
177
177
|
end
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
#This class coordinates parsing, execution and reporting of test specifications
|
181
181
|
class Coordinator
|
182
182
|
attr_accessor :configuration,:parse_errors,:parsed_files
|
@@ -201,23 +201,28 @@ module Rutema
|
|
201
201
|
def run mode
|
202
202
|
@configuration.context.start_time=Time.now
|
203
203
|
@logger.info("Run started")
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
204
|
+
begin
|
205
|
+
case mode
|
206
|
+
when :all
|
207
|
+
specs=parse_all_specifications
|
208
|
+
run_scenarios(specs)
|
209
|
+
when :attended
|
210
|
+
specs=parse_all_specifications
|
211
|
+
@logger.debug(specs)
|
212
|
+
run_scenarios(specs.select{|s| s.scenario && s.scenario.attended?})
|
213
|
+
when :unattended
|
214
|
+
specs=parse_all_specifications
|
215
|
+
@logger.debug(specs)
|
216
|
+
run_scenarios(specs.select{|s| s.scenario && !s.scenario.attended?})
|
217
|
+
when String
|
218
|
+
spec=parse_specification(mode)
|
219
|
+
run_test(spec) if spec
|
220
|
+
else
|
221
|
+
@logger.error("Don't know how to run '#{mode}'")
|
222
|
+
end
|
223
|
+
rescue
|
224
|
+
@logger.error("Runner error: #{$!.message}")
|
225
|
+
@logger.debug($!)
|
221
226
|
end
|
222
227
|
@configuration.context.end_time=Time.now
|
223
228
|
@logger.info("Run completed in #{@configuration.context.end_time-@configuration.context.start_time}s")
|
@@ -384,25 +389,31 @@ module Rutema
|
|
384
389
|
private
|
385
390
|
def run_scenario name,scenario
|
386
391
|
state=Patir::CommandSequenceStatus.new(name,scenario.steps)
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
else
|
391
|
-
if scenario.attended?
|
392
|
-
state.strategy=:attended
|
393
|
-
else
|
394
|
-
state.strategy=:unattended
|
395
|
-
end
|
396
|
-
stps=scenario.steps
|
397
|
-
if stps.empty?
|
398
|
-
@logger.warn("Scenario #{name} contains no steps")
|
392
|
+
begin
|
393
|
+
if scenario.attended? && !self.attended?
|
394
|
+
@logger.warn("Attended scenario cannot be run in unattended mode")
|
399
395
|
state.status=:warning
|
400
396
|
else
|
401
|
-
|
402
|
-
state.
|
403
|
-
|
397
|
+
if scenario.attended?a
|
398
|
+
state.strategy=:attended
|
399
|
+
else
|
400
|
+
state.strategy=:unattended
|
401
|
+
end
|
402
|
+
stps=scenario.steps
|
403
|
+
if stps.empty?
|
404
|
+
@logger.warn("Scenario #{name} contains no steps")
|
405
|
+
state.status=:warning
|
406
|
+
else
|
407
|
+
stps.each do |s|
|
408
|
+
state.step=run_step(s)
|
409
|
+
break if !state.success?
|
410
|
+
end
|
404
411
|
end
|
405
412
|
end
|
413
|
+
rescue
|
414
|
+
@logger.error("Encountered error in #{name}: #{$!.message}")
|
415
|
+
@logger.debug($!)
|
416
|
+
state.status=:error
|
406
417
|
end
|
407
418
|
state.stop_time=Time.now
|
408
419
|
state.sequence_id=@number_of_runs
|
@@ -474,6 +485,11 @@ module Rutema
|
|
474
485
|
opt.on("--check","Runs just the check test"){@check=true}
|
475
486
|
opt.on("-V", "--version","Displays the version") { $stdout.puts("v#{VERSION_MAJOR}.#{VERSION_MINOR}");exit 0 }
|
476
487
|
opt.on("--help", "-h", "-?", "This text") { $stdout.puts opt; exit 0 }
|
488
|
+
opt.on("The commands are:")
|
489
|
+
opt.on("\tall - Runs all tests")
|
490
|
+
opt.on("\tattended - Runs all attended tests")
|
491
|
+
opt.on("\tunattended - Runs all unattended tests")
|
492
|
+
opt.on("You can also provide a specification filename in order to run a single test")
|
477
493
|
opt.parse!
|
478
494
|
#and now the rest
|
479
495
|
if args.empty?
|
@@ -498,7 +514,7 @@ module Rutema
|
|
498
514
|
end
|
499
515
|
end
|
500
516
|
end
|
501
|
-
|
517
|
+
|
502
518
|
def application_flow
|
503
519
|
if @check
|
504
520
|
#run just the check test
|
Binary file
|
Binary file
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
3
|
+
<head>
|
4
|
+
<meta name="author" content="Vassilis Rizopoulos" />
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF8" />
|
6
|
+
<link rel="stylesheet" href="style.css" type="text/css" />
|
7
|
+
<title>Rutema Historian Web Interface</title>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<div id="page" align="center">
|
11
|
+
<div id="content" style="width:800px">
|
12
|
+
<div id="logo">
|
13
|
+
<div style="margin-top:70px" class="whitetitle">rutema</div>
|
14
|
+
</div>
|
15
|
+
<div id="topheader">
|
16
|
+
<div align="left" class="bodytext">
|
17
|
+
<br />
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
<div id="menu">
|
21
|
+
</div>
|
22
|
+
<div id="submenu">
|
23
|
+
<div align="right" class="smallgraytext" style="padding:9px;">
|
24
|
+
<!-- <a href="../index.html">patir</a> | <a href="index.html">rutema</a> | <a href="rdoc/index.html">rdoc</a> -->
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
<div id="contenttext">
|
28
|
+
<div style="padding:10px">
|
29
|
+
<span class="titletext">Intro</span>
|
30
|
+
</div>
|
31
|
+
<div class="bodytext" style="padding:12px;" align="justify">
|
32
|
+
<p>This is the rutema web interface.<br />
|
33
|
+
It allows you to browse the contents of the test results database.
|
34
|
+
</p>
|
35
|
+
<p>Currently you can view the results for each separate run, the results for a specific scenario (a complete list of all steps executed in the scenario with standard and error output logs) or the complete execution history of a scenario.</p>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<div id="leftpanel">
|
39
|
+
<div align="justify" class="graypanel">
|
40
|
+
<span class="bodytext"><a href="/rutema" class="smallgraytext">Run overview</a></span><br /><br />
|
41
|
+
<span class="bodytext"><a href="/rutema?scenarios=all" class="smallgraytext">Scenario overview</a></span><br /><br />
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
<div id="footer" class="smallgraytext">
|
45
|
+
<a href="/index.html">Home</a> | © 2007 Vassilis Rizopoulos</a>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
</body>
|
50
|
+
</html>
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,102 @@
|
|
1
|
+
/* CSS Document */
|
2
|
+
|
3
|
+
/*PAGE LAYOUT*/
|
4
|
+
body {
|
5
|
+
margin-left: 0px;
|
6
|
+
margin-top: 0px;
|
7
|
+
margin-right: 0px;
|
8
|
+
margin-bottom: 0px;
|
9
|
+
}
|
10
|
+
table {
|
11
|
+
font: 0.9em Tahoma, sans-serif;
|
12
|
+
color: #666666;
|
13
|
+
text-align: center;
|
14
|
+
|
15
|
+
}
|
16
|
+
#logo{float:left; background-image:url(tie_logo.gif); width:234px; height:213px;}
|
17
|
+
#topheader{float:right; width:566px; height:97px; background-color:#F0F0F0; position:relative}
|
18
|
+
#toplinks{position:absolute; right:10px; top:10px;}
|
19
|
+
#menu{float:right; width:566px; height:32px; background-image:url(bg_menu.gif); background-repeat:repeat-x;}
|
20
|
+
#submenu{float:right; width:566px; height:32px; background-image:url(bg_submenu.gif); background-position:top; background-repeat:repeat-x;}
|
21
|
+
#contenttext{float:right; width:566px;}
|
22
|
+
#contentnopanel{float:left; width:800px}
|
23
|
+
#leftpanel{float:left; width:234px;}
|
24
|
+
#footer{float:left; width:800px; background-color:#F0F0F0; padding:10px;}
|
25
|
+
#footernopanel{float:left; width:800px; background-color:#F0F0F0; padding:10px;}
|
26
|
+
/*GRAY PANEL*/
|
27
|
+
.graypanel{
|
28
|
+
border:solid 1px #666666; background-color:#F7F7F7; padding:10px; margin:10px;
|
29
|
+
}
|
30
|
+
|
31
|
+
/*TEXT STYLES*/
|
32
|
+
.bodytext {
|
33
|
+
font: 0.9em Tahoma, sans-serif;
|
34
|
+
color: #666666;
|
35
|
+
}
|
36
|
+
|
37
|
+
.titletext {
|
38
|
+
font: 0.7em Tahoma, sans-serif;
|
39
|
+
font-size:26px;
|
40
|
+
font-weight:bold;
|
41
|
+
color:#CC0000;
|
42
|
+
}
|
43
|
+
.whitetitle {
|
44
|
+
font: 0.7em Tahoma, sans-serif;
|
45
|
+
font-size:36px;
|
46
|
+
font-weight:bold;
|
47
|
+
color:#FFFFFF;
|
48
|
+
}
|
49
|
+
.smalltitle {
|
50
|
+
font: 0.7em Tahoma, sans-serif;
|
51
|
+
font-size:20px;
|
52
|
+
font-weight:bold;
|
53
|
+
color:#CC0000;
|
54
|
+
}
|
55
|
+
.smallwhitetext {
|
56
|
+
font: 0.7em Tahoma, sans-serif;
|
57
|
+
font-size: 11px;
|
58
|
+
font-weight:bold;
|
59
|
+
color: #FFFFFF;
|
60
|
+
}
|
61
|
+
.smallwhitetext a{
|
62
|
+
font: 0.7em Tahoma, sans-serif;
|
63
|
+
font-size: 11px;
|
64
|
+
font-weight:bold;
|
65
|
+
color: #FFFFFF;
|
66
|
+
text-decoration:none;
|
67
|
+
}
|
68
|
+
.smallwhitetext a:hover{
|
69
|
+
text-decoration:underline;
|
70
|
+
}
|
71
|
+
.smallgraytext {
|
72
|
+
font: 0.7em Tahoma, sans-serif;
|
73
|
+
font-size: 11px;
|
74
|
+
font-weight:bold;
|
75
|
+
color:#999999;
|
76
|
+
}
|
77
|
+
.smallgraytext a{
|
78
|
+
font: 0.7em Tahoma, sans-serif;
|
79
|
+
font-size: 11px;
|
80
|
+
font-weight:bold;
|
81
|
+
color:#999999;
|
82
|
+
text-decoration:none;
|
83
|
+
}
|
84
|
+
.smallgraytext a:hover{
|
85
|
+
text-decoration:underline;
|
86
|
+
}
|
87
|
+
.smallredtext {
|
88
|
+
font: 0.7em Tahoma, sans-serif;
|
89
|
+
font-size: 11px;
|
90
|
+
font-weight:bold;
|
91
|
+
color:#CC0000;
|
92
|
+
}
|
93
|
+
.smallredtext a{
|
94
|
+
font: 0.7em Tahoma, sans-serif;
|
95
|
+
font-size: 11px;
|
96
|
+
font-weight:bold;
|
97
|
+
color:#CC0000;
|
98
|
+
text-decoration:none;
|
99
|
+
}
|
100
|
+
.smallredtext a:hover{
|
101
|
+
text-decoration:underline;
|
102
|
+
}
|
Binary file
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__),"..")
|
3
|
+
|
4
|
+
require 'rutema/model'
|
5
|
+
require 'rutema/historian'
|
6
|
+
require 'webrick'
|
7
|
+
require 'rubygems'
|
8
|
+
require 'camping/webrick'
|
9
|
+
|
10
|
+
|
11
|
+
Camping.goes :RutemaWeb
|
12
|
+
|
13
|
+
#This is the module containing the Camping views and controllers for the web interface to rutema
|
14
|
+
module RutemaWeb
|
15
|
+
#The rutema web interface controllers
|
16
|
+
module RutemaWeb::Controllers
|
17
|
+
#This is the main controller
|
18
|
+
#
|
19
|
+
#The various views on the data are found through the query keys
|
20
|
+
class Index < R '/'
|
21
|
+
def get
|
22
|
+
@head_title||="Rutema Historian"
|
23
|
+
@white_title||="Runs"
|
24
|
+
@title||="History"
|
25
|
+
@left_panel=:runs
|
26
|
+
if @input.empty?
|
27
|
+
render :start
|
28
|
+
else
|
29
|
+
if @input["scenario"]
|
30
|
+
@scenario_id=@input[:scenario]
|
31
|
+
scenario=Rutema::Model::Scenario.find(@scenario_id)
|
32
|
+
@title="#{scenario.name} from Run ##{scenario.run_id}"
|
33
|
+
@white_title="Scenario <br/>##{@scenario_id}"
|
34
|
+
render :scenario_in_a_run
|
35
|
+
elsif @input[:run]
|
36
|
+
@run_id=@input[:run]
|
37
|
+
@white_title="Run ##{@run_id}"
|
38
|
+
@title="Summary"
|
39
|
+
render :single_run
|
40
|
+
elsif @input["scenario_name"]
|
41
|
+
@spec_name=@input["scenario_name"]
|
42
|
+
@white_title=@spec_name
|
43
|
+
@title="Summary"
|
44
|
+
render :scenario_by_name
|
45
|
+
elsif @input["scenarios"]
|
46
|
+
@white_title="Scenarios"
|
47
|
+
@title="Summary"
|
48
|
+
@left_panel=:scenarios
|
49
|
+
render :start
|
50
|
+
elsif @input["runs"]
|
51
|
+
@white_title="Runs"
|
52
|
+
@title="Summary"
|
53
|
+
@left_panel=:runs
|
54
|
+
render :start
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
module RutemaWeb::Views
|
61
|
+
#Time format to use for the start and stop times
|
62
|
+
TIME_FORMAT="%y%m%d - %H:%M:%S"
|
63
|
+
#image filename to use for succesfull scenarios
|
64
|
+
IMG_SCE_OK="run_ok.png"
|
65
|
+
#image filename to use for failed scenarios
|
66
|
+
IMG_SCE_ERROR="run_error.png"
|
67
|
+
#image filename to use for unexecuted scenarios
|
68
|
+
IMG_SCE_WARN="run_warn.png"
|
69
|
+
#image filename to use for succesfull steps
|
70
|
+
IMG_STEP_OK="step_ok.png"
|
71
|
+
#image filename to use for failed steps
|
72
|
+
IMG_STEP_ERROR="step_error.png"
|
73
|
+
#image filename to use for unexecuted steps
|
74
|
+
IMG_STEP_WARN="step_warn.png"
|
75
|
+
#The whole page in Markaby
|
76
|
+
def layout
|
77
|
+
xhtml_transitional do
|
78
|
+
head do
|
79
|
+
meta(:name=>"author",:content=>"Vassilis Rizopoulos")
|
80
|
+
link(:rel=>"stylesheet",:href=>"style.css",:type=>"text/css")
|
81
|
+
title { @head_title }
|
82
|
+
end
|
83
|
+
body do
|
84
|
+
div.page!(:align=>"center") do
|
85
|
+
div.content!(:style=>"width:800px") do
|
86
|
+
div.logo!{div.whitetitle(:style=>"margin-top:70px"){@white_title}}
|
87
|
+
div.topheader!{div.bodytext(:align=>"left"){br} }
|
88
|
+
div.menu!{}
|
89
|
+
div.submenu! do
|
90
|
+
div(:align=>"right",:class=>"smallgraytext",:style=>"padding:9px;") do
|
91
|
+
a(:href=>"?runs=all"){"runs"}+" | "+a(:href=>"?scenarios=all"){"scenarios"}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
div.contenttext! do
|
95
|
+
div(:style=>"padding:10px"){span.titletext{@title}}
|
96
|
+
div.bodytext(:style=>"padding:12px;", :align=>"justify"){self<<yield}
|
97
|
+
end
|
98
|
+
leftpanel
|
99
|
+
footer
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
#Start point: No rendering content
|
107
|
+
def start
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
#Renders the information for a specific executed scenario
|
112
|
+
#giving a detailed list of the steps, with status and output
|
113
|
+
def scenario_in_a_run
|
114
|
+
table=Rutema::Model::Step.report_table(:all,:conditions=>["scenario_id = :scenario_id",{:scenario_id=>@scenario_id}])
|
115
|
+
table.replace_column("status") do |r|
|
116
|
+
img_src=IMG_STEP_WARN if "not_executed"==r.status
|
117
|
+
img_src=IMG_STEP_OK if "success"==r.status
|
118
|
+
img_src=IMG_STEP_ERROR if "error"==r.status
|
119
|
+
img(:src=>img_src,:align=>"center")
|
120
|
+
end
|
121
|
+
table.reorder("number","status","name","output","error","duration")
|
122
|
+
table.to_html
|
123
|
+
end
|
124
|
+
#Renders the information for a single run providing the context and a list of the scenarios
|
125
|
+
def single_run
|
126
|
+
ret=""
|
127
|
+
run=Rutema::Model::Run.find(@run_id)
|
128
|
+
if run.context
|
129
|
+
ret<<context_table(run.context)
|
130
|
+
end
|
131
|
+
table=Rutema::Model::Scenario.report_table(:all,:conditions=>["run_id = :run_id",{:run_id=>@run_id}],:except=>["run_id"])
|
132
|
+
table.replace_column("status") do |r|
|
133
|
+
if "not_executed"==r.status
|
134
|
+
img(:src=>IMG_SCE_WARN,:align=>"center")
|
135
|
+
else
|
136
|
+
img_src=IMG_SCE_OK if "success"==r.status
|
137
|
+
img_src=IMG_SCE_ERROR if "error"==r.status
|
138
|
+
a(:href=> "?scenario=#{r.data["id"]}"){img(:src=>img_src,:align=>"center")}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
table.replace_column("version") {|r| r.version ? r.version : "N/A"}
|
142
|
+
table.replace_column("start_time"){|r| r.stop_time ? r.start_time.strftime(TIME_FORMAT) : nil}
|
143
|
+
table.replace_column("stop_time"){|r| r.stop_time.strftime(TIME_FORMAT)}
|
144
|
+
table.reorder("status","name","version","start_time","stop_time")
|
145
|
+
ret<<table.to_html
|
146
|
+
return ret
|
147
|
+
end
|
148
|
+
|
149
|
+
#Renders the summary of all runs for a single scenario
|
150
|
+
def scenario_by_name
|
151
|
+
ret=""
|
152
|
+
begin
|
153
|
+
table=Rutema::Model::Scenario.report_table(:all,:conditions=>["name = :spec_name",{:spec_name=>@spec_name}])
|
154
|
+
if table.empty?
|
155
|
+
ret=p{"no results for #{@spec_name}"}
|
156
|
+
else
|
157
|
+
table.replace_column("status") do |r|
|
158
|
+
if "not_executed"==r.status
|
159
|
+
img(:src=>IMG_SCE_WARN,:align=>"center")
|
160
|
+
else
|
161
|
+
img_src=IMG_SCE_OK if "success"==r.status
|
162
|
+
img_src=IMG_SCE_ERROR if "error"==r.status
|
163
|
+
a(:href=> "?scenario=#{r.data["id"]}"){img(:src=>img_src,:align=>"center")}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
table.replace_column("version") {|r| r.version ? r.version : "N/A"}
|
167
|
+
table.replace_column("start_time"){|r| r.stop_time ? r.start_time.strftime(TIME_FORMAT) : nil}
|
168
|
+
table.replace_column("stop_time"){|r| r.stop_time.strftime(TIME_FORMAT)}
|
169
|
+
table.reorder("status","run_id","version","start_time","stop_time")
|
170
|
+
ret<<table.to_html
|
171
|
+
end
|
172
|
+
rescue
|
173
|
+
puts $!
|
174
|
+
ret=p{"could not retrieve data for #{@spec_name}"}
|
175
|
+
end
|
176
|
+
return ret
|
177
|
+
end
|
178
|
+
private
|
179
|
+
#Constructs the left panel of the page as a list of the test runs
|
180
|
+
def leftpanel
|
181
|
+
div.leftpanel! do
|
182
|
+
div.graypanel(:align=>"justify") do
|
183
|
+
span.bodytext do
|
184
|
+
if @left_panel==:runs
|
185
|
+
#<img src="run_error.png" align="center"/><a href="index.html" class="smallgraytext">1 - 28.06.2007</a>
|
186
|
+
Rutema::Model::Run.find(:all,:select=>"id").reverse.each do |r|
|
187
|
+
a.smallgraytext(:href=>"?run=#{r.id}"){"Run ##{r.id}"}
|
188
|
+
br
|
189
|
+
end
|
190
|
+
elsif @left_panel==:scenarios
|
191
|
+
result=Rutema::Model::Scenario.find(:all).collect{|r| r.name}
|
192
|
+
result.uniq.sort.each do |r|
|
193
|
+
a.smallgraytext(:href=>"?scenario_name=#{r}"){"#{r}"}
|
194
|
+
br
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
#Just a bit of copyright info as a footer
|
203
|
+
def footer
|
204
|
+
div.footer!(:class=>"smallgraytext") do
|
205
|
+
"© 2007 Vassilis Rizopoulos"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
#will render a hash in a table of key||value rows
|
210
|
+
def context_table context
|
211
|
+
table do
|
212
|
+
tr do
|
213
|
+
context.each do |k,v|
|
214
|
+
td {k.to_s}
|
215
|
+
td {v.to_s}
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
#Starts a WEBRick server with the RutemaWeb controller in /rutema
|
224
|
+
def start_server (port=3301,docroot=File.join(File.dirname(__FILE__),"htdocs"),mountpoint="/rutema")
|
225
|
+
include WEBrick
|
226
|
+
dbfile=ARGV.shift
|
227
|
+
if !dbfile
|
228
|
+
puts "please provide a database filename"
|
229
|
+
exit 0
|
230
|
+
end
|
231
|
+
if File.exist?(dbfile)
|
232
|
+
ActiveRecord::Base.establish_connection(:adapter=>"sqlite3", :database=>dbfile )
|
233
|
+
s = HTTPServer.new(:Port => port, :DocumentRoot => docroot )
|
234
|
+
s.mount mountpoint, WEBrick::CampingHandler, RutemaWeb
|
235
|
+
trap("INT") { s.shutdown }
|
236
|
+
s.start
|
237
|
+
else
|
238
|
+
$stderr.puts "Can't find database file '#{dbfile}'"
|
239
|
+
end
|
240
|
+
end
|
data/test/test_historian.rb
CHANGED
@@ -7,25 +7,54 @@ require 'rutema/historian'
|
|
7
7
|
#$DEBUG=true
|
8
8
|
module TestRutema
|
9
9
|
class TestHistorian<Test::Unit::TestCase
|
10
|
-
|
10
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database =>":memory:")
|
11
|
+
Rutema::Model::Schema.up
|
11
12
|
def setup
|
12
|
-
@prev_dir=Dir.pwd
|
13
|
-
Dir.chdir(File.dirname(__FILE__))
|
14
13
|
@configuration=OpenStruct.new
|
15
|
-
@configuration.source=
|
16
|
-
|
14
|
+
@configuration.source=":memory:"
|
15
|
+
a_bunch_of_data
|
17
16
|
end
|
18
17
|
def teardown
|
19
|
-
Dir.chdir(@prev_dir)
|
20
18
|
end
|
21
|
-
|
22
19
|
def test_history
|
23
20
|
assert_nothing_raised() do
|
24
21
|
h=Rutema::Historian.new(@configuration)
|
25
|
-
h.history(
|
26
|
-
h.history("
|
27
|
-
h.history("test5")
|
22
|
+
assert_not_nil( h.history("all"), "There should be some history there" )
|
23
|
+
assert_not_nil(h.history("TC001"), "TC001 should have some history" )
|
24
|
+
assert_nil(h.history("test5"), "NO history expected of test5" )
|
25
|
+
puts h.history("all")
|
26
|
+
puts h.history("TC002")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def a_bunch_of_data
|
31
|
+
runs=[]
|
32
|
+
runs<<Rutema::Model::Run.new(:context=>{:version=>"0.4a"},:scenarios=>success_scenarios)
|
33
|
+
runs<<Rutema::Model::Run.new(:context=>{:version=>"0.4b"},:scenarios=>success_scenarios)
|
34
|
+
runs<<Rutema::Model::Run.new(:context=>{:version=>"0.4c"},:scenarios=>failure_scenarios)
|
35
|
+
runs.each{|r| r.save}
|
36
|
+
end
|
37
|
+
def success_scenarios
|
38
|
+
scenarios=[]
|
39
|
+
1.upto(2) do |i|
|
40
|
+
steps=[]
|
41
|
+
steps<<Rutema::Model::Step.new(:name=>"hard",:number=>1,:status=>"success",
|
42
|
+
:output=>"the first step is hard",:error=>"",:duration=>1)
|
43
|
+
steps<<Rutema::Model::Step.new(:name=>"easy",:number=>2,:status=>"success",
|
44
|
+
:output=>"the next step is easy",:error=>"",:duration=>1)
|
45
|
+
scenarios<<Rutema::Model::Scenario.new(:name=>"TC00#{i}",:version=>"100",
|
46
|
+
:attended=>false,:status=>"success",
|
47
|
+
:start_time=>(Time.now-10000*i),:stop_time=>(Time.now-10000*i),
|
48
|
+
:steps=>steps)
|
28
49
|
end
|
50
|
+
return scenarios
|
51
|
+
end
|
52
|
+
def failure_scenarios
|
53
|
+
failed_step=Rutema::Model::Step.new(:name=>"echo",:number=>1,:status=>"error",
|
54
|
+
:output=>"Hel^.",:error=>"IO error",:duration=>1)
|
55
|
+
[Rutema::Model::Scenario.new(:name=>"TC003",:version=>"10",
|
56
|
+
:attended=>false,:status=>"error",:steps=>[failed_step],
|
57
|
+
:start_time=>(Time.now-10000),:stop_time=>Time.now)]
|
29
58
|
end
|
30
59
|
|
31
60
|
end
|
data/test/test_model.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rutema/model'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'active_record/fixtures'
|
7
|
+
|
8
|
+
module TestRutema
|
9
|
+
class TestModel<Test::Unit::TestCase
|
10
|
+
ActiveRecord::Base.establish_connection(:adapter=>"sqlite3",:dbfile=>":memory:")
|
11
|
+
Rutema::Model::Schema.up
|
12
|
+
#test the CRUD operations
|
13
|
+
def test_create_read_update_delete
|
14
|
+
#create
|
15
|
+
r=Rutema::Model::Run.new
|
16
|
+
context={:tester=>"automatopoulos",:version=>"latest"}
|
17
|
+
r.context=context
|
18
|
+
sc=Rutema::Model::Scenario.new(:name=>"TC000",:attended=>false,:status=>"success",:start_time=>Time.now)
|
19
|
+
sc.steps<<Rutema::Model::Step.new(:name=>"echo",:number=>1,:status=>"success",:output=>"testing is nice",:error=>"",:duration=>1)
|
20
|
+
r.scenarios<<sc
|
21
|
+
assert(r.save, "Failed to save.")
|
22
|
+
#read
|
23
|
+
run=Rutema::Model::Run.find(r.id)
|
24
|
+
assert_equal(context,run.context)
|
25
|
+
assert_equal(sc.name, run.scenarios[0].name)
|
26
|
+
#update
|
27
|
+
new_context={:tester=>"tempelopoulos"}
|
28
|
+
run.context=new_context
|
29
|
+
assert(run.save, "Failed to update.")
|
30
|
+
#delete
|
31
|
+
assert(run.destroy, "Failed to delete.")
|
32
|
+
assert_raise(ActiveRecord::RecordNotFound) {Rutema::Model::Run.find(r.id)}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/test/test_reporter.rb
CHANGED
@@ -14,7 +14,7 @@ module TestRutema
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
class TestActiveRecordReporter<Test::Unit::TestCase
|
17
|
-
DB_FILE="
|
17
|
+
DB_FILE=":memory:"
|
18
18
|
def setup
|
19
19
|
@prev_dir=Dir.pwd
|
20
20
|
Dir.chdir(File.dirname(__FILE__))
|
@@ -29,7 +29,6 @@ module TestRutema
|
|
29
29
|
test2.step=MockCommand.new(2)
|
30
30
|
test2.step=MockCommand.new(3)
|
31
31
|
@status=[test1,test2]
|
32
|
-
FileUtils.rm_rf(DB_FILE)
|
33
32
|
end
|
34
33
|
def teardown
|
35
34
|
Dir.chdir(@prev_dir)
|
@@ -41,8 +40,7 @@ module TestRutema
|
|
41
40
|
specs={"test1"=>spec1,
|
42
41
|
"test2"=>spec2
|
43
42
|
}
|
44
|
-
|
45
|
-
r=Rutema::ActiveRecordReporter.new(definition)
|
43
|
+
r=Rutema::ActiveRecordReporter.new(:dbfile=>DB_FILE)
|
46
44
|
#without configuration
|
47
45
|
assert_nothing_raised() { r.report(specs,@status,@parse_errors,nil) }
|
48
46
|
configuration=OpenStruct.new
|
data/test/test_system.rb
CHANGED
@@ -2,6 +2,8 @@ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
|
2
2
|
$:.unshift File.join(File.dirname(__FILE__),"..","ext")
|
3
3
|
require 'test/unit'
|
4
4
|
require 'ostruct'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'patir/command'
|
5
7
|
|
6
8
|
#$DEBUG=true
|
7
9
|
module TestRutema
|
@@ -86,7 +88,16 @@ EOT
|
|
86
88
|
state2=runner.run("test2",scenario)
|
87
89
|
assert_equal(2, runner.states.size)
|
88
90
|
end
|
89
|
-
|
91
|
+
|
92
|
+
def test_run_exceptions
|
93
|
+
runner=Rutema::Runner.new
|
94
|
+
scenario=Rutema::TestScenario.new
|
95
|
+
step=Rutema::TestStep.new("bad",Patir::RubyCommand.new("bad"){|cmd| raise "Bad command"})
|
96
|
+
scenario.add_step(step)
|
97
|
+
state1=:success
|
98
|
+
assert_nothing_raised() { state1=runner.run("test1",scenario) }
|
99
|
+
assert_equal(:error, state1.status)
|
100
|
+
end
|
90
101
|
def test_reset
|
91
102
|
runner=Rutema::Runner.new
|
92
103
|
scenario=Rutema::TestScenario.new
|
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.
|
7
|
-
date: 2007-05
|
6
|
+
version: "0.4"
|
7
|
+
date: 2007-07-05 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
|
@@ -36,12 +36,26 @@ files:
|
|
36
36
|
- Rakefile
|
37
37
|
- bin/rutemax
|
38
38
|
- bin/rutemah
|
39
|
+
- bin/rutemaweb
|
39
40
|
- lib/rutema/configuration.rb
|
40
41
|
- lib/rutema/specification.rb
|
41
42
|
- lib/rutema/system.rb
|
42
43
|
- lib/rutema/reporter.rb
|
43
44
|
- lib/rutema/reporter_ar.rb
|
44
45
|
- lib/rutema/historian.rb
|
46
|
+
- lib/rutema/model.rb
|
47
|
+
- lib/rutemaweb/htdocs/bg_menu.gif
|
48
|
+
- lib/rutemaweb/htdocs/bg_submenu.gif
|
49
|
+
- lib/rutemaweb/htdocs/run_error.png
|
50
|
+
- lib/rutemaweb/htdocs/run_ok.png
|
51
|
+
- lib/rutemaweb/htdocs/run_warn.png
|
52
|
+
- lib/rutemaweb/htdocs/step_error.png
|
53
|
+
- lib/rutemaweb/htdocs/step_ok.png
|
54
|
+
- lib/rutemaweb/htdocs/step_warn.png
|
55
|
+
- lib/rutemaweb/htdocs/style.css
|
56
|
+
- lib/rutemaweb/htdocs/tie_logo.gif
|
57
|
+
- lib/rutemaweb/htdocs/index.html
|
58
|
+
- lib/rutemaweb/rutemaweb.rb
|
45
59
|
- test/test_configuration.rb
|
46
60
|
- test/test_specification.rb
|
47
61
|
- test/test_system.rb
|
@@ -58,6 +72,7 @@ files:
|
|
58
72
|
test_files:
|
59
73
|
- test/test_configuration.rb
|
60
74
|
- test/test_historian.rb
|
75
|
+
- test/test_model.rb
|
61
76
|
- test/test_reporter.rb
|
62
77
|
- test/test_specification.rb
|
63
78
|
- test/test_system.rb
|
@@ -72,6 +87,7 @@ extra_rdoc_files:
|
|
72
87
|
executables:
|
73
88
|
- rutemax
|
74
89
|
- rutemah
|
90
|
+
- rutemaweb
|
75
91
|
extensions: []
|
76
92
|
|
77
93
|
requirements: []
|
@@ -122,6 +138,15 @@ dependencies:
|
|
122
138
|
- !ruby/object:Gem::Version
|
123
139
|
version: 0.0.0
|
124
140
|
version:
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: camping
|
143
|
+
version_requirement:
|
144
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">"
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 0.0.0
|
149
|
+
version:
|
125
150
|
- !ruby/object:Gem::Dependency
|
126
151
|
name: hoe
|
127
152
|
version_requirement:
|