continuous4r 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -3
- data/Manifest.txt +4 -0
- data/lib/changelog_builder.rb +10 -4
- data/lib/continuous4r.rb +165 -127
- data/lib/dcov_builder.rb +22 -1
- data/lib/flay_builder.rb +53 -7
- data/lib/flog_builder.rb +24 -0
- data/lib/rcov_builder.rb +33 -11
- data/lib/reek_builder.rb +50 -6
- data/lib/saikuro_builder.rb +28 -0
- data/lib/site/body-continuous4r-reports.rhtml +57 -1
- data/lib/site/body-dependencies.rhtml +16 -7
- data/lib/site/body-flay.rhtml +1 -1
- data/lib/site/build.xml.erb +48 -0
- data/lib/site/charts/AC_RunActiveContent.js +292 -0
- data/lib/site/charts/charts.swf +0 -0
- data/lib/site/charts/charts_library/pono.swf +0 -0
- data/lib/site/flog.html.erb +8 -4
- data/lib/site/flog_page.html.erb +20 -1
- data/lib/site/header.rhtml +1 -13
- data/lib/site/menu-continuous4r-reports.rhtml +6 -1
- data/lib/site/menu-task.rhtml +6 -1
- data/lib/tests_builder.rb +10 -0
- data/lib/utils.rb +69 -1
- data/lib/zen_test_formatter.rb +1 -1
- data/lib/zentest_builder.rb +10 -0
- data/website/index.txt +37 -28
- metadata +6 -2
data/History.txt
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
== 0.0.
|
1
|
+
== 0.0.3 2009-03-02
|
2
2
|
|
3
|
-
*
|
4
|
-
|
3
|
+
* Third release
|
4
|
+
Major bug fixes on rcov, ZenTest, tests, and changelog builders
|
5
|
+
Various bug fixes on gems and tasks management
|
6
|
+
Tests made on other projects than mine !!! (Apologies for all errors, everyone)
|
7
|
+
Introduction of reporting quality indicators (will be completed for 0.0.4)
|
8
|
+
The release of 0.0.4 will be here very shortly, this release is here for build capability
|
9
|
+
|
10
|
+
|
11
|
+
To see this release details, go to http://dubois.vct.free.fr/continuous4r
|
data/Manifest.txt
CHANGED
@@ -9,6 +9,10 @@ lib/git_extractor.rb
|
|
9
9
|
lib/subversion_extractor.rb
|
10
10
|
lib/tests_formatter.rb
|
11
11
|
lib/zen_test_formatter.rb
|
12
|
+
lib/site/charts/charts.swf
|
13
|
+
lib/site/build.xml.erb
|
14
|
+
lib/site/charts/AC_RunActiveContent.js
|
15
|
+
lib/site/charts/charts_library/pono.swf
|
12
16
|
lib/site/body-changelog.rhtml
|
13
17
|
lib/site/body-continuous4r-reports.rhtml
|
14
18
|
lib/site/body-dcov.rhtml
|
data/lib/changelog_builder.rb
CHANGED
@@ -6,12 +6,18 @@
|
|
6
6
|
class ChangelogBuilder
|
7
7
|
include Utils
|
8
8
|
|
9
|
+
# Prérequis à la tâche
|
10
|
+
def prerequisite_met?
|
11
|
+
File.exist?(".svn") or File.exist?(".git")
|
12
|
+
end
|
13
|
+
|
14
|
+
# Dans le cas de l'erreur de prérequis
|
15
|
+
def prerequisite_unmet_message
|
16
|
+
" Only Subversion and Git are supported. The 'changelog' task will be empty."
|
17
|
+
end
|
18
|
+
|
9
19
|
# Implementation de la construction de la tache
|
10
20
|
def build(project_name, auto_install, proxy_option)
|
11
|
-
unless File.exist?(".svn") or File.exist?(".git")
|
12
|
-
puts " Only Subversion and Git are supported. The 'changelog' task will be empty."
|
13
|
-
break
|
14
|
-
end
|
15
21
|
# On verifie l'existence de Subversion
|
16
22
|
scm_name = "svn"
|
17
23
|
if File.exist?(".git")
|
data/lib/continuous4r.rb
CHANGED
@@ -1,127 +1,165 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
require File.join(File.dirname(__FILE__), 'tasks', 'continuous4r')
|
4
|
-
|
5
|
-
require 'rubygems'
|
6
|
-
require 'XmlElements'
|
7
|
-
require 'date'
|
8
|
-
require 'erb'
|
9
|
-
require 'stats_formatter.rb'
|
10
|
-
require 'tests_formatter.rb'
|
11
|
-
require 'zen_test_formatter.rb'
|
12
|
-
require 'subversion_extractor.rb'
|
13
|
-
require 'git_extractor.rb'
|
14
|
-
require 'utils.rb'
|
15
|
-
|
16
|
-
# ==============================================================================
|
17
|
-
# Classe modelisant un fichier de description de projet Ruby on Rails
|
18
|
-
# Author:: Vincent Dubois
|
19
|
-
# Date : 03 decembre 2007 - version 0.0.1
|
20
|
-
# 03 fevrier 2009 - version 0.0.2
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
puts "
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
puts "
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
require File.join(File.dirname(__FILE__), 'tasks', 'continuous4r')
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'XmlElements'
|
7
|
+
require 'date'
|
8
|
+
require 'erb'
|
9
|
+
require 'stats_formatter.rb'
|
10
|
+
require 'tests_formatter.rb'
|
11
|
+
require 'zen_test_formatter.rb'
|
12
|
+
require 'subversion_extractor.rb'
|
13
|
+
require 'git_extractor.rb'
|
14
|
+
require 'utils.rb'
|
15
|
+
|
16
|
+
# ==============================================================================
|
17
|
+
# Classe modelisant un fichier de description de projet Ruby on Rails
|
18
|
+
# Author:: Vincent Dubois
|
19
|
+
# Date : 03 decembre 2007 - version 0.0.1
|
20
|
+
# 03 fevrier 2009 - version 0.0.2
|
21
|
+
# 25 fevrier 2009 - version 0.0.3
|
22
|
+
# ==============================================================================
|
23
|
+
module Continuous4r
|
24
|
+
include Utils
|
25
|
+
VERSION = '0.0.3'
|
26
|
+
|
27
|
+
# Support de CruiseControl.rb
|
28
|
+
WORK_DIR = "#{ENV['CC_BUILD_ARTIFACTS'].nil? ? "tmp/continuous4r" : "#{ENV['CC_BUILD_ARTIFACTS']}/continuous4r"}"
|
29
|
+
|
30
|
+
TASKS = ['rdoc','dcov','rcov','stats','changelog','flog','xdoclet','flay','reek','roodi','saikuro','tests','zentest']
|
31
|
+
#TASKS = ['rdoc', 'dcov', 'rcov', 'stats', 'flog', 'xdoclet', 'flay', 'reek']
|
32
|
+
#TASKS = ['zentest']
|
33
|
+
|
34
|
+
METRICS_HASH = Hash.new
|
35
|
+
|
36
|
+
# Méthode qui permet de récupérer le nom du build pour la construction du template notamment
|
37
|
+
def self.build_name
|
38
|
+
@build_name ||= "no build name found"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Methode de generation du site au complet
|
42
|
+
def self.generate_site
|
43
|
+
@build_name = Utils.build_name
|
44
|
+
tasks = TASKS
|
45
|
+
project = XmlElements.fromString(File.read("#{RAILS_ROOT}/continuous4r-project.xml"))
|
46
|
+
generation_date = DateTime.now
|
47
|
+
auto_install = project['auto-install-tools']
|
48
|
+
auto_install ||= "false"
|
49
|
+
|
50
|
+
puts "====================================================================="
|
51
|
+
puts " Continuous Integration for Ruby, starting website generation..."
|
52
|
+
puts "---------------------------------------------------------------------"
|
53
|
+
puts " Project name : #{project['name']}"
|
54
|
+
puts " Project URL : #{project.url.text}"
|
55
|
+
puts " Generation date : #{generation_date}"
|
56
|
+
puts "---------------------------------------------------------------------"
|
57
|
+
|
58
|
+
# Récupération des paramètres de proxy s'ils existent
|
59
|
+
proxy_option = ""
|
60
|
+
if File.exist?("#{(Config::CONFIG['host_os'] =~ /mswin/ ? ENV['USERPROFILE'] : ENV['HOME'])}/.continuous4r/proxy.yml")
|
61
|
+
require 'YAML'
|
62
|
+
proxy_options = YAML.load_file("#{(Config::CONFIG['host_os'] =~ /mswin/ ? ENV['USERPROFILE'] : ENV['HOME'])}/.continuous4r/proxy.yml")
|
63
|
+
proxy_option = " -p \"http://#{proxy_options['proxy']['login']}:#{proxy_options['proxy']['password']}@#{proxy_options['proxy']['server']}:#{proxy_options['proxy']['port']}\""
|
64
|
+
end
|
65
|
+
|
66
|
+
# Vérification de présence et de la version de Rubygems
|
67
|
+
puts " Checking presence and version of RubyGems..."
|
68
|
+
rubygems_version = Utils.run_command("gem --version")
|
69
|
+
if rubygems_version.empty?
|
70
|
+
raise " You don't seem to have RubyGems installed, please go first to http://rubygems.rubyforge.org"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Verification de la presence d'hpricot
|
74
|
+
Utils.verify_gem_presence("hpricot", auto_install, proxy_option)
|
75
|
+
|
76
|
+
# Chargement/Vérification des gems nécessaires à l'application
|
77
|
+
puts " Checking gems for this project, please hold on..."
|
78
|
+
begin
|
79
|
+
project.gems.each('gem') do |gem|
|
80
|
+
puts " Checking for #{gem['name']} gem, version #{gem['version']}..."
|
81
|
+
gem_version = Utils.run_command("gem list #{gem['name']}")
|
82
|
+
if gem_version.empty? or gem_version.index("#{gem['version']}").nil?
|
83
|
+
if project['auto-install-gems'] == "false"
|
84
|
+
raise " The #{gem['name']} gem with version #{gem['version']} is needed. Please run '#{"sudo " unless Config::CONFIG['host_os'] =~ /mswin/}gem install #{gem['name']} --version #{gem['version']}' to install it.\n BUILD FAILED."
|
85
|
+
end
|
86
|
+
gem_installed = Utils.run_command("#{"sudo " unless Config::CONFIG['host_os'] =~ /mswin/}gem install #{gem['name']} --version #{gem['version']}#{proxy_option} 2>&1")
|
87
|
+
if !gem_installed.index("ERROR").nil?
|
88
|
+
raise " Unable to install #{gem['name']} gem with version #{gem['version']}.\n BUILD FAILED."
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
rescue
|
93
|
+
puts " No gems declared for this project, continuing..."
|
94
|
+
end
|
95
|
+
|
96
|
+
puts "---------------------------------------------------------------------"
|
97
|
+
# Création du répertoire de travail
|
98
|
+
if File.exist?(WORK_DIR)
|
99
|
+
FileUtils.rm_rf(WORK_DIR)
|
100
|
+
end
|
101
|
+
FileUtils.mkdir_p WORK_DIR
|
102
|
+
|
103
|
+
# Construction des taches
|
104
|
+
tasks.each do |task|
|
105
|
+
self.build_task task, project['name'], auto_install, proxy_option
|
106
|
+
puts "\n---------------------------------------------------------------------"
|
107
|
+
end
|
108
|
+
puts " All tasks done."
|
109
|
+
puts "\n---------------------------------------------------------------------"
|
110
|
+
|
111
|
+
# On copie les feuilles de styles
|
112
|
+
FileUtils.cp_r("#{File.dirname(__FILE__)}/site/style/", "#{WORK_DIR}/")
|
113
|
+
|
114
|
+
# On copie la partie flash
|
115
|
+
FileUtils.cp_r("#{File.dirname(__FILE__)}/site/charts/", "#{WORK_DIR}/")
|
116
|
+
# Production du fichier XML des indicateurs de qualité
|
117
|
+
page_file = File.open("#{Continuous4r::WORK_DIR}/build.xml", "w")
|
118
|
+
erb = ERB.new(File.read("#{File.dirname(__FILE__)}/site/build.xml.erb"))
|
119
|
+
page_file.write(erb.result)
|
120
|
+
page_file.close
|
121
|
+
|
122
|
+
# On copie les images
|
123
|
+
FileUtils.cp_r("#{File.dirname(__FILE__)}/site/images/", "#{WORK_DIR}/")
|
124
|
+
FileUtils.copy_file("#{File.dirname(__FILE__)}/site/images/continuous4r-logo.png", "#{WORK_DIR}/continuous4r-logo.png")
|
125
|
+
puts " Building project information page..."
|
126
|
+
Utils.erb_run "index", false
|
127
|
+
puts " Building team list page..."
|
128
|
+
Utils.erb_run "team-list", false
|
129
|
+
puts " Building project dependencies page..."
|
130
|
+
Utils.erb_run "dependencies", false
|
131
|
+
puts " Building source control management page..."
|
132
|
+
Utils.erb_run "scm-usage", false
|
133
|
+
puts " Building issue tracking page..."
|
134
|
+
Utils.erb_run "issue-tracking", false
|
135
|
+
puts " Building project reports page..."
|
136
|
+
Utils.erb_run "continuous4r-reports", false
|
137
|
+
tasks.each do |task|
|
138
|
+
task_class = Object.const_get("#{task.capitalize}Builder")
|
139
|
+
task_builder = task_class.new
|
140
|
+
next if task_builder.respond_to?(:prerequisite_met?) and !task_builder.prerequisite_met?
|
141
|
+
puts " Building #{task} page..."
|
142
|
+
Utils.erb_run task, true
|
143
|
+
end
|
144
|
+
puts "\n BUILD SUCCESSFUL."
|
145
|
+
puts "====================================================================="
|
146
|
+
end
|
147
|
+
|
148
|
+
# Methode qui permet de construire une tache de nom donne
|
149
|
+
def self.build_task task, project_name, auto_install, proxy_option
|
150
|
+
require "#{task}_builder.rb"
|
151
|
+
task_class = Object.const_get("#{task.capitalize}Builder")
|
152
|
+
task_builder = task_class.new
|
153
|
+
if task_builder.respond_to?(:prerequisite_met?)
|
154
|
+
if !task_builder.prerequisite_met?
|
155
|
+
puts task_builder.prerequisite_unmet_message
|
156
|
+
return
|
157
|
+
end
|
158
|
+
end
|
159
|
+
task_builder.build(project_name, auto_install, proxy_option)
|
160
|
+
if task_builder.respond_to?(:quality_percentage)
|
161
|
+
METRICS_HASH[task_builder.quality_indicator_name] = task_builder.quality_percentage
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
data/lib/dcov_builder.rb
CHANGED
@@ -29,6 +29,11 @@ module Dcov
|
|
29
29
|
|
30
30
|
def build_stats_body
|
31
31
|
output = ""
|
32
|
+
num_classes = File.read("#{Continuous4r::WORK_DIR}/rdoc/rdoc.log").split(/$/).select { |l| l =~ /^Classes:/ }[0].strip.split(/Classes:/)[1].strip.to_f
|
33
|
+
num_modules = File.read("#{Continuous4r::WORK_DIR}/rdoc/rdoc.log").split(/$/).select { |l| l =~ /^Modules:/ }[0].strip.split(/Modules:/)[1].strip.to_f
|
34
|
+
num_methods = File.read("#{Continuous4r::WORK_DIR}/rdoc/rdoc.log").split(/$/).select { |l| l =~ /^Methods:/ }[0].strip.split(/Methods:/)[1].strip.to_f
|
35
|
+
global_coverage = ((class_coverage.to_f * num_classes) + (module_coverage.to_f * num_modules) + (method_coverage.to_f * num_methods)) / (num_classes + num_modules + num_methods)
|
36
|
+
output << "<h3 #{Utils.percent_to_css_style(global_coverage.to_i)}>Global coverage percentage : #{global_coverage.to_i}%</h3>\n"
|
32
37
|
output << "<h3>Summary</h3><p>\n"
|
33
38
|
output << "<table class='bodyTable' style='width: 200px;'><tr><th>Type</th><th>Coverage</th></tr>"
|
34
39
|
output << "<tr class='a'><td><b>Class</b></td><td style='text-align: right;'>#{class_coverage}%</td></tr>\n"
|
@@ -140,5 +145,21 @@ class DcovBuilder
|
|
140
145
|
raise " Execution of dcov failed.\n BUILD FAILED."
|
141
146
|
end
|
142
147
|
end
|
148
|
+
|
149
|
+
# Methode qui permet d'extraire le pourcentage de qualité extrait d'un builder
|
150
|
+
def quality_percentage
|
151
|
+
require 'hpricot'
|
152
|
+
doc = Hpricot(File.read("#{Continuous4r::WORK_DIR}/dcov/coverage.html"))
|
153
|
+
doc.search('//h3') do |h3|
|
154
|
+
if h3.inner_text.match(/^Global coverage percentage/)
|
155
|
+
return h3.inner_text.split(/Global coverage percentage : /)[1].split(/%/)[0]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Nom de l'indicateur de qualité
|
161
|
+
def quality_indicator_name
|
162
|
+
"rdoc coverage"
|
163
|
+
end
|
143
164
|
end
|
144
|
-
|
165
|
+
|
data/lib/flay_builder.rb
CHANGED
@@ -18,21 +18,67 @@ class FlayBuilder
|
|
18
18
|
files << Dir.glob("lib/**/*.rb")
|
19
19
|
files << Dir.glob("test/**/*.rb")
|
20
20
|
files.flatten!
|
21
|
-
flay_command = "flay"
|
21
|
+
flay_command = "flay -v"
|
22
22
|
files.each do |file|
|
23
23
|
flay_command += " '#{file}'"
|
24
24
|
end
|
25
25
|
flay_result = Utils.run_command(flay_command)
|
26
|
-
matches = flay_result.chomp.split("\n\n")
|
26
|
+
matches = flay_result.chomp.split("\n\n")
|
27
27
|
FileUtils.mkdir("#{Continuous4r::WORK_DIR}/flay")
|
28
28
|
flay_file = File.open("#{Continuous4r::WORK_DIR}/flay/index.html","w")
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
class_index = 0
|
30
|
+
summary = ""
|
31
|
+
duplicate_lines = 0
|
32
|
+
matches.each_with_index do |match, index|
|
33
|
+
if index % 2 == 0
|
34
|
+
flay_file.write("<tr class='#{class_index % 2 == 0 ? "a" : "b"}'>")
|
35
|
+
lines = match.split(/$/)
|
36
|
+
summary = lines[0]
|
37
|
+
flay_file.write("<td>")
|
38
|
+
(1..(lines.length - 1)).to_a.each do |line|
|
39
|
+
flay_file.write("<a href='xdoclet/#{lines[line].split(":")[1].strip.gsub(/\//,'_')}.html##{lines[line].split(":")[2]}' target='_blank'>#{lines[line].strip}</a><br/>")
|
40
|
+
end
|
41
|
+
flay_file.write("</td>")
|
42
|
+
class_index += 1
|
43
|
+
else
|
44
|
+
flay_file.write("<td")
|
45
|
+
begin
|
46
|
+
mass = summary.split(/mass = /)[1].split(/\)/)[0].to_i
|
47
|
+
rescue
|
48
|
+
mass = summary.split(Regexp.new(" = "))[1].split(/\)/)[0].to_i
|
49
|
+
end
|
50
|
+
if summary.match(/IDENTICAL/)
|
51
|
+
flay_file.write(" style='background-color: orange;' title='Not DRY'")
|
52
|
+
elsif mass >= 40
|
53
|
+
flay_file.write(" style='background-color: yellow;' title='Not DRY'")
|
54
|
+
end
|
55
|
+
if summary.match(/IDENTICAL/) or mass >= 40
|
56
|
+
arr_match = match.split(/$/)
|
57
|
+
arr_match.each do |elem|
|
58
|
+
if elem.match(/^A:/) or elem.match(/^ /)
|
59
|
+
duplicate_lines += 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
flay_file.write(">#{summary}<br/><pre>")
|
64
|
+
flay_file.write("#{match}</pre></td></tr>")
|
33
65
|
end
|
34
|
-
|
66
|
+
require 'hpricot'
|
67
|
+
doc = Hpricot(File.read("#{Continuous4r::WORK_DIR}/stats_body.html"))
|
68
|
+
tr_arr = doc.search("//tr")
|
69
|
+
loc = tr_arr[tr_arr.length-1].search("td")[2].inner_text.strip.to_f
|
70
|
+
@dryness = 100.0 - ((duplicate_lines.to_f * 100.0) / loc)
|
35
71
|
end
|
36
72
|
flay_file.close
|
37
73
|
end
|
74
|
+
|
75
|
+
# Methode qui permet d'extraire le pourcentage de qualité extrait d'un builder
|
76
|
+
def quality_percentage
|
77
|
+
@dryness
|
78
|
+
end
|
79
|
+
|
80
|
+
# Nom de l'indicateur de qualité
|
81
|
+
def quality_indicator_name
|
82
|
+
"DRYness"
|
83
|
+
end
|
38
84
|
end
|
data/lib/flog_builder.rb
CHANGED
@@ -117,4 +117,28 @@ class FlogBuilder
|
|
117
117
|
end
|
118
118
|
save_html(ERB.new(File.read(File.join(File.dirname(__FILE__), "site/flog.html.erb"))).result(binding))
|
119
119
|
end
|
120
|
+
|
121
|
+
# Methode qui permet d'extraire le pourcentage de qualité extrait d'un builder
|
122
|
+
def quality_percentage
|
123
|
+
require 'hpricot'
|
124
|
+
doc = Hpricot(File.read("#{Continuous4r::WORK_DIR}/flog/index.html"))
|
125
|
+
doc.search('//h3') do |h3|
|
126
|
+
if h3.inner_text.match(/^Project average score/)
|
127
|
+
score = h3.inner_text.split(/Project average score : /)[1].to_f
|
128
|
+
if score > 100.0
|
129
|
+
percent = 0
|
130
|
+
elsif score < 11.0
|
131
|
+
percent = 100
|
132
|
+
else
|
133
|
+
percent = ((100.0 - score) * 100.0) / 89.0
|
134
|
+
end
|
135
|
+
return percent
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Nom de l'indicateur de qualité
|
141
|
+
def quality_indicator_name
|
142
|
+
"code complexity"
|
143
|
+
end
|
120
144
|
end
|
data/lib/rcov_builder.rb
CHANGED
@@ -6,18 +6,40 @@
|
|
6
6
|
class RcovBuilder
|
7
7
|
include Utils
|
8
8
|
|
9
|
+
# Prérequis à la tâche
|
10
|
+
def prerequisite_met?
|
11
|
+
Dir.glob("test/rcov*.rb").length > 0
|
12
|
+
end
|
13
|
+
|
14
|
+
# Dans le cas de l'erreur de prérequis
|
15
|
+
def prerequisite_unmet_message
|
16
|
+
" No file matching the [test/rcov*.rb] pattern. Rcov task will be ignored."
|
17
|
+
end
|
18
|
+
|
9
19
|
# Implementation de la construction de la tache
|
10
20
|
def build(project_name, auto_install, proxy_option)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
# On verifie la presence de rcov
|
22
|
+
Utils.verify_gem_presence("rcov", auto_install, proxy_option)
|
23
|
+
# On lance la generation
|
24
|
+
puts " Building rcov code coverage report..."
|
25
|
+
rcov_pass = Utils.run_command("rcov --rails --exclude rcov,rubyforge,builder,mime-types,xml-simple test/rcov*.rb")
|
26
|
+
if rcov_pass.index("Finished in").nil?
|
27
|
+
raise " Execution of rcov failed with command 'rcov --rails --exclude rcov,rubyforge,builder,mime-types,xml-simple test/rcov*.rb'.\n BUILD FAILED."
|
28
|
+
end
|
29
|
+
# On recupere le rapport genere
|
30
|
+
Dir.mkdir "#{Continuous4r::WORK_DIR}/rcov"
|
31
|
+
FileUtils.mv("coverage", "#{Continuous4r::WORK_DIR}/rcov/")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Methode qui permet d'extraire le pourcentage de qualite extrait d'un builder
|
35
|
+
def quality_percentage
|
36
|
+
require 'hpricot'
|
37
|
+
doc = Hpricot(File.read("#{Continuous4r::WORK_DIR}/rcov/coverage/index.html"))
|
38
|
+
(doc/'tt[@class^="coverage_code"]')[0].inner_text.split(/%/)[0]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Nom de l'indicateur de qualite
|
42
|
+
def quality_indicator_name
|
43
|
+
"tests coverage"
|
22
44
|
end
|
23
45
|
end
|
data/lib/reek_builder.rb
CHANGED
@@ -3,6 +3,23 @@
|
|
3
3
|
# author: Vincent Dubois
|
4
4
|
# date: 08 fevrier 2009
|
5
5
|
# ==========================================================================
|
6
|
+
require 'reek'
|
7
|
+
require 'reek/options'
|
8
|
+
require 'reek/smells/smells'
|
9
|
+
|
10
|
+
module Reek
|
11
|
+
|
12
|
+
SMELLS = {
|
13
|
+
:defn => [
|
14
|
+
Smells::ControlCouple,
|
15
|
+
Smells::UncommunicativeName,
|
16
|
+
Smells::LongMethod,
|
17
|
+
Smells::UtilityFunction,
|
18
|
+
Smells::FeatureEnvy
|
19
|
+
]
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
6
23
|
class ReekBuilder
|
7
24
|
include Utils
|
8
25
|
|
@@ -13,7 +30,9 @@ class ReekBuilder
|
|
13
30
|
# On lance la generation
|
14
31
|
puts " Building reek report..."
|
15
32
|
files = Array.new
|
16
|
-
files << Dir.glob("app
|
33
|
+
files << Dir.glob("app/controllers/*.rb")
|
34
|
+
files << Dir.glob("app/helpers/*.rb")
|
35
|
+
files << Dir.glob("app/models/*.rb")
|
17
36
|
files << Dir.glob("lib/**/*.rb")
|
18
37
|
files << Dir.glob("test/**/*.rb")
|
19
38
|
files.flatten!
|
@@ -25,14 +44,39 @@ class ReekBuilder
|
|
25
44
|
matches = reek_result.chomp.split("\n\n").map{|m| m.split("\n") }
|
26
45
|
FileUtils.mkdir("#{Continuous4r::WORK_DIR}/reek")
|
27
46
|
reek_file = File.open("#{Continuous4r::WORK_DIR}/reek/index.html","w")
|
28
|
-
|
29
|
-
|
30
|
-
|
47
|
+
count = 0
|
48
|
+
score = 0.0
|
49
|
+
matches.each do |match|
|
50
|
+
smells = Array.new
|
31
51
|
match[1..-1].each do |filename|
|
32
|
-
|
52
|
+
smells << filename if filename.index("[Duplication]").nil?
|
53
|
+
end
|
54
|
+
if smells.length > 0
|
55
|
+
reek_file.write("<tr class='#{count % 2 == 0 ? "a" : "b"}'>")
|
56
|
+
reek_file.write("<td><a href='xdoclet/#{match.first.split("\"")[1].gsub(/\//,'_')}.html' target='_blank'>#{match.first.split("\"")[1]}</a> -- #{smells.length} warning#{"s" if smells.length > 1}</td><td>")
|
57
|
+
if smells.length > 10
|
58
|
+
score += 1.0
|
59
|
+
else
|
60
|
+
score += 0.5
|
61
|
+
end
|
62
|
+
smells.each do |smell|
|
63
|
+
reek_file.write("#{smell}<br/>")
|
64
|
+
end
|
65
|
+
reek_file.write("</td></tr>")
|
66
|
+
count += 1
|
33
67
|
end
|
34
|
-
reek_file.write("</td></tr>")
|
35
68
|
end
|
36
69
|
reek_file.close
|
70
|
+
@percent = 100 - ((score * files.length) / 100)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Methode qui permet d'extraire le pourcentage de qualité extrait d'un builder
|
74
|
+
def quality_percentage
|
75
|
+
@percent
|
76
|
+
end
|
77
|
+
|
78
|
+
# Nom de l'indicateur de qualité
|
79
|
+
def quality_indicator_name
|
80
|
+
"code smells"
|
37
81
|
end
|
38
82
|
end
|