turbulence 1.2.4 → 1.4.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.
Files changed (37) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +51 -0
  3. data/CHANGELOG.md +227 -0
  4. data/Gemfile.lock +47 -24
  5. data/LICENSE.txt +7 -0
  6. data/README.md +100 -31
  7. data/bin/bule +1 -1
  8. data/docs/scatter-plot.png +0 -0
  9. data/docs/treemap.png +0 -0
  10. data/lib/turbulence/calculators/churn.rb +3 -1
  11. data/lib/turbulence/calculators/complexity.rb +4 -16
  12. data/lib/turbulence/cli_parser.rb +12 -1
  13. data/lib/turbulence/command_line_interface.rb +28 -3
  14. data/lib/turbulence/configuration.rb +10 -6
  15. data/lib/turbulence/generators/scatterplot.rb +10 -4
  16. data/lib/turbulence/generators/treemap.rb +14 -10
  17. data/lib/turbulence/scm/git.rb +1 -1
  18. data/lib/turbulence/version.rb +1 -1
  19. data/lib/turbulence.rb +1 -1
  20. data/spec/turbulence/calculators/churn_spec.rb +50 -62
  21. data/spec/turbulence/calculators/complexity_spec.rb +2 -5
  22. data/spec/turbulence/cli_parser_spec.rb +16 -6
  23. data/spec/turbulence/command_line_interface_spec.rb +59 -7
  24. data/spec/turbulence/configuration_spec.rb +11 -5
  25. data/spec/turbulence/generators/scatter_plot_spec.rb +49 -44
  26. data/spec/turbulence/generators/treemap_spec.rb +7 -7
  27. data/spec/turbulence/scm/git_spec.rb +7 -6
  28. data/spec/turbulence/scm/perforce_spec.rb +44 -40
  29. data/spec/turbulence/turbulence_spec.rb +4 -4
  30. data/template/highcharts-heatmap.js +23 -0
  31. data/template/highcharts-treemap.js +11 -0
  32. data/template/highcharts.js +28 -162
  33. data/template/treemap.html +121 -27
  34. data/template/turbulence.html +34 -12
  35. data/turbulence.gemspec +13 -9
  36. metadata +61 -29
  37. data/.travis.yml +0 -6
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require 'json'
2
3
  require 'launchy'
3
4
  require 'optparse'
4
5
  require 'forwardable'
@@ -14,6 +15,8 @@ class Turbulence
14
15
  TEMPLATE_FILES = [
15
16
  'turbulence.html',
16
17
  'highcharts.js',
18
+ 'highcharts-heatmap.js',
19
+ 'highcharts-treemap.js',
17
20
  'jquery.min.js',
18
21
  'treemap.html',
19
22
  ].map do |filename|
@@ -31,16 +34,38 @@ class Turbulence
31
34
  :directory,
32
35
  :graph_type,
33
36
  :exclusion_pattern,
37
+ :no_open,
38
+ :output_dir,
39
+ :json_output,
34
40
  ]
35
41
 
42
+ def output_path
43
+ output_dir || File.join(Dir.pwd, "turbulence")
44
+ end
45
+
36
46
  def copy_templates_into(directory)
37
47
  FileUtils.cp TEMPLATE_FILES, directory
38
48
  end
39
49
 
40
50
  def generate_bundle
41
- FileUtils.mkdir_p("turbulence")
51
+ if json_output
52
+ generate_json
53
+ else
54
+ generate_html
55
+ end
56
+ end
57
+
58
+ def generate_json
59
+ # Suppress progress output for clean JSON
60
+ config.output = nil
61
+ turb = Turbulence.new(config)
62
+ puts JSON.pretty_generate(turb.metrics)
63
+ end
64
+
65
+ def generate_html
66
+ FileUtils.mkdir_p(output_path)
42
67
 
43
- Dir.chdir("turbulence") do
68
+ Dir.chdir(output_path) do
44
69
  turb = Turbulence.new(config)
