rutemaweb 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ === 0.9.4 / 2008-11-28
2
+ * Configuration file column added to run overview
3
+ * More code to check for old OpenStruct instances of context
4
+ * statistics graphs
5
+ * rutemaweb now depends on gruff (and consequently on RMagick/ImageMagick) for the generation of graphs - It will work without but if you want the pretty colors you need gruff.
1
6
  === 0.9.3 / 2008-11-07
2
7
  * Fixed bug in display of run list (context incorrectly used)
3
8
  === 0.9.2 / 2008-11-05
data/README.txt CHANGED
@@ -3,7 +3,9 @@ rutemaweb http://patir.rubyforge.org/rutema
3
3
  == DESCRIPTION:
4
4
  rutemaweb is the web frontend for rutema.
5
5
 
6
- It can be used as a viewer for database files created with the ActiveRecord reporter.
6
+ It can be used as a viewer for database files created with the rutema ActiveRecord reporter.
7
+ It also provides you with some basic statistics about the tests in your database in the form of
8
+ diagrams of debatable aesthetics but undoubtable value!
7
9
 
8
10
  == FEATURES/PROBLEMS:
9
11
 
@@ -18,6 +20,7 @@ rutemaweb [results.db] and browse to http://localhost:7000 for the glorious view
18
20
  * ruport (http://rubyreports.org/)
19
21
  * acts_as_reportable
20
22
  * erubis
23
+ * gruff/RMagick (optional, but needed if you want to see the statistics graphs)
21
24
 
22
25
  == INSTALL:
23
26
  * sudo gem install rutemaweb
data/Rakefile CHANGED
@@ -20,6 +20,7 @@ Hoe.new('rutemaweb', "#{RutemaWeb::Version::STRING}") do |p|
20
20
  p.extra_deps<<['ramaze','=2008.06']
21
21
  p.extra_deps<<['erubis']
22
22
  p.extra_deps<<['acts_as_reportable']
23
+ p.extra_deps<<['gruff','0.3.4']
23
24
  p.spec_extras={:executables=>["rutemaweb"],
24
25
  :default_executable=>"rutemaweb"}
25
26
  end
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  gem 'ramaze','=2008.06'
3
3
  require 'ramaze'
4
4
  #this fixes a clash with activesupport 2.1.1 (because it checks start_with? but not end_with?)
5
- #end Ramaze on 1.8.6 only creates a start_with? method
5
+ #and Ramaze on 1.8.6 only creates a start_with? method
6
6
  class String; undef_method :start_with? end
7
7
  gem 'activerecord','=2.1.1'
8
8
  require 'active_record'
@@ -10,4 +10,4 @@ gem 'rutema',">=1.0.0"
10
10
  require 'patir/configuration'
11
11
  require 'patir/command'
12
12
  require 'patir/base'
13
- require 'ruport/acts_as_reportable'
13
+ require 'ruport/acts_as_reportable'
@@ -9,7 +9,7 @@ module RutemaWeb
9
9
  module Version
10
10
  MAJOR=0
11
11
  MINOR=9
12
- TINY=3
12
+ TINY=4
13
13
  STRING=[ MAJOR, MINOR, TINY ].join( "." )
14
14
  end
15
15
  #Starts Ramaze
@@ -35,8 +35,17 @@ module Rutema
35
35
  end
36
36
  return st
37
37
  end
38
+ #number of unsuccessful scenarios (does not count setup or teardown scripts)
38
39
  def number_of_failed
39
- self.scenarios.select{|sc| !sc.success?}.size
40
+ self.scenarios.select{|sc| !sc.success? && sc.is_test? }.size
41
+ end
42
+ #returns the number of actual tests (so, don't take into account setup or teardown tests)
43
+ def number_of_tests
44
+ self.scenarios.select{|sc| sc.is_test? }.size
45
+ end
46
+ def config_file
47
+ return nil if self.context.is_a?(OpenStruct)
48
+ return context[:config_file]
40
49
  end
41
50
  end
42
51
 
@@ -53,7 +62,10 @@ module Rutema
53
62
  :conditions=>conditions,
54
63
  :offset => page_num*page_size)
