rutema 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|