reek 0.0.1

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.
@@ -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