55
64
  end
56
-
65
+ #returns true if the scenario does not belong to a setup or teardown script
66
+ def is_test?
67
+ return !(self.name=~/_setup$/ || self.name=~/_teardown$/)
68
+ end
57
69
  def success?
58
70
  return self.status=="success"
59
71
  end
@@ -51,12 +51,19 @@ module Rutema
51
51
 
52
52
  def run_summary r
53
53
  Ramaze::Log.debug("Summary snippet for #{r}") if @logger
54
- "#{run_link(r)} started at #{time_formatted(r.context[:start_time])}"
54
+ msg="#{run_link(r)}"
55
+ if r.context.is_a?(Hash)
56
+ msg<<" started at #{time_formatted(r.context[:start_time])}"
57
+ end
58
+ return msg
55
59
  end
56
60
 
57
61
  def run_link r
58
62
  "<a class=\"smallgreytext\" href=\"#{run_url(r)}\">Run #{r.id}</a>"
59
63
  end
64
+ def cfg_link cfg
65
+ "<a class=\"smallgreytext\" href=\"/statistics/config_report/#{cfg}\">#{cfg}</a>"
66
+ end
60
67
  #will render a hash in a table of key||value rows
61
68
  def context_table context
62
69
  ret=""
@@ -101,6 +108,18 @@ module Rutema
101
108
 
102
109
  end
103
110
 
111
+ #Contains all the settings that control the display of information for RutemaWeb's controllers
112
+ module Settings
113
+ @@rutemaweb_settings||=Hash.new
114
+ #Set to true to show all setup and teardown scenarios
115
+ def show_setup_teardown= v
116
+ @@rutemaweb_settings[:show_setup_teardown]= v
117
+ end
118
+
119
+ def show_setup_teardown?
120
+ return @@rutemaweb_settings[:show_setup_teardown]
121
+ end
122
+ end
104
123
  #Sets the values we need for public and view directories
105
124
  def self.ramaze_settings
106
125
  Ramaze::Global.public_root = File.expand_path(File.join(File.dirname(__FILE__),"public"))
@@ -109,6 +128,7 @@ module Rutema
109
128
 
110
129
  class MainController < Ramaze::Controller
111
130
  include ViewUtilities
131
+ include Settings
112
132
  map '/'
113
133
  engine :Erubis
114
134
  layout :layout
@@ -132,9 +152,9 @@ module Rutema
132
152
 
133
153
  runs=Rutema::Model::Run.find_on_page(page_number,PAGE_SIZE)
134
154
  runs.each do |r|
135
- dt<<[status_icon(r.status),run_summary(r)]
155
+ dt<<[status_icon(r.status),run_summary(r),r.config_file]
136
156
  end
137
- @content<< Ruport::Data::Table.new(:data=>dt,:column_names=>["status","description"]).to_html
157
+ @content<< Ruport::Data::Table.new(:data=>dt,:column_names=>["status","description","configuration"]).to_html
138
158
  @content<<"<br/>"
139
159
  @content<<run_page_link(page_number,total_pages)
140
160
  return @content
@@ -201,6 +221,7 @@ module Rutema
201
221
  end
202
222
 
203
223
  def error
224
+ @content="There was an error"
204
225
  end
205
226
 
206
227
  def settings
@@ -324,57 +345,102 @@ module Rutema
324
345
  return ((failures.to_f/scenarios.size)*100).round
325
346
  end
326
347
  end