45
70
 
46
71
  generator = case graph_type
@@ -55,7 +80,7 @@ class Turbulence
55
80
  end
56
81
 
57
82
  def open_bundle
58
- Launchy.open("file:///#{directory}/turbulence/#{graph_type}.html")
83
+ Launchy.open("file:///#{output_path}/#{graph_type}.html")
59
84
  end
60
85
  end
61
86
  end
@@ -1,5 +1,3 @@
1
- require 'ostruct'
2
-
3
1
  class Turbulence
4
2
  class Configuration
5
3
  attr_accessor *[
@@ -11,13 +9,19 @@ class Turbulence
11
9
  :exclusion_pattern,
12
10
  :graph_type,
13
11
  :output,
12
+ :output_dir,
13
+ :no_open,
14
+ :json_output,
14
15
  ]
15
16
 
16
17
  def initialize
17
- @directory = Dir.pwd
18
- @graph_type = 'turbulence'
19
- @scm_name = 'Git'
20
- @output = STDOUT
18
+ @directory = Dir.pwd
19
+ @graph_type = 'turbulence'
20
+ @scm_name = 'Git'
21
+ @output = STDOUT
22
+ @output_dir = nil
23
+ @no_open = false
24
+ @json_output = false
21
25
  end
22
26
 
23
27
  # TODO: drop attr accessor and ivar once it stops getting set via Churn
@@ -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 = Turbulence::Calculators::Churn,
8
- y_metric = Turbulence::Calculators::Complexity)
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
@@ -49,11 +49,17 @@ class Turbulence
49
49
  def file_metrics_for_directory(metrics_hash)
50
50
  metrics_hash.map do |filename, metrics|
51
51
  { :filename => filename,
52
- :x => metrics[x_metric],
53
- :y => metrics[y_metric]}
52
+ :x => ensure_minimum(metrics[x_metric]),
53
+ :y => ensure_minimum(metrics[y_metric])}
54
54
  end
55
55
  end
56
56
 
57
+ # Offset zero values slightly to avoid Highcharts tooltip detection
58
+ # issues at the chart edge (bug in Highcharts 2.x)
59
+ def ensure_minimum(value)
60
+ value.zero? ? 1 : value
61
+ end
62
+
57
63
  def generate_results(metrics, ci)
58
64
  File.open("cc.js", "w") do |f|
59
65
  ci.copy_templates_into(Dir.pwd)
@@ -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 = Turbulence::Calculators::Churn,
8
- y_metric = Turbulence::Calculators::Complexity)
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
@@ -21,16 +21,20 @@ class Turbulence
21
21
  def build_js
22
22
  clean_metrics_from_missing_data
23
23
 
24
- output = "var treemap_data = [['File', 'Parent', 'Churn (size)', 'Complexity (color)'],\n"
25
- output << "['Root', null, 0, 0],\n"
26
-
27
- @metrics_hash.each do |file|
28
- output << "['#{file[0]}', 'Root', #{file[1][@x_metric]}, #{file[1][@y_metric]}],\n"
24
+ # Build Highcharts treemap data format
25
+ data = @metrics_hash.map do |filename, metrics|
26
+ churn = metrics[@x_metric] || 0
27
+ complexity = metrics[@y_metric] || 0
28
+ # Ensure minimum value of 1 for churn to avoid zero-size boxes
29
+ churn = 1 if churn.zero?
30
+ {
31
+ name: filename,
32
+ value: churn,
33
+ colorValue: complexity
34
+ }
29
35
  end
30
36
 
31
- output << "];"
32
-
33
- output
37
+ "var treemap_data = #{data.to_json};"
34
38
  end
35
39
 
36
40
  private
@@ -8,7 +8,7 @@ class Turbulence
8
8
 
9
9
  def is_repo?(directory)
