reek 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/class_checker'
4
+
5
+ include Reek
6
+
7
+ describe ClassChecker do
8
+
9
+ before(:each) do
10
+ @rpt = []
11
+ @cchk = ClassChecker.new(@rpt)
12
+ end
13
+
14
+ it 'should report Long Parameter List' do
15
+ @cchk.check_source('class Inner; def simple(arga, argb, argc, argd) f(3);true end end')
16
+ @rpt.length.should == 1
17
+ @rpt[0].report.should match(/Inner#simple/)
18
+ end
19
+
20
+ it 'should report two different methods' do
21
+ src = <<EOEX
22
+ class Fred
23
+ def simple(arga, argb, argc, argd) f(3);true end
24
+ def simply(arga, argb, argc, argd) f(3);false end
25
+ end
26
+ EOEX
27
+ @cchk.check_source(src)
28
+ @rpt.length.should == 2
29
+ @rpt[0].report.should match(/Fred#simple/)
30
+ @rpt[1].report.should match(/Fred#simply/)
31
+ end
32
+
33
+ it 'should report many different methods' do
34
+ src = <<EOEX
35
+ class Fred
36
+ def textile_bq(tag, atts, cite, content) f(3);end
37
+ def textile_p(tag, atts, cite, content) f(3);end
38
+ def textile_fn_(tag, num, atts, cite, content) f(3);end
39
+ def textile_popup_help(name, windowW, windowH) f(3);end
40
+ end
41
+ EOEX
42
+ @cchk.check_source(src)
43
+ @rpt.length.should == 3
44
+ @rpt[0].report.should match(/Fred#textile_bq/)
45
+ @rpt[1].report.should match(/Fred#textile_p/)
46
+ end
47
+
48
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/method_checker'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe MethodChecker, "(Feature Envy)" do
9
+
10
+ before(:each) do
11
+ @rpt = Report.new
12
+ @cchk = MethodChecker.new(@rpt, 'Thing')
13
+ end
14
+
15
+ it 'should not report local method call' do
16
+ @cchk.check_source('def simple(arga) f(17) end')
17
+ @rpt.should be_empty
18
+ end
19
+
20
+ it 'should report message chain' do
21
+ @cchk.check_source('def parse(arga) arga.b.c end')
22
+ @rpt.length.should == 2
23
+ end
24
+
25
+ it 'should report simple parameter call' do
26
+ @cchk.check_source('def simple(arga) arga[3] end')
27
+ @rpt.length.should == 2
28
+ @rpt[0].should == UtilityFunction.new(@cchk)
29
+ @rpt[1].should == FeatureEnvy.new(@cchk, ':arga')
30
+ end
31
+
32
+ it 'should report highest affinity' do
33
+ @cchk.check_source('def simple(arga) slim = ""; s1 = ""; s1.to_s; @m = 34; end')
34
+ @rpt.length.should == 1
35
+ @rpt[0].should == FeatureEnvy.new(@cchk, ':s1')
36
+ end
37
+
38
+ it 'should report multiple affinities' do
39
+ @cchk.check_source('def simple(arga) s1 = ""; s1.to_s; s2 = ""; s2.to_s; @m = 34; end')
40
+ @rpt.length.should == 1
41
+ @rpt[0].should == FeatureEnvy.new(@cchk, ':s1 or :s2')
42
+ end
43
+
44
+ it 'should not reference global variables' do
45
+ @cchk.check_source('def simple(arga) @s = ""; $s2.to_a; $s2.to_s; end')
46
+ @rpt.length.should == 0
47
+ end
48
+
49
+ it 'should not report class methods' do
50
+ @cchk.check_source('def simple() self.class.new.flatten_merge(self) end')
51
+ @rpt.should be_empty
52
+ end
53
+ end
54
+
55
+ describe FeatureEnvy, '#report' do
56
+ it 'should report the envious host' do
57
+ mchk = MethodChecker.new([], 'Class')
58
+ smell = FeatureEnvy.new(mchk, [:lvar, :fred])
59
+ smell.report.should match(/fred/)
60
+ smell.report.should_not match(/:fred/)
61
+ end
62
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/class_checker'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe ClassChecker, "(Large Class)" do
9
+
10
+ class BigOne
11
+ 26.times do |i|
12
+ define_method "m#{i}".to_sym do
13
+ @melting
14
+ end
15
+ end
16
+ end
17
+
18
+ before(:each) do
19
+ @rpt = Report.new
20
+ @cchk = ClassChecker.new(@rpt)
21
+ end
22
+
23
+ it 'should not report short class' do
24
+ class ShortClass
25
+ def m1() @m1; end
26
+ def m2() @m2; end
27
+ def m3() @m3; end
28
+ def m4() @m4; end
29
+ def m5() @m5; end
30
+ def m6() @m6; end
31
+ end
32
+ @cchk.check_object(ShortClass)
33
+ @rpt.should be_empty
34
+ end
35
+
36
+ it 'should report large class' do
37
+ @cchk.check_object(BigOne)
38
+ @rpt.length.should == 1
39
+ end
40
+
41
+ it 'should report class name' do
42
+ @cchk.check_object(BigOne)
43
+ @rpt[0].report.should match(/BigOne/)
44
+ end
45
+ end
@@ -0,0 +1,201 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/method_checker'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe MethodChecker, "(Long Parameter List)" do
9
+
10
+ before(:each) do
11
+ @rpt = Report.new
12
+ @cchk = MethodChecker.new(@rpt, 'Thing')
13
+ end
14
+
15
+ describe 'with no method definitions' do
16
+ it 'should report no problems for empty source code' do
17
+ @cchk.check_source('')
18
+ @rpt.should be_empty
19
+ end
20
+
21
+ it 'should report no problems for empty class' do
22
+ @cchk.check_source('class Fred; end')
23
+ @rpt.should be_empty
24
+ end
25
+ end
26
+
27
+ describe 'for methods with few parameters' do
28
+ it 'should report nothing for no parameters' do
29
+ @cchk.check_source('def simple; f(3);true; end')
30
+ @rpt.should be_empty
31
+ end
32
+
33
+ it 'should report nothing for 1 parameter' do
34
+ @cchk.check_source('def simple(yep) f(3);true end')
35
+ @rpt.should be_empty
36
+ end
37
+
38
+ it 'should report nothing for 2 parameters' do
39
+ @cchk.check_source('def simple(yep,zero) f(3);true end')
40
+ @rpt.should be_empty
41
+ end
42
+
43
+ it 'should not count an optional block' do
44
+ @cchk.check_source('def simple(alpha, yep, zero, &opt) f(3);true end')
45
+ @rpt.should be_empty
46
+ end
47
+
48
+ it 'should not report inner block with too many parameters' do
49
+ @cchk.check_source('def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end')
50
+ @rpt.should be_empty
51
+ end
52
+
53
+ describe 'and default values' do
54
+ it 'should report nothing for 1 parameter' do
55
+ @cchk.check_source('def simple(zero=nil) f(3);false end')
56
+ @rpt.should be_empty
57
+ end
58
+
59
+ it 'should report nothing for 2 parameters with 1 default' do
60
+ @cchk.check_source('def simple(yep, zero=nil) f(3);false end')
61
+ @rpt.should be_empty
62
+ end
63
+
64
+ it 'should report nothing for 2 defaulted parameters' do
65
+ @cchk.check_source('def simple(yep=4, zero=nil) f(3);false end')
66
+ @rpt.should be_empty
67
+ end
68
+ end
69
+ end
70
+
71
+ describe 'for methods with too many parameters' do
72
+ it 'should report 4 parameters' do
73
+ @cchk.check_source('def simple(arga, argb, argc, argd) f(3);true end')
74
+ @rpt.length.should == 1
75
+ @rpt[0].should == LongParameterList.new(@cchk)
76
+ end
77
+
78
+ it 'should report 8 parameters' do
79
+ @cchk.check_source('def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end')
80
+ @rpt.length.should == 1
81
+ @rpt[0].should == LongParameterList.new(@cchk)
82
+ end
83
+
84
+ describe 'and default values' do
85
+ it 'should report 3 with 1 defaulted' do
86
+ @cchk.check_source('def simple(polly, queue, yep, zero=nil) f(3);false end')
87
+ @rpt.length.should == 1
88
+ @rpt[0].should == LongParameterList.new(@cchk)
89
+ end
90
+
91
+ it 'should report with 3 defaulted' do
92
+ @cchk.check_source('def simple(aarg, polly=2, yep=true, zero=nil) f(3);false end')
93
+ @rpt.length.should == 1
94
+ @rpt[0].should == LongParameterList.new(@cchk)
95
+ end
96
+ end
97
+
98
+ describe 'in a class' do
99
+ class InnerTest
100
+ def xyzero(arga,argb) f(3);true end
101
+ def abc(argx,yep,zero,argm) f(3);false end
102
+ end
103
+
104
+ it 'should only report long param list' do
105
+ @cchk.check_object(InnerTest)
106
+ @rpt.length.should == 1
107
+ @rpt[0].should == LongParameterList.new(@cchk)
108
+ end
109
+ end
110
+ end
111
+
112
+ describe 'yield' do
113
+ it 'should not report yield with few parameters' do
114
+ @cchk.check_source('def simple(arga, argb, &blk) f(3);yield a,b; end')
115
+ @rpt.should be_empty
116
+ end
117
+
118
+ it 'should report yield with many parameters' do
119
+ @cchk.check_source('def simple(arga, argb, &blk) f(3);yield a,b,a,b; end')
120
+ @rpt.length.should == 1
121
+ @rpt[0].should == LongYieldList.new(@cchk)
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ describe MethodChecker, 'when given the class name' do
129
+
130
+ before(:each) do
131
+ @rpt = Report.new
132
+ @cchk = MethodChecker.new(@rpt, 'classname')
133
+ end
134
+
135
+ it 'should report the class name' do
136
+ @cchk.check_source('def simple(arga, argb, argc, argd) f(3);true end')
137
+ @rpt.length.should == 1
138
+ @rpt[0].should == LongParameterList.new(@cchk)
139
+ @rpt[0].report.should match(/classname#simple/)
140
+ end
141
+ end
142
+
143
+ describe LongParameterList, '#report' do
144
+ it 'should report the method name and num params' do
145
+ mchk = MethodChecker.new([], 'Class')
146
+ smell = LongParameterList.new(mchk)
147
+ smell.report.should match(/Class/)
148
+ end
149
+
150
+ end
151
+
152
+ describe MethodChecker, "(Long Method)" do
153
+
154
+ before(:each) do
155
+ @rpt = Report.new
156
+ @cchk = MethodChecker.new(@rpt, 'Thing')
157
+ end
158
+
159
+ it 'should not report short methods' do
160
+ @cchk.check_source('def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end')
161
+ @rpt.should be_empty
162
+ end
163
+
164
+ it 'should report long methods' do
165
+ @cchk.check_source('def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end')
166
+ @rpt.length.should == 1
167
+ @rpt[0].should == LongMethod.new(@cchk)
168
+ end
169
+
170
+ it 'should report long inner block' do
171
+ src = <<EOS
172
+ def long(arga)
173
+ f(3)
174
+ 37.each do |xyzero|
175
+ xyzero = 1
176
+ xyzero = 2
177
+ xyzero = 3
178
+ xyzero = 4
179
+ xyzero = 5
180
+ xyzero = 6
181
+ end
182
+ end
183
+ EOS
184
+ @cchk.check_source(src)
185
+ @rpt.length.should == 1
186
+ @rpt[0].report.should match(/block/)
187
+ end
188
+ end
189
+
190
+ describe MethodChecker, 'when given a C extension' do
191
+
192
+ before(:each) do
193
+ @rpt = Report.new
194
+ @cchk = MethodChecker.new(@rpt, 'Thing')
195
+ end
196
+
197
+ it 'should ignore :cfunc' do
198
+ @cchk.check_object(Enumerable)
199
+ end
200
+ end
201
+
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/method_checker'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe Report, "to_s" do
9
+
10
+ before(:each) do
11
+ rpt = Report.new
12
+ chk = MethodChecker.new(rpt, 'Thing')
13
+ chk.check_source('def simple(arga) arga[3] end')
14
+ @report = rpt.to_s.split("\n")
15
+ end
16
+
17
+ it 'should place each detailed report on a separate line' do
18
+ @report.length.should == 2
19
+ end
20
+
21
+ it 'should mention every smell name' do
22
+ @report[0].should match(/[Utility Function]/)
23
+ @report[1].should match(/[Feature Envy]/)
24
+ end
25
+ end
26
+
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/smells'
4
+
5
+ include Reek
6
+
7
+ describe Smell, "camel case converter" do
8
+ it "should convert camel case name" do
9
+ Smell.convert_camel_case('LongParameterList').should == 'Long Parameter List'
10
+ end
11
+
12
+ it "should display correct name in report" do
13
+ mchk = MethodChecker.new([], 'Class')
14
+ smell = FeatureEnvy.new(mchk, [:lvar, :fred])
15
+ smell.report.should match(/[#{smell.name}]/)
16
+ end
17
+ end
@@ -0,0 +1,106 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/method_checker'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe MethodChecker, "uncommunicative method name" do
9
+
10
+ before(:each) do
11
+ @rpt = Report.new
12
+ @cchk = MethodChecker.new(@rpt, 'Thing')
13
+ end
14
+
15
+ it 'should not report one-word method name' do
16
+ @cchk.check_source('def help(fred) basics(17) end')
17
+ @rpt.should be_empty
18
+ end
19
+
20
+ it 'should report one-letter method name' do
21
+ @cchk.check_source('def x(fred) basics(17) end')
22
+ @rpt.length.should == 1
23
+ @rpt[0].detailed_report.should match(/x/)
24
+ @rpt[0].detailed_report.should match(/method name/)
25
+ end
26
+ end
27
+
28
+ describe MethodChecker, "uncommunicative field name" do
29
+
30
+ before(:each) do
31
+ @rpt = Report.new
32
+ @cchk = MethodChecker.new(@rpt, 'Thing')
33
+ end
34
+
35
+ it 'should not report one-word field name' do
36
+ @cchk.check_source('def help(fred) @simple end')
37
+ @rpt.should be_empty
38
+ end
39
+
40
+ it 'should report one-letter fieldname' do
41
+ @cchk.check_source('def simple(fred) @x end')
42
+ @rpt.length.should == 1
43
+ @rpt[0].detailed_report.should match(/@x/)
44
+ @rpt[0].detailed_report.should match(/field name/)
45
+ end
46
+ end
47
+
48
+ describe MethodChecker, "uncommunicative local variable name" do
49
+
50
+ before(:each) do
51
+ @rpt = Report.new
52
+ @cchk = MethodChecker.new(@rpt, 'Thing')
53
+ end
54
+
55
+ it 'should not report one-word variable name' do
56
+ @cchk.check_source('def help(fred) simple = jim(45) end')
57
+ @rpt.should be_empty
58
+ end
59
+
60
+ it 'should report one-letter variable name' do
61
+ @cchk.check_source('def simple(fred) x = jim(45) end')
62
+ @rpt.length.should == 1
63
+ @rpt[0].detailed_report.should match(/x/)
64
+ @rpt[0].detailed_report.should match(/local variable name/)
65
+ end
66
+
67
+ it 'should report variable name only once' do
68
+ @cchk.check_source('def simple(fred) x = jim(45); x = y end')
69
+ @rpt.length.should == 1
70
+ end
71
+ end
72
+
73
+ describe MethodChecker, "uncommunicative parameter name" do
74
+
75
+ before(:each) do
76
+ @rpt = Report.new
77
+ @cchk = MethodChecker.new(@rpt, 'Thing')
78
+ end
79
+
80
+ it 'should recognise short parameter name' do
81
+ @cchk.check_source('def help(x) basics(17) end')
82
+ @rpt.length.should == 1
83
+ @rpt[0].name.should == 'Uncommunicative Name'
84
+ end
85
+
86
+ it 'should not recognise *' do
87
+ @cchk.check_source('def help(xray, *) basics(17) end')
88
+ @rpt.length.should == 0
89
+ end
90
+
91
+ it "should report parameter's name" do
92
+ @cchk.check_source('def help(x) basics(17) end')
93
+ @rpt[0].detailed_report.should match(/x/)
94
+ @rpt[0].detailed_report.should match(/parameter name/)
95
+ end
96
+ end
97
+
98
+ describe UncommunicativeName, '#report' do
99
+ it 'should report the bad symbol name' do
100
+ mchk = MethodChecker.new([], 'Class')
101
+ smell = UncommunicativeName.new(mchk, 'thing')
102
+ smell.recognise?(:x).should == true
103
+ smell.report.should match(/x/)
104
+ smell.report.should_not match(/:x/)
105
+ end
106
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/method_checker'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe MethodChecker, "(Utility Function)" do
9
+
10
+ before(:each) do
11
+ @rpt = Report.new
12
+ @cchk = MethodChecker.new(@rpt, 'Thing')
13
+ end
14
+
15
+ it 'should not report instance variable reference' do
16
+ @cchk.check_source('def simple(arga) @yellow end')
17
+ @rpt.should be_empty
18
+ end
19
+
20
+ it 'should not report vcall' do
21
+ @cchk.check_source('def simple(arga) y end')
22
+ @rpt.should be_empty
23
+ end
24
+
25
+ it 'should not report attrset' do
26
+ class Fred
27
+ attr_writer :xyz
28
+ end
29
+ @cchk.check_object(Fred)
30
+ @rpt.should be_empty
31
+ end
32
+ end
data/spec/reek_spec.rb ADDED
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ require 'reek'
4
+
5
+ describe Reek, "#analyse" do
6
+
7
+ class ReekAnalyseInner1
8
+ def short1(str) f(3);true end
9
+ def long(arga, argb, argc, argd=4) f(3);27 end
10
+ end
11
+
12
+ class ReekAnalyseInner2
13
+ def long(arga, argb, argc, argd) f(3);27 end
14
+ def short2(str) f(3);true end
15
+ end
16
+
17
+ it 'should report Long Parameter List' do
18
+ rpt = Reek.analyse(ReekAnalyseInner1)
19
+ rpt.length.should == 1
20
+ end
21
+
22
+ it 'should report all Long Parameter Lists' do
23
+ rpt = Reek.analyse(ReekAnalyseInner1, ReekAnalyseInner2)
24
+ rpt.length.should == 2
25
+ end
26
+
27
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,9 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift File.dirname(__FILE__) + '/../lib'
data/tasks/rspec.rake ADDED
@@ -0,0 +1,40 @@
1
+ require 'rake/clean'
2
+
3
+ begin
4
+ require 'spec'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'spec'
8
+ end
9
+ begin
10
+ require 'spec/rake/spectask'
11
+ require 'spec/rake/verify_rcov'
12
+ rescue LoadError
13
+ puts <<-EOS
14
+ To use rspec for testing you must install rspec gem:
15
+ gem install rspec
16
+ EOS
17
+ exit(0)
18
+ end
19
+
20
+ REPORT_DIR = 'spec/output/coverage'
21
+ CLEAN.include(REPORT_DIR)
22
+
23
+ desc 'runs the specs in colour'
24
+ Spec::Rake::SpecTask.new(:spec_colour) do |t|
25
+ t.spec_opts = ['--options', "spec/spec.opts"]
26
+ t.spec_files = FileList['spec/**/*_spec.rb']
27
+ end
28
+
29
+ Spec::Rake::SpecTask.new(:spec_rcov) do |t|
30
+ t.spec_files = FileList['spec/**/*.rb']
31
+ t.rcov = true
32
+ t.rcov_dir = REPORT_DIR
33
+ t.rcov_opts = ['--exclude', 'spec,\.autotest']
34
+ end
35
+
36
+ "runs the specs and reports coverage in #{REPORT_DIR}"
37
+ RCov::VerifyTask.new(:spec => :spec_rcov) do |t|
38
+ t.index_html = "#{REPORT_DIR}/index.html"
39
+ t.threshold = 100
40
+ end