devtools 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/Gemfile +0 -2
  4. data/README.md +2 -2
  5. data/circle.yml +1 -1
  6. data/config/devtools.yml +2 -0
  7. data/config/flay.yml +2 -2
  8. data/config/flog.yml +1 -1
  9. data/config/mutant.yml +2 -0
  10. data/config/reek.yml +7 -12
  11. data/devtools.gemspec +20 -18
  12. data/lib/devtools.rb +34 -83
  13. data/lib/devtools/config.rb +76 -55
  14. data/lib/devtools/flay.rb +94 -0
  15. data/lib/devtools/project.rb +28 -105
  16. data/lib/devtools/project/initializer.rb +2 -12
  17. data/lib/devtools/project/initializer/rake.rb +9 -7
  18. data/lib/devtools/project/initializer/rspec.rb +28 -55
  19. data/lib/devtools/rake/flay.rb +126 -0
  20. data/lib/devtools/spec_helper.rb +1 -3
  21. data/shared/spec/shared/abstract_type_behavior.rb +0 -2
  22. data/shared/spec/shared/command_method_behavior.rb +0 -2
  23. data/shared/spec/shared/each_method_behaviour.rb +0 -2
  24. data/shared/spec/shared/hash_method_behavior.rb +0 -2
  25. data/shared/spec/shared/idempotent_method_behavior.rb +0 -2
  26. data/shared/spec/support/ice_nine_config.rb +0 -2
  27. data/spec/integration/devtools/rake/flay/verify_spec.rb +164 -0
  28. data/spec/spec_helper.rb +2 -8
  29. data/spec/unit/devtools/config/yardstick_spec.rb +17 -0
  30. data/spec/unit/devtools/config_spec.rb +78 -0
  31. data/spec/unit/devtools/flay/file_list/call_spec.rb +19 -0
  32. data/spec/unit/devtools/flay/scale/flay_report_spec.rb +17 -0
  33. data/spec/unit/devtools/flay/scale/measure_spec.rb +43 -0
  34. data/spec/unit/devtools/project/initializer/rake_spec.rb +21 -0
  35. data/spec/unit/devtools/project/initializer/rspec_spec.rb +52 -0
  36. data/spec/unit/devtools/project_spec.rb +34 -0
  37. data/spec/unit/devtools_spec.rb +14 -0
  38. data/tasks/metrics/ci.rake +1 -3
  39. data/tasks/metrics/coverage.rake +0 -2
  40. data/tasks/metrics/flay.rake +6 -33
  41. data/tasks/metrics/flog.rake +0 -2
  42. data/tasks/metrics/mutant.rake +31 -39
  43. data/tasks/metrics/reek.rake +0 -2
  44. data/tasks/metrics/rubocop.rake +0 -2
  45. data/tasks/metrics/yardstick.rake +0 -14
  46. data/tasks/spec.rake +0 -2
  47. data/tasks/yard.rake +0 -2
  48. metadata +96 -31
  49. data/.travis.yml +0 -15
  50. data/TODO +0 -0
  51. data/bin/devtools +0 -18
  52. data/default/config/devtools.yml +0 -2
  53. data/default/config/flay.yml +0 -3
  54. data/default/config/flog.yml +0 -2
  55. data/default/config/mutant.yml +0 -3
  56. data/default/config/reek.yml +0 -103
  57. data/default/config/rubocop.yml +0 -91
  58. data/default/config/yardstick.yml +0 -2
  59. data/lib/devtools/platform.rb +0 -118
  60. data/lib/devtools/site.rb +0 -41
  61. data/lib/devtools/site/initializer.rb +0 -57
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require 'devtools'
4
2
 
5
- Devtools.init_spec_helper
3
+ Devtools::PROJECT.init_rspec
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  shared_examples_for 'an abstract type' do
4
2
  context 'called on a subclass' do
5
3
  let(:object) { Class.new(described_class) }
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  shared_examples_for 'a command method' do
4
2
  it 'returns self' do
5
3
  should equal(object)
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  shared_examples_for 'an #each method' do
4
2
  it_should_behave_like 'a command method'
5
3
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  shared_examples_for 'a hash method' do
4
2
  it_should_behave_like 'an idempotent method'