327
-
328
- # class StatisticsController < Ramaze::Controller
329
- # include ViewUtilities
330
- # map '/statistics'
331
- # engine :Erubis
332
- # layout :layout
333
- # deny_layout :graph
334
- # view_root(File.expand_path(File.join(File.dirname(__FILE__),"view")))
335
- # def index
336
- #
337
- # end
338
- # def config_report configuration
339
- # @content="<img src=\"/statistics/graph/#{configuration}\""
340
- # end
341
- # def graph configuration
342
- # response.header['Content-type'] = "image/jpg"
343
- # successful=[]
344
- # failed=[]
345
- # labels=Hash.new
346
- # if configuration
347
- # #find all runs beloging to this configuration
348
- # runs=Rutema::Model::Run.find(:all)
349
- # runs=runs.select{|r| r.context[:config_file]==configuration if r.context.is_a?(Hash)}
350
- # #now extract the data
351
- #
352
- # counter=0
353
- # runs.each do |r|
354
- # fails=r.number_of_failed
355
- # successful<<r.scenarios.size-fails
356
- # failed<<fails
357
- # labels[counter]="R#{r.id}"
358
- # counter+=1
359
- # end
360
- # end
361
- # require 'rubygems'
362
- # require 'gruff'
363
- #
364
- # graph=Gruff::StackedBar.new(640)
365
- #
366
- # graph.data("successful",successful)
367
- # graph.data("failed",failed)
368
- # graph.labels=labels
369
- # return graph.to_blob("JPG")
370
- # end
371
- #
372
- # private
373
- # #extract all the configuration names
374
- # def configurations
375
- # runs=Rutema::Model::Run.find(:all)
376
- # return runs.map{|r| r.context[:config_file] if r.context.is_a?(Hash)}.compact.uniq
377
- # end
378
- # end
348
+
349
+ class StatisticsController < Ramaze::Controller
350
+ include ViewUtilities
351
+ include Settings
352
+ def self.gruff_working= v
353
+ @@gruff_working= v
354
+ end
355
+ def self.gruff_working?
356
+ return @@gruff_working
357
+ end
358
+ begin
359
+ gem 'gruff',"=0.3.4"
360
+ require 'gruff'
361
+ self.gruff_working=true
362
+ rescue LoadError
363
+ self.gruff_working=false
364
+ end
365
+ map '/statistics'
366
+ engine :Erubis
367
+ layout :layout
368
+ deny_layout :graph
369
+ view_root(File.expand_path(File.join(File.dirname(__FILE__),"view")))
370
+ def index
371
+ @title="Rutema"
372
+ @panel_content=panel_configurations
373
+ @content_title="Statistics"
374
+ @content="<p>rutema statistics provide reports that present the results on a time axis<br/>At present you can see the ratio of successful vs. failed test cases over time grouped per configuration file.</p>"
375
+ @content<<"statistics reports require the <a href=\"\">gruff</a> gem. gruff does not appear to be available!<br/>rutemaweb will not be able to produce statistics reports" unless false
376
+ @content
377
+ end
378
+ def config_report configuration=nil
379
+ @title=configuration || "All configurations"
380
+ @panel_content=panel_configurations
381
+ @content_title= configuration || "All configurations"
382
+ if StatisticsController.gruff_working?
383
+ @content="<img src=\"/statistics/graph/#{configuration}\"/>"
384
+ else
385
+ @content="Could not generate graph.<p>This is probably due to a missing gruff/RMagick installation.</p><p>You will need to restart rutemaweb once the issue is resolved.</p>"
386
+ end
387
+ return @content
388
+ end
389
+ def graph configuration=nil
390
+ response.header['Content-type'] = "image/png"
391
+ successful=[]
392
+ failed=[]
393
+ labels=Hash.new
394
+ runs=Rutema::Model::Run.find(:all)
395
+ #find all runs beloging to this configuration
396
+ runs=runs.select{|r| r.context[:config_file]==configuration if r.context.is_a?(Hash)} if configuration
397
+ #now extract the data
398
+ counter=0
399
+ #the normalizer thins out the labels on the x axis so that they won't overlap
400
+ normalizer = 1
401
+ normalizer=runs.size/11 unless runs.size<=11
402
+ runs.each do |r|
403
+ fails=r.number_of_failed
404
+ #the scenarios array includes setup and teardown scripts as well - we want only the actual testcases
405
+ #so we use the added number_of_tests method that filters setup and test scripts
406
+ successful<<r.number_of_tests-fails
407
+ failed<<fails
408
+ #every Nth label
409
+ labels[counter]="R#{r.id}" if counter%normalizer==0
410
+ counter+=1
411
+ end
412
+ respond runs_graph_jpg(successful,failed,labels)
413
+ end
414
+
415
+ private
416
+ #returns a jpg blob
417
+ def runs_graph_jpg successful,failed,labels
418
+ graph=Gruff::StackedBar.new(640)
419
+ graph.theme = {
420
+ :colors => %w(green red yellow blue),
421
+ :marker_color => 'black',
422
+ :background_colors => %w(white grey)
423
+ }
424
+ graph.x_axis_label="#{successful.size} runs"
425
+ graph.data("successful",successful)
426
+ graph.data("failed",failed)
427
+ graph.labels=labels
428
+ graph.marker_font_size=12
429
+ return graph.to_blob("PNG")
430
+ end
431
+ #extract all the configuration names
432
+ def configurations
433
+ runs=Rutema::Model::Run.find(:all)
434
+ return runs.map{|r| r.context[:config_file] if r.context.is_a?(Hash)}.compact.uniq
435
+ end
436
+ def panel_configurations
437
+ ret="<a href=\"/statistics/config_report\">all</a><br/>"
438
+ configurations.each do |cfg|
439
+ ret<<cfg_link(cfg)
440
+ ret<<"<br/>"
441
+ end
442
+ return ret
443
+ end
444
+ end
379
445
  end
