devtools 0.1.2 → 0.1.3

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 (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