5
3
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  shared_examples_for 'an idempotent method' do
4
2
  it 'is idempotent' do
5
3
  first = subject
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  if defined?(IceNine)
4
2
  module IceNine
5
3
 
@@ -0,0 +1,164 @@
1
+ describe Devtools::Rake::Flay, '#verify' do
2
+ let(:tempfile) { Tempfile.new(%w[file .rb], Dir.mktmpdir) }
3
+ let(:file) { Pathname(tempfile.path) }
4
+ let(:directories) { [file.dirname.to_s] }
5
+
6
+ let(:ruby) do
7
+ <<-ERUBY
8
+ def foo; end
9
+ def bar; end
10
+ ERUBY
11
+ end
12
+
13
+ around(:each) do |example|
14
+ begin
15
+ # silence other flay output
16
+ $stdout = $stderr = StringIO.new
17
+
18
+ tempfile.write(ruby)
19
+ tempfile.close
20
+
21
+ example.run
22
+ ensure
23
+ $stdout = STDOUT
24
+ $stderr = STDERR
25
+
26
+ file.unlink
27
+ end
28
+ end
29
+
30
+ context 'reporting' do
31
+ let(:options) do
32
+ { threshold: 3, total_score: 3, lib_dirs: directories, excludes: [] }.freeze
33
+ end
34
+
35
+ let(:instance) { described_class.new(options) }
36
+
37
+ it 'measures total mass' do
38
+ allow(::Flay).to receive(:new).and_call_original
39
+
40
+ instance.verify
41
+
42
+ expect(::Flay).to have_received(:new).with(hash_including(mass: 0))
43
+ end
44
+
45
+ it 'does not report the files it is processing' do
46
+ expect { instance.verify }.to_not output(/Processing #{file}/).to_stderr
47
+ end
48
+ end
49
+
50
+ context 'when theshold is too low' do
51
+ let(:instance) do
52
+ described_class.new(threshold: 0, total_score: 0, lib_dirs: directories, excludes: [])
53
+ end
54
+
55
+ specify do
56
+ expect { instance.verify }
57
+ .to raise_error(SystemExit)
58
+ .with_message('Flay total is now 3, but expected 0')
59
+ end
60
+ end
61
+
62
+ context 'when threshold is too high' do
63
+ let(:instance) do
64
+ described_class.new(threshold: 1000, total_score: 0, lib_dirs: directories, excludes: [])
65
+ end
66
+
67
+ specify do
68
+ expect { instance.verify }
69
+ .to raise_error(SystemExit)
70
+ .with_message('Adjust flay threshold down to 3')
71
+ end
72
+ end
73
+
74
+ context 'when total is too high' do
75
+ let(:instance) do
76
+ described_class.new(threshold: 3, total_score: 50, lib_dirs: directories, excludes: [])
77
+ end
78
+
79
+ specify do
80
+ expect { instance.verify }
81
+ .to raise_error(SystemExit)
82
+ .with_message('Flay total is now 3, but expected 50')
83
+ end
84
+ end
85
+
86
+ context 'when duplicate mass is greater than 0' do
87
+ let(:ruby) do
88
+ <<-ERUBY
89
+ def foo
90
+ :hi if baz?
91
+ end
92
+
93
+ def bar
94
+ :hi if baz?
95
+ end
96
+ ERUBY
97
+ end
98
+
99
+ let(:report) do
100
+ <<-REPORT
101
+ Total score (lower is better) = 10
102
+
103
+ Similar code found in :defn (mass = 10)
104
+ #{file}:1
105
+ #{file}:5
106
+ REPORT
107
+ end
108
+
109
+ let(:instance) do
110
+ described_class.new(threshold: 3, total_score: 5, lib_dirs: directories, excludes: [])
111
+ end
112
+
113
+ specify do
114
+ expect { instance.verify }
115
+ .to raise_error(SystemExit)
116
+ .with_message('1 chunks have a duplicate mass > 3')
117
+ end
118
+
119
+ specify do
120
+ expect { instance.verify }
121
+ .to raise_error(SystemExit)
122
+ .and output(report).to_stdout
123
+ end
124
+ end
125
+
126
+ context 'when multiple duplicate masses' do
127
+ let(:ruby) do
128
+ <<-ERUBY
129
+ def foo; end
130
+ def bar; end
131
+
132
+ class Foo
133
+ def initialize
134
+ @a = 1
135
+ end
136
+ end
137
+ class Bar
138
+ def initialize
139
+ @a = 1
140
+ end
141
+ end
142
+ ERUBY
143
+ end
144
+
145
+ let(:instance) do
146
+ described_class.new(threshold: 5, total_score: 8, lib_dirs: directories, excludes: [])
147
+ end
148
+
149
+ it 'sums masses for total' do
150
+ expect { instance.verify }.to_not raise_error
151
+ end
152
+ end
153
+
154
+ context 'when no duplication masses' do
155
+ let(:ruby) { '' }
156
+ let(:instance) do
157
+ described_class.new(threshold: 0, total_score: 0, lib_dirs: directories, excludes: [])
158
+ end
159
+
160
+ specify do
161
+ expect { instance.verify }.to_not raise_error
162
+ end
163
+ end
164
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,14 +1,10 @@
1
- # encoding: utf-8
2
-
3
1
  require 'devtools/spec_helper'
2
+ require 'tempfile'
3
+ require 'tmpdir'
4
4
 
5
5
  if ENV['COVERAGE'] == 'true'
6
- require 'simplecov'
7
- require 'coveralls'
8
-
9
6
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
10
7
  SimpleCov::Formatter::HTMLFormatter,
11
- Coveralls::SimpleCov::Formatter
12
8
  ]