10
10
  FileUtils.cd(directory) {
11
- return !(`git status 2>&1` =~ /Not a git repository/)
11
+ return !(`git status 2>&1` =~ /not a git repository/i)
12
12
  }
13
13
  end
14
14
  end
@@ -1,3 +1,3 @@
1
1
  class Turbulence
2
- VERSION = "1.2.4"
2
+ VERSION = "1.4.0"
3
3
  end
data/lib/turbulence.rb CHANGED
@@ -55,7 +55,7 @@ class Turbulence
55
55
 
56
56
  calculator.for_these_files(files_of_interest) do |filename, score|
57
57
  report "."
58
- set_file_metric(filename, calculator.class, score)
58
+ set_file_metric(filename, calculator.type, score)
59
59
  end
60
60
 
61
61
  report "\n"
@@ -5,150 +5,138 @@ describe Turbulence::Calculators::Churn do
5
5
  let(:config) { Turbulence::Configuration.new }
6
6
 
7
7
  before do
8
- calculator.stub(:scm_log_command) { "" }
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.stub(:changes_by_ruby_file) {
15
- [
16
- ["lib/corey.rb", 5],
17
- ["lib/chad.rb", 10]
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.should =~ [["lib/corey.rb", 5],
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.stub(:changes_by_ruby_file) {
31
- [
32
- ["lib/corey.rb", 5],
33
- ["lib/chad.rb", 10]
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.should =~ [["lib/corey.rb", 5]]
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.stub(:scm_log_command) do
47
- "\n\n\n\n10\t6\tlib/turbulence.rb\n\n\n\n17\t2\tlib/eddies.rb\n"
48
- end
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.should =~ [
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.stub(:scm_log_file_lines) {
60
- [
61
- "10\t6\tlib/turbulence.rb",
62
- "17\t2\tlib/eddies.rb"
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.should =~ [["lib/turbulence.rb", 16], ["lib/eddies.rb", 19]]
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.stub(:ruby_files_changed_in_scm) {
75
- [
76
- ['lib/eddies.rb', 4],
77
- ['lib/turbulence.rb', 5],
78
- ['lib/turbulence.rb', 16],
79
- ['lib/eddies.rb', 2],
80
- ['lib/turbulence.rb', 7],
81
- ['lib/eddies.rb', 19],
82
- ['lib/eddies.rb', 28]
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.should =~ [ ['lib/eddies.rb', 25], ['lib/turbulence.rb', 21]]
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.stub(:ruby_files_changed_in_scm) {
94
- [
95
- ['lib/eddies.rb', 4],
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.should =~ [ ['lib/eddies.rb', 0] ]
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.should =~ [ ['lib/eddies.rb', 8], ['lib/turbulence.rb', 10]]
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).should == 8
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" do
115
- calculator.calculate_mean_of_churn(8,1).should == 8
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).should == 8
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.stub(:scm_log_command) do
116
+ allow(calculator).to receive(:scm_log_command).and_return(
129
117
  "\n\n\n\n10\t6\tlib/turbulence.rb\n" +
130
- "\n\n\n\n11\t7\tlib/turbulence.rb\n"
131
- end
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.should =~ [["lib/turbulence.rb", 16]]
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.stub(:scm_log_command) do
130
+ allow(calculator).to receive(:scm_log_command).and_return(
143
131
  "\n\n\n\n10\t6\tlib/turbulence.rb\n"
144
- end
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.should =~ [["lib/turbulence.rb", 0]]
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.stub(:score_for_file) { |filename|
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.should =~ [["lib/corey.rb", 12],
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.should == 'path/to/compute'
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.should == 'Perforce'
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.should eq('f3e1d7a6..830b9d3d9f')
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.should be_true
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.should == 'turbulence'
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.should == 'treemap'
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.dirname(template_file).should == Turbulence::CommandLineInterface::TURBULENCE_TEMPLATE_PATH
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,68 @@ describe Turbulence::CommandLineInterface do
16
18
  end
17
19
  it "bundles the files" do
18
20
  cli.generate_bundle
19
- Dir.glob('turbulence/*').sort.should eq(["turbulence/cc.js",
20
- "turbulence/highcharts.js",
21
- "turbulence/jquery.min.js",
22
- "turbulence/treemap.html",
23
- "turbulence/turbulence.html"])
21
+ expect(Dir.glob('turbulence/*').sort).to eq(["turbulence/cc.js",
22
+ "turbulence/highcharts-heatmap.js",
23
+ "turbulence/highcharts-treemap.js",
24
+ "turbulence/highcharts.js",
25
+ "turbulence/jquery.min.js",
26
+ "turbulence/treemap.html",
27
+ "turbulence/turbulence.html"])
24
28
  end
25
29
 
26
30
  it "passes along exclusion pattern" do
27
31
  cli = Turbulence::CommandLineInterface.new(%w(--exclude turbulence), :output => nil)
28
32
  cli.generate_bundle
29
33
  lines = File.new('turbulence/cc.js').readlines
30
- lines.any? { |l| l =~ /turbulence\.rb/ }.should be_false
34
+ expect(lines.any? { |l| l =~ /turbulence\.rb/ }).to be false
35
+ end
36
+
37
+ it "outputs to custom directory when --output is specified" do
38
+ custom_dir = 'tmp/custom_output'
39
+ FileUtils.remove_dir(custom_dir, true)
40
+ cli = Turbulence::CommandLineInterface.new(['--output', custom_dir], :output => nil)
41
+ cli.generate_bundle
42
+ expect(Dir.glob("#{custom_dir}/*").sort).to eq(["#{custom_dir}/cc.js",
43
+ "#{custom_dir}/highcharts-heatmap.js",
44
+ "#{custom_dir}/highcharts-treemap.js",
45
+ "#{custom_dir}/highcharts.js",
46
+ "#{custom_dir}/jquery.min.js",
47
+ "#{custom_dir}/treemap.html",
48
+ "#{custom_dir}/turbulence.html"])
49
+ FileUtils.remove_dir(custom_dir, true)
50
+ end
51
+ end
52
+
53
+ describe "#generate_json" do
54
+ before do
55
+ Turbulence.instance_variable_set(:@config, nil)
56
+ end
57
+
58
+ it "outputs valid JSON to stdout" do
59
+ cli = Turbulence::CommandLineInterface.new(%w(--json), :output => nil)
60
+ expect { cli.generate_bundle }.to output(/\{.*"complexity".*"churn".*\}/m).to_stdout
61
+ end
62
+
63
+ it "suppresses progress output" do
64
+ cli = Turbulence::CommandLineInterface.new(%w(--json), :output => nil)
65
+ expect { cli.generate_bundle }.not_to output(/calculating metric/).to_stdout
66
+ end
67
+ end
68
+
69
+ describe "#output_path" do
70
+ before do
71
+ # Reset the singleton config between tests
72
+ Turbulence.instance_variable_set(:@config, nil)
73
+ end
74
+
75
+ it "defaults to ./turbulence when output_dir is not set" do
76
+ cli = Turbulence::CommandLineInterface.new(%w(.), :output => nil)
77
+ expect(cli.output_path).to eq(File.join(Dir.pwd, "turbulence"))
78
+ end
79
+
80
+ it "returns the custom output_dir when set" do
81
+ cli = Turbulence::CommandLineInterface.new(%w(--output custom/path), :output => nil)
82
+ expect(cli.output_path).to eq('custom/path')
31
83
  end
32
84
  end
33
85
  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) { should eq(STDOUT) }
7
- its(:directory) { should eq(Dir.pwd) }
8
- its(:graph_type) { should eq('turbulence') }
9
- its(:scm_name) { should eq('Git') }
10
- its(:scm) { should eq(Turbulence::Scm::Git) }
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