turbulence 1.2.4 → 1.3.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.
- checksums.yaml +5 -5
- data/.github/workflows/ci.yml +51 -0
- data/CHANGELOG.md +208 -0
- data/Gemfile.lock +47 -24
- data/LICENSE.txt +7 -0
- data/README.md +100 -31
- data/bin/bule +1 -1
- data/docs/scatter-plot.png +0 -0
- data/docs/treemap.png +0 -0
- data/lib/turbulence/calculators/churn.rb +3 -1
- data/lib/turbulence/calculators/complexity.rb +4 -16
- data/lib/turbulence/cli_parser.rb +8 -1
- data/lib/turbulence/command_line_interface.rb +9 -3
- data/lib/turbulence/configuration.rb +4 -2
- data/lib/turbulence/generators/scatterplot.rb +2 -2
- data/lib/turbulence/generators/treemap.rb +2 -2
- data/lib/turbulence/scm/git.rb +1 -1
- data/lib/turbulence/version.rb +1 -1
- data/lib/turbulence.rb +1 -1
- data/spec/turbulence/calculators/churn_spec.rb +50 -62
- data/spec/turbulence/calculators/complexity_spec.rb +2 -5
- data/spec/turbulence/cli_parser_spec.rb +16 -6
- data/spec/turbulence/command_line_interface_spec.rb +39 -7
- data/spec/turbulence/configuration_spec.rb +11 -5
- data/spec/turbulence/generators/scatter_plot_spec.rb +49 -44
- data/spec/turbulence/generators/treemap_spec.rb +7 -7
- data/spec/turbulence/scm/git_spec.rb +7 -6
- data/spec/turbulence/scm/perforce_spec.rb +44 -40
- data/spec/turbulence/turbulence_spec.rb +4 -4
- data/turbulence.gemspec +13 -9
- metadata +59 -29
- data/.travis.yml +0 -6
|
@@ -4,8 +4,8 @@ class Turbulence
|
|
|
4
4
|
attr_reader :metrics_hash, :x_metric, :y_metric
|
|
5
5
|
|
|
6
6
|
def initialize(metrics_hash,
|
|
7
|
-
x_metric =
|
|
8
|
-
y_metric =
|
|
7
|
+
x_metric = :churn,
|
|
8
|
+
y_metric = :complexity)
|
|
9
9
|
@x_metric = x_metric
|
|
10
10
|
@y_metric = y_metric
|
|
11
11
|
@metrics_hash = metrics_hash
|
data/lib/turbulence/scm/git.rb
CHANGED
data/lib/turbulence/version.rb
CHANGED
data/lib/turbulence.rb
CHANGED
|
@@ -5,150 +5,138 @@ describe Turbulence::Calculators::Churn do
|
|
|
5
5
|
let(:config) { Turbulence::Configuration.new }
|
|
6
6
|
|
|
7
7
|
before do
|
|
8
|
-
calculator.
|
|
8
|
+
allow(calculator).to receive(:scm_log_command).and_return("")
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
describe "::for_these_files" do
|
|
12
12
|
it "yields up the filename and score for each file" do
|
|
13
13
|
files = ["lib/corey.rb", "lib/chad.rb"]
|
|
14
|
-
calculator.
|
|
15
|
-
[
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
]
|
|
19
|
-
}
|
|
14
|
+
allow(calculator).to receive(:changes_by_ruby_file).and_return([
|
|
15
|
+
["lib/corey.rb", 5],
|
|
16
|
+
["lib/chad.rb", 10]
|
|
17
|
+
])
|
|
20
18
|
yielded_files = []
|
|
21
19
|
calculator.for_these_files(files) do |filename, score|
|
|
22
20
|
yielded_files << [filename, score]
|
|
23
21
|
end
|
|
24
|
-
yielded_files.
|
|
25
|
-
["lib/chad.rb",10]]
|
|
22
|
+
expect(yielded_files).to match_array([["lib/corey.rb", 5], ["lib/chad.rb", 10]])
|
|
26
23
|
end
|
|
27
24
|
|
|
28
25
|
it "filters the results by the passed-in files" do
|
|
29
26
|
files = ["lib/corey.rb"]
|
|
30
|
-
calculator.
|
|
31
|
-
[
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
]
|
|
35
|
-
}
|
|
27
|
+
allow(calculator).to receive(:changes_by_ruby_file).and_return([
|
|
28
|
+
["lib/corey.rb", 5],
|
|
29
|
+
["lib/chad.rb", 10]
|
|
30
|
+
])
|
|
36
31
|
yielded_files = []
|
|
37
32
|
calculator.for_these_files(files) do |filename, score|
|
|
38
33
|
yielded_files << [filename, score]
|
|
39
34
|
end
|
|
40
|
-
yielded_files.
|
|
35
|
+
expect(yielded_files).to match_array([["lib/corey.rb", 5]])
|
|
41
36
|
end
|
|
42
37
|
end
|
|
43
38
|
|
|
44
39
|
describe "::scm_log_file_lines" do
|
|
45
40
|
it "returns just the file lines" do
|
|
46
|
-
calculator.
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
allow(calculator).to receive(:scm_log_command).and_return(
|
|
42
|
+
"\n\n\n\n10\t6\tlib/turbulence.rb\n\n\n\n17\t2\tlib/eddies.rb\n"
|
|
43
|
+
)
|
|
49
44
|
|
|
50
|
-
calculator.scm_log_file_lines.
|
|
45
|
+
expect(calculator.scm_log_file_lines).to match_array([
|
|
51
46
|
"10\t6\tlib/turbulence.rb",
|
|
52
47
|
"17\t2\tlib/eddies.rb"
|
|
53
|
-
]
|
|
48
|
+
])
|
|
54
49
|
end
|
|
55
50
|
end
|
|
56
51
|
|
|
57
52
|
describe "::counted_line_changes_by_file_by_commit" do
|
|
58
53
|
before do
|
|
59
|
-
calculator.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
]
|
|
64
|
-
}
|
|
54
|
+
allow(calculator).to receive(:scm_log_file_lines).and_return([
|
|
55
|
+
"10\t6\tlib/turbulence.rb",
|
|
56
|
+
"17\t2\tlib/eddies.rb"
|
|
57
|
+
])
|
|
65
58
|
end
|
|
66
59
|
|
|
67
60
|
it "sums up the line changes" do
|
|
68
|
-
calculator.counted_line_changes_by_file_by_commit.
|
|
61
|
+
expect(calculator.counted_line_changes_by_file_by_commit).to match_array([["lib/turbulence.rb", 16], ["lib/eddies.rb", 19]])
|
|
69
62
|
end
|
|
70
63
|
end
|
|
71
|
-
|
|
64
|
+
|
|
72
65
|
describe "::changes_by_ruby_file" do
|
|
73
66
|
before do
|
|
74
|
-
calculator.
|
|
75
|
-
[
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
]
|
|
84
|
-
}
|
|
67
|
+
allow(calculator).to receive(:ruby_files_changed_in_scm).and_return([
|
|
68
|
+
['lib/eddies.rb', 4],
|
|
69
|
+
['lib/turbulence.rb', 5],
|
|
70
|
+
['lib/turbulence.rb', 16],
|
|
71
|
+
['lib/eddies.rb', 2],
|
|
72
|
+
['lib/turbulence.rb', 7],
|
|
73
|
+
['lib/eddies.rb', 19],
|
|
74
|
+
['lib/eddies.rb', 28]
|
|
75
|
+
])
|
|
85
76
|
end
|
|
86
|
-
|
|
77
|
+
|
|
87
78
|
it "groups and sums churns, excluding the last" do
|
|
88
79
|
calculator.compute_mean = false
|
|
89
|
-
calculator.changes_by_ruby_file.
|
|
80
|
+
expect(calculator.changes_by_ruby_file).to match_array([['lib/eddies.rb', 25], ['lib/turbulence.rb', 21]])
|
|
90
81
|
end
|
|
91
82
|
|
|
92
83
|
it "interprets a single entry as zero churn" do
|
|
93
|
-
calculator.
|
|
94
|
-
[
|
|
95
|
-
|
|
96
|
-
]
|
|
97
|
-
}
|
|
84
|
+
allow(calculator).to receive(:ruby_files_changed_in_scm).and_return([
|
|
85
|
+
['lib/eddies.rb', 4],
|
|
86
|
+
])
|
|
98
87
|
calculator.compute_mean = false
|
|
99
|
-
calculator.changes_by_ruby_file.
|
|
88
|
+
expect(calculator.changes_by_ruby_file).to match_array([['lib/eddies.rb', 0]])
|
|
100
89
|
end
|
|
101
|
-
|
|
90
|
+
|
|
102
91
|
it "groups and takes the mean of churns, excluding the last" do
|
|
103
92
|
calculator.compute_mean = true
|
|
104
|
-
calculator.changes_by_ruby_file.
|
|
93
|
+
expect(calculator.changes_by_ruby_file).to match_array([['lib/eddies.rb', 8], ['lib/turbulence.rb', 10]])
|
|
105
94
|
calculator.compute_mean = false
|
|
106
95
|
end
|
|
107
96
|
end
|
|
108
97
|
|
|
109
98
|
describe "::calculate_mean_of_churn" do
|
|
110
99
|
it "handles zero sample size" do
|
|
111
|
-
calculator.calculate_mean_of_churn(8,0).
|
|
100
|
+
expect(calculator.calculate_mean_of_churn(8, 0)).to eq 8
|
|
112
101
|
end
|
|
113
102
|
|
|
114
|
-
it "returns original churn for sample size = 1"
|
|
115
|
-
calculator.calculate_mean_of_churn(8,1).
|
|
103
|
+
it "returns original churn for sample size = 1" do
|
|
104
|
+
expect(calculator.calculate_mean_of_churn(8, 1)).to eq 8
|
|
116
105
|
end
|
|
117
106
|
|
|
118
107
|
it "returns churn divided by sample size" do
|
|
119
|
-
calculator.calculate_mean_of_churn(25,3).
|
|
108
|
+
expect(calculator.calculate_mean_of_churn(25, 3)).to eq 8
|
|
120
109
|
end
|
|
121
|
-
|
|
122
110
|
end
|
|
123
111
|
|
|
124
112
|
context "Full stack tests" do
|
|
125
113
|
context "when one ruby file is given" do
|
|
126
114
|
context "with two log entries for file" do
|
|
127
115
|
before do
|
|
128
|
-
calculator.
|
|
116
|
+
allow(calculator).to receive(:scm_log_command).and_return(
|
|
129
117
|
"\n\n\n\n10\t6\tlib/turbulence.rb\n" +
|
|
130
|
-
|
|
131
|
-
|
|
118
|
+
"\n\n\n\n11\t7\tlib/turbulence.rb\n"
|
|
119
|
+
)
|
|
132
120
|
end
|
|
133
121
|
it "gives the line change count for the file" do
|
|
134
122
|
yielded_files = []
|
|
135
123
|
calculator.for_these_files(["lib/turbulence.rb"]) do |filename, score|
|
|
136
124
|
yielded_files << [filename, score]
|
|
137
125
|
end
|
|
138
|
-
yielded_files.
|
|
126
|
+
expect(yielded_files).to match_array([["lib/turbulence.rb", 16]])
|
|
139
127
|
end
|
|
140
128
|
context "with only one log entry for file" do
|
|
141
129
|
before do
|
|
142
|
-
calculator.
|
|
130
|
+
allow(calculator).to receive(:scm_log_command).and_return(
|
|
143
131
|
"\n\n\n\n10\t6\tlib/turbulence.rb\n"
|
|
144
|
-
|
|
132
|
+
)
|
|
145
133
|
end
|
|
146
134
|
it "shows zero churn for the file" do
|
|
147
135
|
yielded_files = []
|
|
148
136
|
calculator.for_these_files(["lib/turbulence.rb"]) do |filename, score|
|
|
149
137
|
yielded_files << [filename, score]
|
|
150
138
|
end
|
|
151
|
-
yielded_files.
|
|
139
|
+
expect(yielded_files).to match_array([["lib/turbulence.rb", 0]])
|
|
152
140
|
end
|
|
153
141
|
end
|
|
154
142
|
end
|
|
@@ -7,15 +7,12 @@ describe Turbulence::Calculators::Complexity do
|
|
|
7
7
|
describe "::for_these_files" do
|
|
8
8
|
it "yields up the filename and score for each file" do
|
|
9
9
|
files = ["lib/corey.rb", "lib/chad.rb"]
|
|
10
|
-
calculator.
|
|
11
|
-
filename.size
|
|
12
|
-
}
|
|
10
|
+
allow(calculator).to receive(:score_for_file) { |filename| filename.size }
|
|
13
11
|
yielded_files = []
|
|
14
12
|
calculator.for_these_files(files) do |filename, score|
|
|
15
13
|
yielded_files << [filename, score]
|
|
16
14
|
end
|
|
17
|
-
yielded_files.
|
|
18
|
-
["lib/chad.rb",11]]
|
|
15
|
+
expect(yielded_files).to match_array([["lib/corey.rb", 12], ["lib/chad.rb", 11]])
|
|
19
16
|
end
|
|
20
17
|
end
|
|
21
18
|
end
|
|
@@ -10,31 +10,41 @@ describe Turbulence::CommandLineInterface::ConfigParser do
|
|
|
10
10
|
|
|
11
11
|
it "sets directory" do
|
|
12
12
|
parse %w( path/to/compute )
|
|
13
|
-
config.directory.
|
|
13
|
+
expect(config.directory).to eq 'path/to/compute'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it "sets SCM name to 'Perforce'" do
|
|
17
17
|
parse %w( --scm p4 )
|
|
18
|
-
config.scm_name.
|
|
18
|
+
expect(config.scm_name).to eq 'Perforce'
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
it "sets commit range" do
|
|
22
22
|
parse %w( --churn-range f3e1d7a6..830b9d3d9f )
|
|
23
|
-
config.commit_range.
|
|
23
|
+
expect(config.commit_range).to eq 'f3e1d7a6..830b9d3d9f'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "sets compute mean" do
|
|
27
27
|
parse %w( --churn-mean )
|
|
28
|
-
config.compute_mean.
|
|
28
|
+
expect(config.compute_mean).to be true
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it "sets the exclusion pattern" do
|
|
32
32
|
parse %w( --exclude turbulence )
|
|
33
|
-
config.exclusion_pattern.
|
|
33
|
+
expect(config.exclusion_pattern).to eq 'turbulence'
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it "sets the graph type" do
|
|
37
37
|
parse %w( --treemap )
|
|
38
|
-
config.graph_type.
|
|
38
|
+
expect(config.graph_type).to eq 'treemap'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "sets no_open" do
|
|
42
|
+
parse %w( --no-open )
|
|
43
|
+
expect(config.no_open).to be true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "sets output_dir" do
|
|
47
|
+
parse %w( --output spec/reports/turbulence )
|
|
48
|
+
expect(config.output_dir).to eq 'spec/reports/turbulence'
|
|
39
49
|
end
|
|
40
50
|
end
|
|
@@ -6,7 +6,9 @@ describe Turbulence::CommandLineInterface do
|
|
|
6
6
|
|
|
7
7
|
describe "::TEMPLATE_FILES" do
|
|
8
8
|
Turbulence::CommandLineInterface::TEMPLATE_FILES.each do |template_file|
|
|
9
|
-
File.
|
|
9
|
+
it "has #{File.basename(template_file)} in the template path" do
|
|
10
|
+
expect(File.dirname(template_file)).to eq Turbulence::CommandLineInterface::TURBULENCE_TEMPLATE_PATH
|
|
11
|
+
end
|
|
10
12
|
end
|
|
11
13
|
end
|
|
12
14
|
|
|
@@ -16,18 +18,48 @@ describe Turbulence::CommandLineInterface do
|
|
|
16
18
|
end
|
|
17
19
|
it "bundles the files" do
|
|
18
20
|
cli.generate_bundle
|
|
19
|
-
Dir.glob('turbulence/*').sort.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
expect(Dir.glob('turbulence/*').sort).to eq(["turbulence/cc.js",
|
|
22
|
+
"turbulence/highcharts.js",
|
|
23
|
+
"turbulence/jquery.min.js",
|
|
24
|
+
"turbulence/treemap.html",
|
|
25
|
+
"turbulence/turbulence.html"])
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
it "passes along exclusion pattern" do
|
|
27
29
|
cli = Turbulence::CommandLineInterface.new(%w(--exclude turbulence), :output => nil)
|
|
28
30
|
cli.generate_bundle
|
|
29
31
|
lines = File.new('turbulence/cc.js').readlines
|
|
30
|
-
lines.any? { |l| l =~ /turbulence\.rb/ }.
|
|
32
|
+
expect(lines.any? { |l| l =~ /turbulence\.rb/ }).to be false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "outputs to custom directory when --output is specified" do
|
|
36
|
+
custom_dir = 'tmp/custom_output'
|
|
37
|
+
FileUtils.remove_dir(custom_dir, true)
|
|
38
|
+
cli = Turbulence::CommandLineInterface.new(['--output', custom_dir], :output => nil)
|
|
39
|
+
cli.generate_bundle
|
|
40
|
+
expect(Dir.glob("#{custom_dir}/*").sort).to eq(["#{custom_dir}/cc.js",
|
|
41
|
+
"#{custom_dir}/highcharts.js",
|
|
42
|
+
"#{custom_dir}/jquery.min.js",
|
|
43
|
+
"#{custom_dir}/treemap.html",
|
|
44
|
+
"#{custom_dir}/turbulence.html"])
|
|
45
|
+
FileUtils.remove_dir(custom_dir, true)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#output_path" do
|
|
50
|
+
before do
|
|
51
|
+
# Reset the singleton config between tests
|
|
52
|
+
Turbulence.instance_variable_set(:@config, nil)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "defaults to ./turbulence when output_dir is not set" do
|
|
56
|
+
cli = Turbulence::CommandLineInterface.new(%w(.), :output => nil)
|
|
57
|
+
expect(cli.output_path).to eq(File.join(Dir.pwd, "turbulence"))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "returns the custom output_dir when set" do
|
|
61
|
+
cli = Turbulence::CommandLineInterface.new(%w(--output custom/path), :output => nil)
|
|
62
|
+
expect(cli.output_path).to eq('custom/path')
|
|
31
63
|
end
|
|
32
64
|
end
|
|
33
65
|
end
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
require 'rspec'
|
|
2
|
+
require 'rspec/its'
|
|
2
3
|
require 'turbulence'
|
|
3
4
|
|
|
4
5
|
describe Turbulence::Configuration do
|
|
5
6
|
describe "defaults" do
|
|
6
|
-
its(:output)
|
|
7
|
-
its(:directory)
|
|
8
|
-
its(:graph_type)
|
|
9
|
-
its(:scm_name)
|
|
10
|
-
its(:scm)
|
|
7
|
+
its(:output) { should eq(STDOUT) }
|
|
8
|
+
its(:directory) { should eq(Dir.pwd) }
|
|
9
|
+
its(:graph_type) { should eq('turbulence') }
|
|
10
|
+
its(:scm_name) { should eq('Git') }
|
|
11
|
+
its(:scm) { should eq(Turbulence::Scm::Git) }
|
|
12
|
+
its(:no_open) { should eq(false) }
|
|
13
|
+
its(:output_dir) { should be_nil }
|
|
14
|
+
its(:commit_range) { should be_nil }
|
|
15
|
+
its(:compute_mean) { should be_nil }
|
|
16
|
+
its(:exclusion_pattern) { should be_nil }
|
|
11
17
|
end
|
|
12
18
|
end
|
|
13
19
|
|
|
@@ -2,93 +2,98 @@ require 'turbulence'
|
|
|
2
2
|
|
|
3
3
|
describe Turbulence::Generators::ScatterPlot do
|
|
4
4
|
context "with both Metrics" do
|
|
5
|
-
it "generates JavaScript" do
|
|
5
|
+
it "generates JavaScript", :aggregate_failures do
|
|
6
6
|
generator = Turbulence::Generators::ScatterPlot.new(
|
|
7
|
-
"foo.rb" => {
|
|
8
|
-
|
|
7
|
+
"foo.rb" => { :churn => 1,
|
|
8
|
+
:complexity => 2 }
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
generator.to_js.
|
|
12
|
-
generator.to_js.
|
|
13
|
-
generator.to_js.
|
|
14
|
-
generator.to_js.
|
|
11
|
+
expect(generator.to_js).to match(/var directorySeries/)
|
|
12
|
+
expect(generator.to_js).to match(/\"filename\"\:\"foo.rb\"/)
|
|
13
|
+
expect(generator.to_js).to match(/\"x\":1/)
|
|
14
|
+
expect(generator.to_js).to match(/\"y\":2/)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
context "with a missing Metric" do
|
|
19
19
|
it "generates JavaScript" do
|
|
20
20
|
generator = Turbulence::Generators::ScatterPlot.new(
|
|
21
|
-
"foo.rb" => {
|
|
21
|
+
"foo.rb" => { :churn => 1 }
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
-
generator.to_js.
|
|
24
|
+
expect(generator.to_js).to eq 'var directorySeries = {};'
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
describe "#clean_metrics_from_missing_data" do
|
|
29
|
-
let(:spg) {Turbulence::Generators::ScatterPlot.new({})}
|
|
29
|
+
let(:spg) { Turbulence::Generators::ScatterPlot.new({}) }
|
|
30
30
|
|
|
31
31
|
it "removes entries with missing churn" do
|
|
32
|
-
spg.
|
|
33
|
-
|
|
34
|
-
spg.clean_metrics_from_missing_data.should == {}
|
|
32
|
+
allow(spg).to receive(:metrics_hash).and_return("foo.rb" => { :complexity => 88.3 })
|
|
33
|
+
expect(spg.clean_metrics_from_missing_data).to eq({})
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
it "removes entries with missing complexity" do
|
|
38
|
-
spg.
|
|
39
|
-
|
|
40
|
-
spg.clean_metrics_from_missing_data.should == {}
|
|
37
|
+
allow(spg).to receive(:metrics_hash).and_return("foo.rb" => { :churn => 1 })
|
|
38
|
+
expect(spg.clean_metrics_from_missing_data).to eq({})
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
it "keeps entries with churn and complexity present" do
|
|
44
|
-
spg.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
allow(spg).to receive(:metrics_hash).and_return("foo.rb" => {
|
|
43
|
+
:churn => 1,
|
|
44
|
+
:complexity => 88.3,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
expect(spg.clean_metrics_from_missing_data).not_to eq({})
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
describe "#grouped_by_directory" do
|
|
52
|
-
let(:spg) {
|
|
53
|
-
Turbulence::
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
let(:spg) {
|
|
53
|
+
Turbulence::Generators::ScatterPlot.new(
|
|
54
|
+
"lib/foo/foo.rb" => { :churn => 1 },
|
|
55
|
+
"lib/bar.rb" => { :churn => 2 }
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
it "uses \".\" to denote flat hierarchy" do
|
|
60
|
+
allow(spg).to receive(:metrics_hash).and_return("foo.rb" => { :churn => 1 })
|
|
61
|
+
expect(spg.grouped_by_directory).to eq({ "." => [["foo.rb", { :churn => 1 }]] })
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "takes full path into account" do
|
|
65
|
+
expect(spg.grouped_by_directory).to eq({
|
|
66
|
+
"lib/foo" => [["lib/foo/foo.rb", { :churn => 1 }]],
|
|
67
|
+
"lib" => [["lib/bar.rb", { :churn => 2 }]]
|
|
68
|
+
})
|
|
69
|
+
end
|
|
68
70
|
end
|
|
69
71
|
|
|
70
72
|
describe "#file_metrics_for_directory" do
|
|
71
|
-
let(:spg) {Turbulence::Generators::ScatterPlot.new({})}
|
|
73
|
+
let(:spg) { Turbulence::Generators::ScatterPlot.new({}) }
|
|
74
|
+
|
|
72
75
|
it "assigns :filename, :x, :y" do
|
|
73
|
-
spg.file_metrics_for_directory("lib/foo/foo.rb" => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
result = spg.file_metrics_for_directory("lib/foo/foo.rb" => {
|
|
77
|
+
:churn => 1,
|
|
78
|
+
:complexity => 88.2,
|
|
79
|
+
})
|
|
80
|
+
expect(result).to eq [{ :filename => "lib/foo/foo.rb", :x => 1, :y => 88.2 }]
|
|
77
81
|
end
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
describe Turbulence::FileNameMangler do
|
|
81
85
|
subject { Turbulence::FileNameMangler.new }
|
|
86
|
+
|
|
82
87
|
it "anonymizes a string" do
|
|
83
|
-
subject.mangle_name("chad").
|
|
88
|
+
expect(subject.mangle_name("chad")).not_to eq "chad"
|
|
84
89
|
end
|
|
85
90
|
|
|
86
91
|
it "maintains standard directory names" do
|
|
87
|
-
subject.mangle_name("/app/controllers/chad.rb").
|
|
92
|
+
expect(subject.mangle_name("/app/controllers/chad.rb")).to match(%r{/app/controllers/1.rb})
|
|
88
93
|
end
|
|
89
94
|
|
|
90
95
|
it "honors leading path separators" do
|
|
91
|
-
subject.mangle_name("/a/b/c.rb").
|
|
96
|
+
expect(subject.mangle_name("/a/b/c.rb")).to eq "/1/2/3.rb"
|
|
92
97
|
end
|
|
93
98
|
end
|
|
94
99
|
end
|
|
@@ -2,24 +2,24 @@ require 'turbulence'
|
|
|
2
2
|
|
|
3
3
|
describe Turbulence::Generators::TreeMap do
|
|
4
4
|
context "with both Metrics" do
|
|
5
|
-
it "generates JavaScript" do
|
|
5
|
+
it "generates JavaScript", :aggregate_failures do
|
|
6
6
|
generator = Turbulence::Generators::TreeMap.new(
|
|
7
|
-
"foo.rb" => {
|
|
8
|
-
|
|
7
|
+
"foo.rb" => { :churn => 1,
|
|
8
|
+
:complexity => 2 }
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
generator.build_js.
|
|
12
|
-
generator.build_js.
|
|
11
|
+
expect(generator.build_js).to match(/var treemap_data/)
|
|
12
|
+
expect(generator.build_js).to match(/\'foo.rb\'/)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
context "with a missing Metric" do
|
|
17
17
|
it "generates JavaScript" do
|
|
18
18
|
generator = Turbulence::Generators::TreeMap.new(
|
|
19
|
-
"foo.rb" => {
|
|
19
|
+
"foo.rb" => { :churn => 1 }
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
-
generator.build_js.
|
|
22
|
+
expect(generator.build_js).to eq "var treemap_data = [['File', 'Parent', 'Churn (size)', 'Complexity (color)'],\n['Root', null, 0, 0],\n];"
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -5,25 +5,26 @@ require 'fileutils'
|
|
|
5
5
|
describe Turbulence::Scm::Git do
|
|
6
6
|
describe "::is_repo?" do
|
|
7
7
|
before do
|
|
8
|
-
|
|
8
|
+
# Create temp dir in system temp location (outside any git repo)
|
|
9
|
+
@tmp = Dir.mktmpdir('turbulence-test')
|
|
9
10
|
end
|
|
10
11
|
after do
|
|
11
|
-
FileUtils.
|
|
12
|
+
FileUtils.remove_entry(@tmp)
|
|
12
13
|
end
|
|
13
14
|
it "returns true for the working directory" do
|
|
14
|
-
Turbulence::Scm::Git.is_repo?(".").
|
|
15
|
+
expect(Turbulence::Scm::Git.is_repo?(".")).to eq true
|
|
15
16
|
end
|
|
16
17
|
it "return false for a newly created tmp directory" do
|
|
17
|
-
Turbulence::Scm::Git.is_repo?(@tmp).
|
|
18
|
+
expect(Turbulence::Scm::Git.is_repo?(@tmp)).to eq false
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
describe "::log_command" do
|
|
22
23
|
it "takes an optional argument specify to the range" do
|
|
23
|
-
expect{Turbulence::Scm::Git.log_command("d551e63f79a90430e560ea871f4e1e39e6e739bd HEAD")}.to_not raise_error
|
|
24
|
+
expect { Turbulence::Scm::Git.log_command("d551e63f79a90430e560ea871f4e1e39e6e739bd HEAD") }.to_not raise_error
|
|
24
25
|
end
|
|
25
26
|
it "lists insertions/deletions per file and change" do
|
|
26
|
-
Turbulence::Scm::Git.log_command.
|
|
27
|
+
expect(Turbulence::Scm::Git.log_command).to match(/\d+\t\d+\t[A-z.]*/)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
end
|