13
9
 
14
10
  SimpleCov.start do
@@ -22,8 +18,6 @@ if ENV['COVERAGE'] == 'true'
22
18
  end
23
19
  end
24
20
 
25
- require 'devtools'
26
-
27
21
  RSpec.configure do |config|
28
22
  config.expect_with :rspec do |expect_with|
29
23
  expect_with.syntax = :expect
@@ -0,0 +1,17 @@
1
+ RSpec.describe Devtools::Config::Yardstick do
2
+ let(:object) { described_class.new(Devtools.root.join('config')) }
3
+
4
+ describe '#options' do
5
+ subject { object.options }
6
+
7
+ specify do
8
+ should eql(
9
+ 'threshold' => 100,
10
+ 'rules' => nil,
11
+ 'verbose' => nil,
12
+ 'path' => nil,
13
+ 'require_exact_threshold' => nil
14
+ )
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,78 @@
1
+ RSpec.describe Devtools::Config do
2
+
3
+ describe '.attribute' do
4
+ let(:raw) do
5
+ {
6
+ 'a' => 'bar',
7
+ 'c' => []
8
+ }
9
+
10
+ end
11
+
12
+ let(:config_path) { instance_double(Pathname) }
13
+
14
+ let(:class_under_test) do
15
+ expect(config_path).to receive(:file?)
16
+ .and_return(file?)
17
+ expect(config_path).to receive(:frozen?)
18
+ .and_return(true)
19
+ expect(config_path).to receive(:join)
20
+ .with('bar.yml')
21
+ .and_return(config_path)
22
+
23
+ Class.new(described_class) do
24
+ attribute :a, [String]
25
+ attribute :b, [Array], default: []
26
+ attribute :c, [TrueClass, FalseClass]
27
+
28
+ const_set(:FILE, 'bar.yml')
29
+ end
30
+ end
31
+
32
+ subject do
33
+ class_under_test.new(config_path)
34
+ end
35
+
36
+ context 'on present config' do
37
+ let(:class_under_test) do
38
+ # Setup message expectation in a lasy way, not in a before
39
+ # block to make sure the around hook setting timeouts from the
40
+ # code under test is not affected.
41
+ expect(YAML).to receive(:load_file)
42
+ .with(config_path)
43
+ .and_return(raw)
44
+
45
+ expect(IceNine).to receive(:deep_freeze)
46
+ .with(raw)
47
+ .and_return(raw)
48
+
49
+ super()
50
+ end
51
+
52
+ let(:file?) { true }
53
+
54
+ it 'allows to receive existing keys' do
55
+ expect(subject.a).to eql('bar')
56
+ end
57
+
58
+ it 'allows to receive absent keys with defaults' do
59
+ expect(subject.b).to eql([])
60
+ end
61
+
62
+ it 'executes checks when configured' do
63
+ expect { subject.c }.to raise_error(
64
+ Devtools::Config::TypeError,
65
+ 'c: Got instance of Array expected TrueClass,FalseClass'
66
+ )
67
+ end
68
+ end
69
+
70
+ context 'on absent config' do
71
+ let(:file?) { false }
72
+
73
+ it 'defaults to absent keys' do
74
+ expect(subject.b).to eql([])
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,19 @@
1
+ describe Devtools::Flay::FileList, '.call' do
2
+ subject(:output) { described_class.call([tmpdir.to_s], [exclude]) }
3
+
4
+ let(:tmpdir) { Dir.mktmpdir }
5
+ let(:one) { Pathname(tmpdir).join('1.rb') }
6
+ let(:two) { Pathname(tmpdir).join('2.erb') }
7
+ let(:three) { Pathname(tmpdir).join('3.rb') }
8
+ let(:exclude) { Pathname(tmpdir).join('3*').to_s }
9
+
10
+ around(:each) do |example|
11
+ [one, two, three].map(&FileUtils.method(:touch))
12
+
13
+ example.run
14
+
15
+ FileUtils.rm_rf(tmpdir)
16
+ end
17
+
18
+ it { should eql(Set.new([one, two])) }
19
+ end
@@ -0,0 +1,17 @@
1
+ describe Devtools::Flay::Scale, '#flay_report' do
2
+ subject(:instance) { described_class.new(minimum_mass: 0, files: []) }
3
+
4
+ let(:flay) do
5
+ instance_double(::Flay, process: nil, analyze: nil, masses: {})
6
+ end
7
+
8
+ before do
9
+ allow(::Flay).to receive(:new).with(mass: 0).and_return(flay)
10
+ end
11
+
12
+ specify do
13
+ allow(flay).to receive(:report)
14
+ instance.flay_report
15
+ expect(flay).to have_received(:report)
16
+ end
17
+ end
@@ -0,0 +1,43 @@
1
+ describe Devtools::Flay::Scale, '#measure' do
2
+ subject(:measure) { instance.measure }
3
+
4
+ let(:minimum_mass) { 0 }
5
+ let(:files) { [instance_double(File)] }
6
+ let(:flay_masses) { { 0 => 5, 1 => 10 } }
7
+
8
+ let(:instance) do
9
+ described_class.new(minimum_mass: minimum_mass, files: files)
10
+ end
11
+
12
+ let(:flay_hashes) do
13
+ {
14
+ 0 => instance_double(Array, size: 3),
15
+ 1 => instance_double(Array, size: 11)
16
+ }
17
+ end
18
+
19
+ let(:flay) do
20
+ instance_double(
21
+ ::Flay,
22
+ analyze: nil,
23
+ masses: flay_masses,
24
+ hashes: flay_hashes
25
+ )
26
+ end
27
+
28
+ before do
29
+ allow(::Flay).to receive(:new).with(mass: minimum_mass).and_return(flay)
30
+ allow(flay).to receive(:process).with(*files)
31
+ end
32
+
33
+ it { should eql([Rational(5, 3), Rational(10, 11)]) }
34
+
35
+ context 'when minimum mass is not 0' do
36
+ let(:minimum_mass) { 1 }
37
+
38
+ specify do
39
+ measure
40
+ expect(::Flay).to have_received(:new).with(mass: 1)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ describe Devtools::Project::Initializer::Rake do
2
+ describe '.call' do
3
+ subject do
4
+ described_class.call
5
+ end
6
+
7
+ it 'performs expected rake initialization' do
8
+ path_a = instance_double(Pathname)
9
+ path_b = instance_double(Pathname)
10
+
11
+ expect(FileList).to receive(:glob)
12
+ .with(Devtools.root.join('tasks/**/*.rake').to_s)
13
+ .and_return([path_a, path_b])
14
+
15
+ expect(Rake.application).to receive(:add_import).with(path_a)
16
+ expect(Rake.application).to receive(:add_import).with(path_b)
17
+
18
+ expect(subject).to be(described_class)
19
+ end
20
+ end
21
+ end