380
446
  end
@@ -2,7 +2,7 @@
2
2
  <html xmlns="http://www.w3.org/1999/xhtml">
3
3
  <head>
4
4
  <meta name="author" content="Vassilis Rizopoulos" />
5
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
6
6
  <link rel="stylesheet" href="/css/style.css" type="text/css" />
7
7
  <script src="/js/folding.js" type="text/javascript"></script>
8
8
  <title><%=@title%></title>
@@ -21,7 +21,7 @@
21
21
  </div>
22
22
  <div id="menu">
23
23
  <div align="right" class="smallwhitetext" style="padding:9px;">
24
- <a href="/">Home</a> | <a href="/run">Runs</a> | <a href="/scenario">Scenarios</a>
24
+ <a href="/">Home</a> | <a href="/run">Runs</a> | <a href="/scenario">Scenarios</a> | <a href="/statistics">Statistics</a>
25
25
  </div>
26
26
  </div>
27
27
  <div id="submenu">
@@ -41,7 +41,7 @@
41
41
  <% end %>
42
42
  </div>
43
43
  <div id="footer" class="smallgraytext">
44
- <a href="/">Home</a> | <a href="http://patir.rubyforge.org/rutema">about rutema</a> |
44
+ rutemaweb v<%= RutemaWeb::Version::STRING %> | <a href="/">Home</a> | <a href="http://patir.rubyforge.org/rutema">about rutema</a> |
45
45
  &copy; 2008 <a href="http://www.braveworld.net/riva" target="_blank">Vassilis Rizopoulos</a>
46
46
  </div>
47
47
  </div>
