bf4-metric_fu 2.1.3.1
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 +252 -0
- data/MIT-LICENSE +22 -0
- data/README.md +49 -0
- data/Rakefile +22 -0
- data/TODO +6 -0
- data/lib/base/base_template.rb +182 -0
- data/lib/base/churn_analyzer.rb +38 -0
- data/lib/base/code_issue.rb +100 -0
- data/lib/base/configuration.rb +219 -0
- data/lib/base/flay_analyzer.rb +50 -0
- data/lib/base/flog_analyzer.rb +43 -0
- data/lib/base/generator.rb +166 -0
- data/lib/base/graph.rb +44 -0
- data/lib/base/grouping.rb +42 -0
- data/lib/base/line_numbers.rb +79 -0
- data/lib/base/location.rb +87 -0
- data/lib/base/md5_tracker.rb +52 -0
- data/lib/base/metric_analyzer.rb +331 -0
- data/lib/base/ranking.rb +34 -0
- data/lib/base/rcov_analyzer.rb +43 -0
- data/lib/base/record.rb +43 -0
- data/lib/base/reek_analyzer.rb +164 -0
- data/lib/base/report.rb +110 -0
- data/lib/base/roodi_analyzer.rb +37 -0
- data/lib/base/saikuro_analyzer.rb +48 -0
- data/lib/base/scoring_strategies.rb +29 -0
- data/lib/base/stats_analyzer.rb +37 -0
- data/lib/base/table.rb +108 -0
- data/lib/generators/churn.rb +28 -0
- data/lib/generators/flay.rb +31 -0
- data/lib/generators/flog.rb +113 -0
- data/lib/generators/hotspots.rb +52 -0
- data/lib/generators/rails_best_practices.rb +53 -0
- data/lib/generators/rcov.rb +124 -0
- data/lib/generators/reek.rb +81 -0
- data/lib/generators/roodi.rb +35 -0
- data/lib/generators/saikuro.rb +259 -0
- data/lib/generators/stats.rb +58 -0
- data/lib/graphs/engines/bluff.rb +113 -0
- data/lib/graphs/engines/gchart.rb +157 -0
- data/lib/graphs/flay_grapher.rb +18 -0
- data/lib/graphs/flog_grapher.rb +57 -0
- data/lib/graphs/grapher.rb +11 -0
- data/lib/graphs/rails_best_practices_grapher.rb +19 -0
- data/lib/graphs/rcov_grapher.rb +18 -0
- data/lib/graphs/reek_grapher.rb +30 -0
- data/lib/graphs/roodi_grapher.rb +18 -0
- data/lib/graphs/stats_grapher.rb +20 -0
- data/lib/metric_fu.rb +80 -0
- data/lib/tasks/metric_fu.rake +36 -0
- data/lib/templates/awesome/awesome_template.rb +92 -0
- data/lib/templates/awesome/churn.html.erb +58 -0
- data/lib/templates/awesome/css/buttons.css +82 -0
- data/lib/templates/awesome/css/default.css +91 -0
- data/lib/templates/awesome/css/integrity.css +334 -0
- data/lib/templates/awesome/css/reset.css +7 -0
- data/lib/templates/awesome/css/syntax.css +19 -0
- data/lib/templates/awesome/flay.html.erb +34 -0
- data/lib/templates/awesome/flog.html.erb +55 -0
- data/lib/templates/awesome/hotspots.html.erb +62 -0
- data/lib/templates/awesome/index.html.erb +34 -0
- data/lib/templates/awesome/layout.html.erb +30 -0
- data/lib/templates/awesome/rails_best_practices.html.erb +27 -0
- data/lib/templates/awesome/rcov.html.erb +42 -0
- data/lib/templates/awesome/reek.html.erb +40 -0
- data/lib/templates/awesome/roodi.html.erb +27 -0
- data/lib/templates/awesome/saikuro.html.erb +71 -0
- data/lib/templates/awesome/stats.html.erb +51 -0
- data/lib/templates/javascripts/bluff-min.js +1 -0
- data/lib/templates/javascripts/excanvas.js +35 -0
- data/lib/templates/javascripts/js-class.js +1 -0
- data/lib/templates/standard/churn.html.erb +31 -0
- data/lib/templates/standard/default.css +64 -0
- data/lib/templates/standard/flay.html.erb +34 -0
- data/lib/templates/standard/flog.html.erb +57 -0
- data/lib/templates/standard/hotspots.html.erb +54 -0
- data/lib/templates/standard/index.html.erb +41 -0
- data/lib/templates/standard/rails_best_practices.html.erb +29 -0
- data/lib/templates/standard/rcov.html.erb +43 -0
- data/lib/templates/standard/reek.html.erb +42 -0
- data/lib/templates/standard/roodi.html.erb +29 -0
- data/lib/templates/standard/saikuro.html.erb +84 -0
- data/lib/templates/standard/standard_template.rb +27 -0
- data/lib/templates/standard/stats.html.erb +55 -0
- data/spec/base/base_template_spec.rb +194 -0
- data/spec/base/configuration_spec.rb +277 -0
- data/spec/base/generator_spec.rb +223 -0
- data/spec/base/graph_spec.rb +61 -0
- data/spec/base/line_numbers_spec.rb +62 -0
- data/spec/base/location_spec.rb +127 -0
- data/spec/base/md5_tracker_spec.rb +57 -0
- data/spec/base/metric_analyzer_spec.rb +452 -0
- data/spec/base/ranking_spec.rb +42 -0
- data/spec/base/report_spec.rb +146 -0
- data/spec/base/table_spec.rb +36 -0
- data/spec/generators/churn_spec.rb +41 -0
- data/spec/generators/flay_spec.rb +105 -0
- data/spec/generators/flog_spec.rb +70 -0
- data/spec/generators/hotspots_spec.rb +88 -0
- data/spec/generators/rails_best_practices_spec.rb +52 -0
- data/spec/generators/rcov_spec.rb +180 -0
- data/spec/generators/reek_spec.rb +134 -0
- data/spec/generators/roodi_spec.rb +24 -0
- data/spec/generators/saikuro_spec.rb +74 -0
- data/spec/generators/stats_spec.rb +74 -0
- data/spec/graphs/engines/bluff_spec.rb +19 -0
- data/spec/graphs/engines/gchart_spec.rb +156 -0
- data/spec/graphs/flay_grapher_spec.rb +56 -0
- data/spec/graphs/flog_grapher_spec.rb +108 -0
- data/spec/graphs/rails_best_practices_grapher_spec.rb +61 -0
- data/spec/graphs/rcov_grapher_spec.rb +56 -0
- data/spec/graphs/reek_grapher_spec.rb +65 -0
- data/spec/graphs/roodi_grapher_spec.rb +56 -0
- data/spec/graphs/stats_grapher_spec.rb +68 -0
- data/spec/resources/line_numbers/foo.rb +33 -0
- data/spec/resources/line_numbers/module.rb +11 -0
- data/spec/resources/line_numbers/module_surrounds_class.rb +15 -0
- data/spec/resources/line_numbers/two_classes.rb +11 -0
- data/spec/resources/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
- data/spec/resources/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
- data/spec/resources/saikuro/index_cyclo.html +155 -0
- data/spec/resources/saikuro_sfiles/thing.rb_cyclo.html +11 -0
- data/spec/resources/yml/20090630.yml +7922 -0
- data/spec/resources/yml/metric_missing.yml +1 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +7 -0
- metadata +560 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
module GchartGrapher
|
|
3
|
+
COLORS = %w{009999 FF7400 A60000 008500 E6399B 344AD7 00B860 D5CCB9}
|
|
4
|
+
GCHART_GRAPH_SIZE = "945x317" # maximum permitted image size is 300000 pixels
|
|
5
|
+
|
|
6
|
+
NUMBER_OF_TICKS = 6
|
|
7
|
+
def determine_y_axis_scale(values)
|
|
8
|
+
values.collect! {|val| val || 0.0 }
|
|
9
|
+
if values.empty?
|
|
10
|
+
@max_value = 10
|
|
11
|
+
@yaxis = [0, 2, 4, 6, 8, 10]
|
|
12
|
+
else
|
|
13
|
+
@max_value = values.max + Integer(0.1 * values.max)
|
|
14
|
+
portion_size = (@max_value / (NUMBER_OF_TICKS - 1).to_f).ceil
|
|
15
|
+
@yaxis = []
|
|
16
|
+
NUMBER_OF_TICKS.times {|n| @yaxis << Integer(portion_size * n) }
|
|
17
|
+
@max_value = @yaxis.last
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Grapher
|
|
23
|
+
include MetricFu::GchartGrapher
|
|
24
|
+
|
|
25
|
+
def self.require_graphing_gem
|
|
26
|
+
require 'gchart' if MetricFu.graph_engine == :gchart
|
|
27
|
+
rescue LoadError
|
|
28
|
+
puts "#"*99 + "\n" +
|
|
29
|
+
"If you want to use google charts for graphing, you'll need to install the googlecharts rubygem." +
|
|
30
|
+
"\n" + "#"*99
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class FlayGchartGrapher < FlayGrapher
|
|
35
|
+
def graph!
|
|
36
|
+
determine_y_axis_scale(@flay_score)
|
|
37
|
+
url = Gchart.line(
|
|
38
|
+
:size => GCHART_GRAPH_SIZE,
|
|
39
|
+
:title => URI.escape("Flay: duplication"),
|
|
40
|
+
:data => @flay_score,
|
|
41
|
+
:max_value => @max_value,
|
|
42
|
+
:axis_with_labels => 'x,y',
|
|
43
|
+
:axis_labels => [@labels.values, @yaxis],
|
|
44
|
+
:format => 'file',
|
|
45
|
+
:filename => File.join(MetricFu.output_directory, 'flay.png'))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class FlogGchartGrapher < FlogGrapher
|
|
50
|
+
def graph!
|
|
51
|
+
determine_y_axis_scale(@top_five_percent_average + @flog_average)
|
|
52
|
+
url = Gchart.line(
|
|
53
|
+
:size => GCHART_GRAPH_SIZE,
|
|
54
|
+
:title => URI.escape("Flog: code complexity"),
|
|
55
|
+
:data => [@flog_average, @top_five_percent_average],
|
|
56
|
+
:stacked => false,
|
|
57
|
+
:bar_colors => COLORS[0..1],
|
|
58
|
+
:legend => ['average', 'top 5% average'],
|
|
59
|
+
:custom => "chdlp=t",
|
|
60
|
+
:max_value => @max_value,
|
|
61
|
+
:axis_with_labels => 'x,y',
|
|
62
|
+
:axis_labels => [@labels.values, @yaxis],
|
|
63
|
+
:format => 'file',
|
|
64
|
+
:filename => File.join(MetricFu.output_directory, 'flog.png'))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class RcovGchartGrapher < RcovGrapher
|
|
69
|
+
def graph!
|
|
70
|
+
url = Gchart.line(
|
|
71
|
+
:size => GCHART_GRAPH_SIZE,
|
|
72
|
+
:title => URI.escape("Rcov: code coverage"),
|
|
73
|
+
:data => self.rcov_percent,
|
|
74
|
+
:max_value => 101,
|
|
75
|
+
:axis_with_labels => 'x,y',
|
|
76
|
+
:axis_labels => [self.labels.values, [0,20,40,60,80,100]],
|
|
77
|
+
:format => 'file',
|
|
78
|
+
:filename => File.join(MetricFu.output_directory, 'rcov.png')
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class ReekGchartGrapher < ReekGrapher
|
|
84
|
+
def graph!
|
|
85
|
+
determine_y_axis_scale(@reek_count.values.flatten.uniq)
|
|
86
|
+
values = []
|
|
87
|
+
legend = @reek_count.keys.sort
|
|
88
|
+
legend.collect {|k| values << @reek_count[k]}
|
|
89
|
+
|
|
90
|
+
url = Gchart.line(
|
|
91
|
+
:size => GCHART_GRAPH_SIZE,
|
|
92
|
+
:title => URI.escape("Reek: code smells"),
|
|
93
|
+
:data => values,
|
|
94
|
+
:stacked => false,
|
|
95
|
+
:bar_colors => COLORS,
|
|
96
|
+
:legend => legend,
|
|
97
|
+
:custom => "chdlp=t",
|
|
98
|
+
:max_value => @max_value,
|
|
99
|
+
:axis_with_labels => 'x,y',
|
|
100
|
+
:axis_labels => [@labels.values, @yaxis],
|
|
101
|
+
:format => 'file',
|
|
102
|
+
:filename => File.join(MetricFu.output_directory, 'reek.png'))
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class RoodiGchartGrapher < RoodiGrapher
|
|
107
|
+
def graph!
|
|
108
|
+
determine_y_axis_scale(@roodi_count)
|
|
109
|
+
url = Gchart.line(
|
|
110
|
+
:size => GCHART_GRAPH_SIZE,
|
|
111
|
+
:title => URI.escape("Roodi: potential design problems"),
|
|
112
|
+
:data => @roodi_count,
|
|
113
|
+
:max_value => @max_value,
|
|
114
|
+
:axis_with_labels => 'x,y',
|
|
115
|
+
:axis_labels => [@labels.values, @yaxis],
|
|
116
|
+
:format => 'file',
|
|
117
|
+
:filename => File.join(MetricFu.output_directory, 'roodi.png'))
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class StatsGchartGrapher < StatsGrapher
|
|
122
|
+
def graph!
|
|
123
|
+
determine_y_axis_scale(@loc_counts + @lot_counts)
|
|
124
|
+
url = Gchart.line(
|
|
125
|
+
:size => GCHART_GRAPH_SIZE,
|
|
126
|
+
:title => URI.escape("Stats: LOC & LOT"),
|
|
127
|
+
:data => [@loc_counts, @lot_counts],
|
|
128
|
+
:bar_colors => COLORS[0..1],
|
|
129
|
+
:legend => ['Lines of code', 'Lines of test'],
|
|
130
|
+
:custom => "chdlp=t",
|
|
131
|
+
:max_value => @max_value,
|
|
132
|
+
:axis_with_labels => 'x,y',
|
|
133
|
+
:axis_labels => [@labels.values, @yaxis],
|
|
134
|
+
:format => 'file',
|
|
135
|
+
:filename => File.join(MetricFu.output_directory, 'stats.png'))
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class RailsBestPracticesGchartGrapher < RailsBestPracticesGrapher
|
|
140
|
+
def graph!
|
|
141
|
+
determine_y_axis_scale(@rails_best_practices_count)
|
|
142
|
+
url = Gchart.line(
|
|
143
|
+
:size => GCHART_GRAPH_SIZE,
|
|
144
|
+
:title => URI.escape("Rails Best Practices: design problems"),
|
|
145
|
+
:data => self.rails_best_practices_count,
|
|
146
|
+
:bar_colors => COLORS[0..1],
|
|
147
|
+
:legend => ['Problems'],
|
|
148
|
+
:custom => "chdlp=t",
|
|
149
|
+
:max_value => @max_value,
|
|
150
|
+
:axis_with_labels => 'x,y',
|
|
151
|
+
:axis_labels => [@labels.values, @yaxis],
|
|
152
|
+
:format => 'file',
|
|
153
|
+
:filename => File.join(MetricFu.output_directory, 'rails_best_practices.png')
|
|
154
|
+
)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class FlayGrapher < Grapher
|
|
3
|
+
attr_accessor :flay_score, :labels
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
@flay_score = []
|
|
8
|
+
@labels = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_metrics(metrics, date)
|
|
12
|
+
if metrics && metrics[:flay]
|
|
13
|
+
@flay_score.push(metrics[:flay][:total_score].to_i)
|
|
14
|
+
@labels.update( { @labels.size => date })
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class FlogGrapher < Grapher
|
|
3
|
+
attr_accessor :flog_average, :labels, :top_five_percent_average
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
@flog_average = []
|
|
8
|
+
@labels = {}
|
|
9
|
+
@top_five_percent_average =[]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get_metrics(metrics, date)
|
|
13
|
+
if metrics && metrics[:flog]
|
|
14
|
+
@top_five_percent_average.push(calc_top_five_percent_average(metrics))
|
|
15
|
+
@flog_average.push(metrics[:flog][:average])
|
|
16
|
+
@labels.update( { @labels.size => date })
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def calc_top_five_percent_average(metrics)
|
|
23
|
+
return calc_top_five_percent_average_legacy(metrics) if metrics[:flog][:pages]
|
|
24
|
+
|
|
25
|
+
method_scores = metrics[:flog][:method_containers].inject([]) do |method_scores, container|
|
|
26
|
+
method_scores += container[:methods].values.map {|v| v[:score]}
|
|
27
|
+
end
|
|
28
|
+
method_scores.sort!.reverse!
|
|
29
|
+
|
|
30
|
+
number_of_methods_that_is_five_percent = (method_scores.size * 0.05).ceil
|
|
31
|
+
|
|
32
|
+
total_for_five_percent =
|
|
33
|
+
method_scores[0...number_of_methods_that_is_five_percent].inject(0) { |total, score| total += score }
|
|
34
|
+
if number_of_methods_that_is_five_percent == 0
|
|
35
|
+
0.0
|
|
36
|
+
else
|
|
37
|
+
total_for_five_percent / number_of_methods_that_is_five_percent.to_f
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def calc_top_five_percent_average_legacy(metrics)
|
|
42
|
+
methods = metrics[:flog][:pages].inject([]) {|methods, page| methods << page[:scanned_methods]}
|
|
43
|
+
methods.flatten!
|
|
44
|
+
methods = methods.sort_by {|method| method[:score]}.reverse
|
|
45
|
+
|
|
46
|
+
number_of_methods_that_is_five_percent = (methods.size * 0.05).ceil
|
|
47
|
+
|
|
48
|
+
total_for_five_percent =
|
|
49
|
+
methods[0...number_of_methods_that_is_five_percent].inject(0) {|total, method| total += method[:score] }
|
|
50
|
+
if number_of_methods_that_is_five_percent == 0
|
|
51
|
+
0.0
|
|
52
|
+
else
|
|
53
|
+
total_for_five_percent / number_of_methods_that_is_five_percent.to_f
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class RailsBestPracticesGrapher < Grapher
|
|
3
|
+
attr_accessor :rails_best_practices_count, :labels
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
@rails_best_practices_count = []
|
|
8
|
+
@labels = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_metrics(metrics, date)
|
|
12
|
+
if metrics && metrics[:rails_best_practices]
|
|
13
|
+
size = (metrics[:rails_best_practices][:problems] || []).size
|
|
14
|
+
@rails_best_practices_count.push(size)
|
|
15
|
+
@labels.update( { @labels.size => date })
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class RcovGrapher < Grapher
|
|
3
|
+
attr_accessor :rcov_percent, :labels
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
self.rcov_percent = []
|
|
8
|
+
self.labels = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_metrics(metrics, date)
|
|
12
|
+
if metrics && metrics[:rcov]
|
|
13
|
+
self.rcov_percent.push(metrics[:rcov][:global_percent_run])
|
|
14
|
+
self.labels.update( { self.labels.size => date })
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class ReekGrapher < Grapher
|
|
3
|
+
attr_accessor :reek_count, :labels
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
@reek_count = {}
|
|
8
|
+
@labels = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_metrics(metrics, date)
|
|
12
|
+
if metrics && metrics[:reek]
|
|
13
|
+
counter = @labels.size
|
|
14
|
+
@labels.update( { @labels.size => date })
|
|
15
|
+
|
|
16
|
+
metrics[:reek][:matches].each do |reek_chunk|
|
|
17
|
+
reek_chunk[:code_smells].each do |code_smell|
|
|
18
|
+
# speaking of code smell...
|
|
19
|
+
@reek_count[code_smell[:type]] = [] if @reek_count[code_smell[:type]].nil?
|
|
20
|
+
if @reek_count[code_smell[:type]][counter].nil?
|
|
21
|
+
@reek_count[code_smell[:type]][counter] = 1
|
|
22
|
+
else
|
|
23
|
+
@reek_count[code_smell[:type]][counter] += 1
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class RoodiGrapher < Grapher
|
|
3
|
+
attr_accessor :roodi_count, :labels
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
@roodi_count = []
|
|
8
|
+
@labels = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def get_metrics(metrics, date)
|
|
12
|
+
if metrics && metrics[:roodi]
|
|
13
|
+
@roodi_count.push(metrics[:roodi][:problems].size)
|
|
14
|
+
@labels.update( { @labels.size => date })
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module MetricFu
|
|
2
|
+
class StatsGrapher < Grapher
|
|
3
|
+
attr_accessor :loc_counts, :lot_counts, :labels
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super
|
|
7
|
+
self.loc_counts = []
|
|
8
|
+
self.lot_counts = []
|
|
9
|
+
self.labels = {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get_metrics(metrics, date)
|
|
13
|
+
if metrics && metrics[:stats]
|
|
14
|
+
self.loc_counts.push(metrics[:stats][:codeLOC].to_i)
|
|
15
|
+
self.lot_counts.push(metrics[:stats][:testLOC].to_i)
|
|
16
|
+
self.labels.update( { self.labels.size => date })
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/metric_fu.rb
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
begin
|
|
4
|
+
require 'psych'
|
|
5
|
+
YAML::ENGINE.yamler = 'syck'
|
|
6
|
+
rescue LoadError
|
|
7
|
+
#nothing to report
|
|
8
|
+
end
|
|
9
|
+
# def with_syck(&block)
|
|
10
|
+
# current_engine = YAML::ENGINE.yamler
|
|
11
|
+
# YAML::ENGINE.yamler = 'syck'
|
|
12
|
+
# block.call
|
|
13
|
+
# YAML::ENGINE.yamler = current_engine
|
|
14
|
+
# end
|
|
15
|
+
begin
|
|
16
|
+
require 'active_support'
|
|
17
|
+
require 'active_support/core_ext/object/to_json'
|
|
18
|
+
require 'active_support/core_ext/object/blank'
|
|
19
|
+
require 'active_support/inflector'
|
|
20
|
+
rescue LoadError
|
|
21
|
+
require 'activesupport' unless defined?(ActiveSupport)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module MfDebugger
|
|
25
|
+
class Logger
|
|
26
|
+
class << self
|
|
27
|
+
attr_accessor :debug_on
|
|
28
|
+
@debug_on = false
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.mf_debug(msg,&block)
|
|
33
|
+
if MfDebugger::Logger.debug_on
|
|
34
|
+
if block_given?
|
|
35
|
+
block.call
|
|
36
|
+
end
|
|
37
|
+
STDOUT.puts msg
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
def mf_debug(msg,&block)
|
|
41
|
+
if block_given?
|
|
42
|
+
MfDebugger.mf_debug(msg,&block)
|
|
43
|
+
else
|
|
44
|
+
MfDebugger.mf_debug(msg)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
include MfDebugger
|
|
49
|
+
MfDebugger::Logger.debug_on = !!(ENV['MF_DEBUG'] =~ /true/i)
|
|
50
|
+
|
|
51
|
+
# Load a few things to make our lives easier elsewhere.
|
|
52
|
+
module MetricFu
|
|
53
|
+
LIB_ROOT = File.dirname(__FILE__)
|
|
54
|
+
end
|
|
55
|
+
base_dir = File.join(MetricFu::LIB_ROOT, 'base')
|
|
56
|
+
generator_dir = File.join(MetricFu::LIB_ROOT, 'generators')
|
|
57
|
+
template_dir = File.join(MetricFu::LIB_ROOT, 'templates')
|
|
58
|
+
graph_dir = File.join(MetricFu::LIB_ROOT, 'graphs')
|
|
59
|
+
|
|
60
|
+
# We need to require these two (sic?) things first because our other classes
|
|
61
|
+
# depend on them.
|
|
62
|
+
require File.expand_path File.join(base_dir, 'report')
|
|
63
|
+
require File.expand_path File.join(base_dir, 'generator')
|
|
64
|
+
require File.expand_path File.join(base_dir, 'graph')
|
|
65
|
+
require File.expand_path File.join(base_dir, 'scoring_strategies')
|
|
66
|
+
|
|
67
|
+
# prevent the task from being run multiple times.
|
|
68
|
+
unless Rake::Task.task_defined? "metrics:all"
|
|
69
|
+
# Load the rakefile so users of the gem get the default metric_fu task
|
|
70
|
+
load File.expand_path File.join(MetricFu::LIB_ROOT, 'tasks', 'metric_fu.rake')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Now load everything else that's in the directory
|
|
74
|
+
Dir[File.expand_path File.join(base_dir, '*.rb')].each{|l| require l }
|
|
75
|
+
Dir[File.expand_path File.join(generator_dir, '*.rb')].each {|l| require l }
|
|
76
|
+
Dir[File.expand_path File.join(template_dir, 'standard/*.rb')].each {|l| require l}
|
|
77
|
+
Dir[File.expand_path File.join(template_dir, 'awesome/*.rb')].each {|l| require l}
|
|
78
|
+
require graph_dir + "/grapher"
|
|
79
|
+
Dir[File.expand_path File.join(graph_dir, '*.rb')].each {|l| require l}
|
|
80
|
+
Dir[File.expand_path File.join(graph_dir, 'engines', '*.rb')].each {|l| require l}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
namespace :metrics do
|
|
3
|
+
desc "Generate all metrics reports"
|
|
4
|
+
task :all do
|
|
5
|
+
STDOUT.sync = true
|
|
6
|
+
MetricFu::Configuration.run {}
|
|
7
|
+
MetricFu.metrics.each {|metric|
|
|
8
|
+
mf_debug "** STARTING METRIC #{metric}"
|
|
9
|
+
MetricFu.report.add(metric)
|
|
10
|
+
mf_debug "** ENDING METRIC #{metric}"
|
|
11
|
+
}
|
|
12
|
+
mf_debug "** SAVING REPORT YAML OUTPUT TO #{MetricFu.base_directory}"
|
|
13
|
+
MetricFu.report.save_output(MetricFu.report.to_yaml,
|
|
14
|
+
MetricFu.base_directory,
|
|
15
|
+
"report.yml")
|
|
16
|
+
mf_debug "** SAVING REPORT DATA OUTPUT TO #{MetricFu.data_directory}"
|
|
17
|
+
MetricFu.report.save_output(MetricFu.report.to_yaml,
|
|
18
|
+
MetricFu.data_directory,
|
|
19
|
+
"#{Time.now.strftime("%Y%m%d")}.yml")
|
|
20
|
+
mf_debug "** SAVING TEMPLATIZED REPORT"
|
|
21
|
+
MetricFu.report.save_templatized_report
|
|
22
|
+
|
|
23
|
+
mf_debug "** PREPARING TO GRAPH"
|
|
24
|
+
MetricFu.graphs.each {|graph|
|
|
25
|
+
mf_debug "** Graphing #{graph} with #{MetricFu.graph_engine}"
|
|
26
|
+
MetricFu.graph.add(graph, MetricFu.graph_engine)
|
|
27
|
+
}
|
|
28
|
+
mf_debug "** GENERATING GRAPH"
|
|
29
|
+
MetricFu.graph.generate
|
|
30
|
+
|
|
31
|
+
if MetricFu.report.open_in_browser?
|
|
32
|
+
mf_debug "** OPENING IN BROWSER FROM #{MetricFu.output_directory}"
|
|
33
|
+
MetricFu.report.show_in_browser(MetricFu.output_directory)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|