metric_fu 1.5.1 → 2.0.0
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 +5 -0
- data/MIT-LICENSE +1 -1
- data/README +8 -6
- data/Rakefile +5 -3
- data/TODO +0 -5
- data/lib/base/base_template.rb +16 -0
- data/lib/base/churn_analyzer.rb +52 -0
- data/lib/base/code_issue.rb +97 -0
- data/lib/base/configuration.rb +4 -2
- data/lib/base/flay_analyzer.rb +50 -0
- data/lib/base/flog_analyzer.rb +43 -0
- data/lib/base/line_numbers.rb +65 -0
- data/lib/base/location.rb +83 -0
- data/lib/base/metric_analyzer.rb +404 -0
- data/lib/base/ranking.rb +33 -0
- data/lib/base/rcov_analyzer.rb +43 -0
- data/lib/base/reek_analyzer.rb +114 -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 +102 -0
- data/lib/generators/hotspots.rb +52 -0
- data/lib/generators/rcov.rb +41 -0
- data/lib/metric_fu.rb +5 -3
- data/lib/templates/awesome/hotspots.html.erb +54 -0
- data/lib/templates/awesome/index.html.erb +3 -0
- data/lib/templates/standard/hotspots.html.erb +54 -0
- data/spec/base/line_numbers_spec.rb +62 -0
- data/spec/generators/rails_best_practices_spec.rb +52 -0
- data/spec/generators/rcov_spec.rb +180 -0
- data/spec/generators/roodi_spec.rb +24 -0
- data/spec/graphs/rails_best_practices_grapher_spec.rb +61 -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/yml/metric_missing.yml +1 -0
- metadata +51 -11
data/lib/metric_fu.rb
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'yaml'
|
3
3
|
begin
|
4
|
+
require 'active_support/core_ext/object/to_json'
|
5
|
+
require 'active_support/core_ext/object/blank'
|
6
|
+
rescue LoadError
|
4
7
|
require 'activesupport'
|
5
|
-
rescue LoadError
|
6
|
-
require 'active_support'
|
7
8
|
end
|
8
9
|
|
9
10
|
# Load a few things to make our lives easier elsewhere.
|
10
11
|
module MetricFu
|
11
12
|
LIB_ROOT = File.dirname(__FILE__)
|
12
13
|
end
|
13
|
-
base_dir
|
14
|
+
base_dir = File.join(MetricFu::LIB_ROOT, 'base')
|
14
15
|
generator_dir = File.join(MetricFu::LIB_ROOT, 'generators')
|
15
16
|
template_dir = File.join(MetricFu::LIB_ROOT, 'templates')
|
16
17
|
graph_dir = File.join(MetricFu::LIB_ROOT, 'graphs')
|
@@ -20,6 +21,7 @@ graph_dir = File.join(MetricFu::LIB_ROOT, 'graphs')
|
|
20
21
|
require File.join(base_dir, 'report')
|
21
22
|
require File.join(base_dir, 'generator')
|
22
23
|
require File.join(base_dir, 'graph')
|
24
|
+
require File.join(base_dir, 'scoring_strategies')
|
23
25
|
|
24
26
|
# prevent the task from being run multiple times.
|
25
27
|
unless Rake::Task.task_defined? "metrics:all"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<h3>Hotspot Results</h3>
|
2
|
+
<p>Meta analysis of your metrics to find hotspots in your code.</p>
|
3
|
+
<br/>
|
4
|
+
|
5
|
+
<% if !@hotspots || @hotspots.size == 0 %>
|
6
|
+
No Hotspots were found.
|
7
|
+
<% elsif @hotspots && @hotspots.size > 0 %>
|
8
|
+
|
9
|
+
<% granularities = [:files, :classes, :methods] %>
|
10
|
+
<table>
|
11
|
+
<tr valign="top">
|
12
|
+
<% granularities.each do |granularity| %>
|
13
|
+
<th width='33%'>
|
14
|
+
<%= granularity.to_s.capitalize %></th>
|
15
|
+
<% end %>
|
16
|
+
</tr>
|
17
|
+
|
18
|
+
<% items = [] %>
|
19
|
+
<% granularities.each_index do |index| %>
|
20
|
+
<% granularity = granularities[index] %>
|
21
|
+
<% items << @hotspots[granularity] %>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<% items_length = 0 %>
|
25
|
+
<% columns = [0, 1, 2] %>
|
26
|
+
<% while (items_length < items[0].length || items_length < items[1].length || items_length < items[2].length) do %>
|
27
|
+
<tr valign="top">
|
28
|
+
<% columns.each do |column| %>
|
29
|
+
<% item = items[column].length >= items_length ? items[column][items_length] : nil %>
|
30
|
+
<% if item %>
|
31
|
+
<td>
|
32
|
+
<b>
|
33
|
+
<%= display_location(item[:location], nil) %>
|
34
|
+
</b>
|
35
|
+
<br/><br/>
|
36
|
+
<!-- TODO HOTSPOTS for metric fu nice metric_link method -->
|
37
|
+
<% item[:details].each do |metric, info| %>
|
38
|
+
<%#= metric_link(@stat, metric, h(metric.to_s.capitalize)) + ": " + h(info)%><br/>
|
39
|
+
<%= "#{metric.to_s.capitalize}: #{info}" %><br/>
|
40
|
+
<% end %>
|
41
|
+
</td>
|
42
|
+
<% else %>
|
43
|
+
<td> </td>
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
<% items_length += 1 %>
|
47
|
+
</tr>
|
48
|
+
<% end %>
|
49
|
+
|
50
|
+
</table>
|
51
|
+
<% end %>
|
52
|
+
|
53
|
+
|
54
|
+
<p>Generated on <%= Time.now.localtime %></p>
|
@@ -27,5 +27,8 @@
|
|
27
27
|
<% if @rails_best_practices %>
|
28
28
|
<li class='even failure'><a href="rails_best_practices.html">Rails Best Practices report</a></li>
|
29
29
|
<% end %>
|
30
|
+
<% if @hotspots %>
|
31
|
+
<li class='even failure'><a href="hotspots.html">Hotspots</a></li>
|
32
|
+
<% end %>
|
30
33
|
</ul>
|
31
34
|
<p>Generated on <%= Time.now.localtime %></p>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<h3>Hotspot Results</h3>
|
2
|
+
<p>Meta analysis of your metrics to find hotspots in your code.</p>
|
3
|
+
<br/>
|
4
|
+
|
5
|
+
<% if !@hotspots || @hotspots.size == 0 %>
|
6
|
+
No Hotspots were found.
|
7
|
+
<% elsif @hotspots && @hotspots.size > 0 %>
|
8
|
+
|
9
|
+
<% granularities = [:files, :classes, :methods] %>
|
10
|
+
<table>
|
11
|
+
<tr valign="top">
|
12
|
+
<% granularities.each do |granularity| %>
|
13
|
+
<th width='33%'>
|
14
|
+
<%= granularity.to_s.capitalize %></th>
|
15
|
+
<% end %>
|
16
|
+
</tr>
|
17
|
+
|
18
|
+
<% items = [] %>
|
19
|
+
<% granularities.each_index do |index| %>
|
20
|
+
<% granularity = granularities[index] %>
|
21
|
+
<% items << @hotspots[granularity] %>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<% items_length = 0 %>
|
25
|
+
<% columns = [0, 1, 2] %>
|
26
|
+
<% while (items_length < items[0].length || items_length < items[1].length || items_length < items[2].length) do %>
|
27
|
+
<tr valign="top">
|
28
|
+
<% columns.each do |column| %>
|
29
|
+
<% item = items[column].length >= items_length ? items[column][items_length] : nil %>
|
30
|
+
<% if item %>
|
31
|
+
<td>
|
32
|
+
<b>
|
33
|
+
<%= display_location(item[:location], nil) %>
|
34
|
+
</b>
|
35
|
+
<br/><br/>
|
36
|
+
<!-- TODO HOTSPOTS for metric fu nice metric_link method -->
|
37
|
+
<% item[:details].each do |metric, info| %>
|
38
|
+
<%#= metric_link(@stat, metric, h(metric.to_s.capitalize)) + ": " + h(info)%><br/>
|
39
|
+
<%= "#{metric.to_s.capitalize}: #{info}" %><br/>
|
40
|
+
<% end %>
|
41
|
+
</td>
|
42
|
+
<% else %>
|
43
|
+
<td> </td>
|
44
|
+
<% end %>
|
45
|
+
<% end %>
|
46
|
+
<% items_length += 1 %>
|
47
|
+
</tr>
|
48
|
+
<% end %>
|
49
|
+
|
50
|
+
</table>
|
51
|
+
<% end %>
|
52
|
+
|
53
|
+
|
54
|
+
<p>Generated on <%= Time.now.localtime %></p>
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe LineNumbers do
|
4
|
+
|
5
|
+
describe "in_method?" do
|
6
|
+
it "should know if a line is NOT in a method" do
|
7
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
8
|
+
ln.in_method?(2).should == false
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should know if a line is in an instance method" do
|
12
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
13
|
+
ln.in_method?(8).should == true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should know if a line is in an class method" do
|
17
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
18
|
+
ln.in_method?(3).should == true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "method_at_line" do
|
23
|
+
it "should know the name of an instance method at a particular line" do
|
24
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
25
|
+
ln.method_at_line(8).should == "Foo#what"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should know the name of a class method at a particular line" do
|
29
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
30
|
+
ln.method_at_line(3).should == "Foo::awesome"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should know the name of a private method at a particular line" do
|
34
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
35
|
+
ln.method_at_line(28).should == "Foo#whoop"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should know the name of a class method defined in a 'class << self block at a particular line" do
|
39
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/foo.rb"))
|
40
|
+
ln.method_at_line(23).should == "Foo::neat"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should know the name of an instance method at a particular line in a file with two classes" do
|
44
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/two_classes.rb"))
|
45
|
+
ln.method_at_line(3).should == "Foo#stuff"
|
46
|
+
ln.method_at_line(9).should == "Bar#stuff"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should work with modules" do
|
50
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/module.rb"))
|
51
|
+
ln.method_at_line(4).should == 'KickAss#get_beat_up?'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should work with module surrounding class" do
|
55
|
+
ln = LineNumbers.new(File.read(File.dirname(__FILE__) + "/../resources/line_numbers/module_surrounds_class.rb"))
|
56
|
+
ln.method_at_line(5).should == "StuffModule::ThingClass#do_it"
|
57
|
+
# ln.method_at_line(12).should == "StuffModule#blah" #why no work?
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe RailsBestPractices do
|
4
|
+
describe "emit method" do
|
5
|
+
it "should gather the raw data" do
|
6
|
+
MetricFu::Configuration.run {}
|
7
|
+
practices = MetricFu::RailsBestPractices.new
|
8
|
+
practices.should_receive(:`).with("rails_best_practices .")
|
9
|
+
practices.emit
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "analyze method" do
|
14
|
+
before :each do
|
15
|
+
output = <<-HERE.gsub(/^[^\S\n]*/, "")
|
16
|
+
./app/views/admin/testimonials/_form.html.erb:17 - replace instance variable with local variable
|
17
|
+
./app/controllers/admin/campaigns_controller.rb:24,45,68,85 - use before_filter for show,edit,update,destroy
|
18
|
+
|
19
|
+
go to http://wiki.github.com/flyerhzm/rails_best_practices to see how to solve these errors.
|
20
|
+
|
21
|
+
Found 2 errors.
|
22
|
+
HERE
|
23
|
+
MetricFu::Configuration.run {}
|
24
|
+
practices = MetricFu::RailsBestPractices.new
|
25
|
+
practices.instance_variable_set(:@output, output)
|
26
|
+
@results = practices.analyze
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should get the total" do
|
30
|
+
@results[:total].should == ["Found 2 errors."]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should get the problems" do
|
34
|
+
@results[:problems].size.should == 2
|
35
|
+
@results[:problems].first.should == { :line => "17",
|
36
|
+
:problem => "replace instance variable with local variable",
|
37
|
+
:file => "./app/views/admin/testimonials/_form.html.erb" }
|
38
|
+
@results[:problems][1].should == { :line => "24,45,68,85",
|
39
|
+
:problem => "use before_filter for show,edit,update,destroy",
|
40
|
+
:file => "./app/controllers/admin/campaigns_controller.rb" }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "to_h method" do
|
45
|
+
it "should put things into a hash" do
|
46
|
+
MetricFu::Configuration.run {}
|
47
|
+
practices = MetricFu::RailsBestPractices.new
|
48
|
+
practices.instance_variable_set(:@rails_best_practices_results, "the_practices")
|
49
|
+
practices.to_h[:rails_best_practices].should == "the_practices"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe MetricFu::Rcov do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
MetricFu::Configuration.run {}
|
7
|
+
File.stub!(:directory?).and_return(true)
|
8
|
+
@rcov = MetricFu::Rcov.new('base_dir')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "emit" do
|
12
|
+
before :each do
|
13
|
+
@rcov.stub!(:puts)
|
14
|
+
MetricFu.rcov[:external] = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should clear out previous output and make output folder" do
|
18
|
+
@rcov.stub!(:`)
|
19
|
+
FileUtils.should_receive(:rm_rf).with(MetricFu::Rcov.metric_directory, :verbose => false)
|
20
|
+
Dir.should_receive(:mkdir).with(MetricFu::Rcov.metric_directory)
|
21
|
+
@rcov.emit
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set the RAILS_ENV" do
|
25
|
+
FileUtils.stub!(:rm_rf)
|
26
|
+
Dir.stub!(:mkdir)
|
27
|
+
MetricFu.rcov[:environment] = "metrics"
|
28
|
+
@rcov.should_receive(:`).with(/RAILS_ENV=metrics/)
|
29
|
+
@rcov.emit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "with RCOV_OUTPUT fed into" do
|
34
|
+
before :each do
|
35
|
+
MetricFu.rcov[:external] = nil
|
36
|
+
File.should_receive(:open).
|
37
|
+
with(MetricFu::Rcov.metric_directory + '/rcov.txt').
|
38
|
+
and_return(mock("io", :read => RCOV_OUTPUT))
|
39
|
+
@files = @rcov.analyze
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "analyze" do
|
43
|
+
it "should compute percent of lines run" do
|
44
|
+
@files["lib/templates/awesome/awesome_template.rb"][:percent_run].should == 13
|
45
|
+
@files["lib/templates/standard/standard_template.rb"][:percent_run].should == 14
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should know which lines were run" do
|
49
|
+
@files["lib/templates/awesome/awesome_template.rb"][:lines].
|
50
|
+
should include({:content=>" require 'fileutils'", :was_run=>true})
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should know which lines NOT were run" do
|
54
|
+
@files["lib/templates/awesome/awesome_template.rb"][:lines].
|
55
|
+
should include({:content=>" if template_exists?(section)", :was_run=>false})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "to_h" do
|
60
|
+
it "should calculate total percentage for all files" do
|
61
|
+
@rcov.to_h[:rcov][:global_percent_run].should == 13.7
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
describe "with external configuration option set" do
|
66
|
+
before :each do
|
67
|
+
@rcov.stub!(:puts)
|
68
|
+
MetricFu.rcov[:external] = "coverage/rcov.txt"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should emit nothing if external configuration option is set" do
|
72
|
+
FileUtils.should_not_receive(:rm_rf)
|
73
|
+
@rcov.emit
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should open the external rcov analysis file" do
|
77
|
+
File.should_receive(:open).
|
78
|
+
with(MetricFu.rcov[:external]).
|
79
|
+
and_return(mock("io", :read => RCOV_OUTPUT))
|
80
|
+
@files = @rcov.analyze
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
RCOV_OUTPUT = <<-HERE
|
87
|
+
Profiling enabled.
|
88
|
+
.............................................................................................................................................................................................
|
89
|
+
|
90
|
+
|
91
|
+
Top 10 slowest examples:
|
92
|
+
0.2707830 MetricFu::RoodiGrapher responding to #get_metrics should push 13 to roodi_count
|
93
|
+
0.1994550 MetricFu::RcovGrapher responding to #get_metrics should update labels with the date
|
94
|
+
0.1985800 MetricFu::ReekGrapher responding to #get_metrics should set a hash of code smells to reek_count
|
95
|
+
0.1919860 MetricFu::ReekGrapher responding to #get_metrics should update labels with the date
|
96
|
+
0.1907400 MetricFu::RoodiGrapher responding to #get_metrics should update labels with the date
|
97
|
+
0.1883000 MetricFu::FlogGrapher responding to #get_metrics should update labels with the date
|
98
|
+
0.1882650 MetricFu::FlayGrapher responding to #get_metrics should push 476 to flay_score
|
99
|
+
0.1868780 MetricFu::FlogGrapher responding to #get_metrics should push to top_five_percent_average
|
100
|
+
0.1847730 MetricFu::FlogGrapher responding to #get_metrics should push 9.9 to flog_average
|
101
|
+
0.1844090 MetricFu::FlayGrapher responding to #get_metrics should update labels with the date
|
102
|
+
|
103
|
+
Finished in 2.517686 seconds
|
104
|
+
|
105
|
+
189 examples, 0 failures
|
106
|
+
================================================================================
|
107
|
+
lib/templates/awesome/awesome_template.rb
|
108
|
+
================================================================================
|
109
|
+
require 'fileutils'
|
110
|
+
|
111
|
+
class AwesomeTemplate < MetricFu::Template
|
112
|
+
|
113
|
+
def write
|
114
|
+
!! # Getting rid of the crap before and after the project name from integrity
|
115
|
+
!! @name = File.basename(Dir.pwd).gsub(/^\w+-|-\w+$/, "")
|
116
|
+
!!
|
117
|
+
!! # Copy Bluff javascripts to output directory
|
118
|
+
!! Dir[File.join(this_directory, '..', 'javascripts', '*')].each do |f|
|
119
|
+
!! FileUtils.copy(f, File.join(MetricFu.output_directory, File.basename(f)))
|
120
|
+
!! end
|
121
|
+
!!
|
122
|
+
!! report.each_pair do |section, contents|
|
123
|
+
!! if template_exists?(section)
|
124
|
+
!! create_instance_var(section, contents)
|
125
|
+
!! @html = erbify(section)
|
126
|
+
!! html = erbify('layout')
|
127
|
+
!! fn = output_filename(section)
|
128
|
+
!! MetricFu.report.save_output(html, MetricFu.output_directory, fn)
|
129
|
+
!! end
|
130
|
+
!! end
|
131
|
+
!!
|
132
|
+
!! # Instance variables we need should already be created from above
|
133
|
+
!! if template_exists?('index')
|
134
|
+
!! @html = erbify('index')
|
135
|
+
!! html = erbify('layout')
|
136
|
+
!! fn = output_filename('index')
|
137
|
+
!! MetricFu.report.save_output(html, MetricFu.output_directory, fn)
|
138
|
+
!! end
|
139
|
+
!! end
|
140
|
+
|
141
|
+
def this_directory
|
142
|
+
!! File.dirname(__FILE__)
|
143
|
+
!! end
|
144
|
+
!! end
|
145
|
+
|
146
|
+
================================================================================
|
147
|
+
lib/templates/standard/standard_template.rb
|
148
|
+
================================================================================
|
149
|
+
class StandardTemplate < MetricFu::Template
|
150
|
+
|
151
|
+
|
152
|
+
def write
|
153
|
+
!! report.each_pair do |section, contents|
|
154
|
+
!! if template_exists?(section)
|
155
|
+
!! create_instance_var(section, contents)
|
156
|
+
!! html = erbify(section)
|
157
|
+
!! fn = output_filename(section)
|
158
|
+
!! MetricFu.report.save_output(html, MetricFu.output_directory, fn)
|
159
|
+
!! end
|
160
|
+
!! end
|
161
|
+
!!
|
162
|
+
!! # Instance variables we need should already be created from above
|
163
|
+
!! if template_exists?('index')
|
164
|
+
!! html = erbify('index')
|
165
|
+
!! fn = output_filename('index')
|
166
|
+
!! MetricFu.report.save_output(html, MetricFu.output_directory, fn)
|
167
|
+
!! end
|
168
|
+
!! end
|
169
|
+
|
170
|
+
def this_directory
|
171
|
+
!! File.dirname(__FILE__)
|
172
|
+
!! end
|
173
|
+
!! end
|
174
|
+
|
175
|
+
HERE
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
|