@@ -0,0 +1,48 @@
1
+ require 'test/unit'
2
+ require 'ostruct'
3
+ require 'rutemaweb/ramaze_controller'
4
+ require 'rubygems'
5
+ require 'mocha'
6
+
7
+ class TestModel <Test::Unit::TestCase
8
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database =>":memory:")
9
+ Rutema::Model::Schema.up
10
+ def setup
11
+ @stp=Rutema::Model::Scenario.new
12
+ @stp.name="test_setup"
13
+ @trd=Rutema::Model::Scenario.new
14
+ @trd.name="test_teardown"
15
+ @tst=Rutema::Model::Scenario.new
16
+ @tst.name="test"
17
+ @r=Rutema::Model::Run.new
18
+ @r.scenarios=[@stp,@tst,@trd]
19
+ end
20
+ def test_status
21
+ assert_equal(:success,@r.status)
22
+ t1=Rutema::Model::Scenario.new
23
+ t1.name="failed"
24
+ t1.stubs(:status).returns("error")
25
+ @r.scenarios<<t1
26
+ assert_equal(:error,@r.status)
27
+ end
28
+ def test_is_test?
29
+ assert(!@stp.is_test?, "Setup as test")
30
+ assert(!@trd.is_test?, "Teardown as test")
31
+ assert(@tst.is_test?, "Test not a test")
32
+ end
33
+ def test_number_of_tests
34
+ assert_equal(1, @r.number_of_tests)
35
+ end
36
+ def test_number_of_failed
37
+ t1=Rutema::Model::Scenario.new
38
+ t1.name="failed"
39
+ t1.stubs(:status).returns("error")
40
+ t2=Rutema::Model::Scenario.new
41
+ t2.name="not executed"
42
+ t2.stubs(:status).returns("not_executed")
43
+ @tst.stubs(:status).returns("success")
44
+ @r.scenarios<<t1
45
+ @r.scenarios<<t2
46
+ assert_equal(2,@r.number_of_failed)
47
+ end
48
+ end
@@ -7,9 +7,7 @@ require 'mocha'
7
7
 
8
8
  class TestRutemaWeb <Test::Unit::TestCase
9
9
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database =>":memory:")
10
- def setup
11
10
 
12
- end
13
11
  def test_loading
14
12
  controller=nil
15
13
  assert_nothing_raised() { controller = Rutema::UI::MainController.new }
@@ -19,8 +17,9 @@ class TestRutemaWeb <Test::Unit::TestCase
19
17
  cntlr=test_loading
20
18
  r=mock()
21
19
  r.expects(:id).returns(5).times(2)
22
- r.expects(:context).returns(OpenStruct.new({:start_time=>Time.now}))
23
- r.expects(:status).returns(:success)
20
+ r.stubs(:context).returns({:start_time=>Time.now,:config_file=>"test"})
21
+ r.stubs(:config_file).returns("test")
22
+ r.stubs(:status).returns(:success)
24
23
  t=mock()
25
24
  t.expects(:to_html).returns("mocked")
26
25
  Rutema::Model::Run.expects(:find).returns([r])
@@ -29,7 +28,7 @@ class TestRutemaWeb <Test::Unit::TestCase
29
28
  #Check nothing is raised when calling run (with everything mocked)
30
29
  assert_nothing_raised(){ cntlr.run}
31
30
  end
32
-
31
+
33
32
  def test_runs
34
33
  cntlr=test_loading
35
34
  mock_12_runs
@@ -63,7 +62,7 @@ class TestRutemaWeb <Test::Unit::TestCase
63
62
  #Check nothing is raised when calling run with a page number that is not a number
64
63
  assert_nothing_raised(){ cntlr.runs("atttaaaaack!!")}
65
64
  end
66
-
65
+
67
66
  #unit tests for scenarios
68
67
  def test_scenarios
69
68
  ctlr=test_loading
@@ -71,10 +70,9 @@ class TestRutemaWeb <Test::Unit::TestCase
71
70
  Rutema::Model::Run.expects(:find).returns("")
72
71
  assert_nothing_raised() { ctlr.scenarios }
73
72
  end
74
-
73
+
75
74
  def test_scenario_wrong_arguments
76
75
  ctlr=test_loading
77
- ctlr.expects(:error).returns("super")
78
76
  assert_raise(ArgumentError) { ctlr.scenario("bla","blu") }
79
77
  end
80
78
  private
@@ -84,9 +82,10 @@ class TestRutemaWeb <Test::Unit::TestCase
84
82
  Ruport::Data::Table.expects(:new).returns(t)
85
83
  runs=[mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock()]
86
84
  runs.each do |r|
87
- r.expects(:id).returns(5).times(2)
88
- r.expects(:context).returns(OpenStruct.new({:start_time=>Time.now}))
89
- r.expects(:status).returns(:success)
85
+ r.stubs(:id).returns(5)
86
+ r.stubs(:context).returns({:start_time=>Time.now,:config_file=>"test"})
87
+ r.stubs(:status).returns(:success)
88
+ r.stubs(:config_file).returns("test")
90
89
  end
91
90
  Rutema::Model::Run.expects(:find).returns(runs)
92
91
  Rutema::Model::Run.expects(:count).returns(12)
@@ -98,10 +97,11 @@ class TestRutemaWeb <Test::Unit::TestCase
98
97
  Ruport::Data::Table.expects(:new).returns(t)
99
98
  scenarios=[mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock(),mock()]
100
99
  scenarios.each do |sc|
101
- sc.expects(:name).returns(scenarios.index(sc).to_s).times(2)
100
+ sc.stubs(:name).returns(scenarios.index(sc).to_s)
101
+ sc.stubs(:status).returns(:success)
102
102
  sc.expects(:title).returns(scenarios.index(sc).to_s)
103
103
  sc.expects(:run).returns(scenarios.index(sc))
104
104
  end
105
- Rutema::Model::Scenario.expects(:find).returns(scenarios).times(2)
105
+ Rutema::Model::Scenario.stubs(:find).returns(scenarios)
106
106
  end
107
107
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rutemaweb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vassilis Rizopoulos
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-07 00:00:00 +01:00
12
+ date: 2008-11-28 00:00:00 +01:00
13
13
  default_executable: rutemaweb
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -82,6 +82,16 @@ dependencies:
82
82
  - !ruby/object:Gem::Version
83
83
  version: "0"
84
84
  version:
85
+ - !ruby/object:Gem::Dependency
86
+ name: gruff
87
+ type: :runtime
88
+ version_requirement:
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "="
92
+ - !ruby/object:Gem::Version
93
+ version: 0.3.4
94
+ version:
85
95
  - !ruby/object:Gem::Dependency
86
96
  name: hoe
87
97
  type: :development
@@ -92,7 +102,7 @@ dependencies:
92
102
  - !ruby/object:Gem::Version
93
103
  version: 1.8.2
94
104
  version:
95
- description: "== DESCRIPTION: rutemaweb is the web frontend for rutema. It can be used as a viewer for database files created with the ActiveRecord reporter. == FEATURES/PROBLEMS: == SYNOPSIS: rutemaweb [results.db] and browse to http://localhost:7000 for the glorious view == REQUIREMENTS: * patir (http://patir.rubyforge.org) * activerecord (http://ar.rubyonrails.com/) * sqlite3 (http://rubyforge.org/projects/sqlite-ruby/) * ramaze (http://www.ramaze.net/) * ruport (http://rubyreports.org/) * acts_as_reportable * erubis"
105
+ description: "== DESCRIPTION: rutemaweb is the web frontend for rutema. It can be used as a viewer for database files created with the rutema ActiveRecord reporter. It also provides you with some basic statistics about the tests in your database in the form of diagrams of debatable aesthetics but undoubtable value! == FEATURES/PROBLEMS: == SYNOPSIS: rutemaweb [results.db] and browse to http://localhost:7000 for the glorious view == REQUIREMENTS: * patir (http://patir.rubyforge.org) * activerecord (http://ar.rubyonrails.com/) * sqlite3 (http://rubyforge.org/projects/sqlite-ruby/) * ramaze (http://www.ramaze.net/) * ruport (http://rubyreports.org/) * acts_as_reportable * erubis * gruff/RMagick (optional, but needed if you want to see the statistics graphs)"
96
106
  email: riva@braveworld.net
97
107
  executables:
98
108
  - rutemaweb
@@ -158,4 +168,5 @@ signing_key:
158
168
  specification_version: 2
159
169
  summary: rutemaweb is the web frontend for rutema
160
170
  test_files:
171
+ - test/test_model.rb
161
172
  - test/test_rutemaweb.rb