kevinrutherford-reek 0.3.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/History.txt +92 -0
  2. data/README.txt +6 -0
  3. data/Rakefile +7 -0
  4. data/bin/reek +19 -0
  5. data/lib/reek/block_context.rb +37 -0
  6. data/lib/reek/class_context.rb +73 -0
  7. data/lib/reek/code_context.rb +47 -0
  8. data/lib/reek/code_parser.rb +204 -0
  9. data/lib/reek/exceptions.reek +13 -0
  10. data/lib/reek/if_context.rb +25 -0
  11. data/lib/reek/method_context.rb +85 -0
  12. data/lib/reek/module_context.rb +34 -0
  13. data/lib/reek/name.rb +42 -0
  14. data/lib/reek/object_refs.rb +53 -0
  15. data/lib/reek/options.rb +92 -0
  16. data/lib/reek/rake_task.rb +121 -0
  17. data/lib/reek/report.rb +42 -0
  18. data/lib/reek/sexp_formatter.rb +52 -0
  19. data/lib/reek/singleton_method_context.rb +27 -0
  20. data/lib/reek/smell_warning.rb +49 -0
  21. data/lib/reek/smells/control_couple.rb +61 -0
  22. data/lib/reek/smells/duplication.rb +50 -0
  23. data/lib/reek/smells/feature_envy.rb +58 -0
  24. data/lib/reek/smells/large_class.rb +50 -0
  25. data/lib/reek/smells/long_method.rb +43 -0
  26. data/lib/reek/smells/long_parameter_list.rb +43 -0
  27. data/lib/reek/smells/long_yield_list.rb +18 -0
  28. data/lib/reek/smells/nested_iterators.rb +28 -0
  29. data/lib/reek/smells/smell_detector.rb +66 -0
  30. data/lib/reek/smells/smells.rb +85 -0
  31. data/lib/reek/smells/uncommunicative_name.rb +80 -0
  32. data/lib/reek/smells/utility_function.rb +34 -0
  33. data/lib/reek/source.rb +116 -0
  34. data/lib/reek/spec.rb +130 -0
  35. data/lib/reek/stop_context.rb +62 -0
  36. data/lib/reek/yield_call_context.rb +14 -0
  37. data/lib/reek.rb +8 -0
  38. data/spec/integration/reek_source_spec.rb +20 -0
  39. data/spec/integration/script_spec.rb +55 -0
  40. data/spec/reek/class_context_spec.rb +198 -0
  41. data/spec/reek/code_context_spec.rb +92 -0
  42. data/spec/reek/code_parser_spec.rb +44 -0
  43. data/spec/reek/config_spec.rb +42 -0
  44. data/spec/reek/module_context_spec.rb +38 -0
  45. data/spec/reek/object_refs_spec.rb +129 -0
  46. data/spec/reek/options_spec.rb +13 -0
  47. data/spec/reek/report_spec.rb +48 -0
  48. data/spec/reek/sexp_formatter_spec.rb +31 -0
  49. data/spec/reek/singleton_method_context_spec.rb +17 -0
  50. data/spec/reek/smells/control_couple_spec.rb +23 -0
  51. data/spec/reek/smells/duplication_spec.rb +81 -0
  52. data/spec/reek/smells/feature_envy_spec.rb +129 -0
  53. data/spec/reek/smells/large_class_spec.rb +86 -0
  54. data/spec/reek/smells/long_method_spec.rb +59 -0
  55. data/spec/reek/smells/long_parameter_list_spec.rb +92 -0
  56. data/spec/reek/smells/nested_iterators_spec.rb +33 -0
  57. data/spec/reek/smells/smell_spec.rb +24 -0
  58. data/spec/reek/smells/uncommunicative_name_spec.rb +118 -0
  59. data/spec/reek/smells/utility_function_spec.rb +96 -0
  60. data/spec/samples/inline.rb +704 -0
  61. data/spec/samples/inline_spec.rb +40 -0
  62. data/spec/samples/optparse.rb +1788 -0
  63. data/spec/samples/optparse_spec.rb +100 -0
  64. data/spec/samples/redcloth.rb +1130 -0
  65. data/spec/samples/redcloth_spec.rb +93 -0
  66. data/spec/spec.opts +1 -0
  67. data/spec/spec_helper.rb +15 -0
  68. data/tasks/reek.rake +20 -0
  69. data/tasks/rspec.rake +22 -0
  70. metadata +167 -0
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe 'Reek source code:' do
4
+ Dir['lib/**/*.rb'].each do |path|
5
+ it "reports no smells in #{path}" do
6
+ File.new(path).should_not reek
7
+ end
8
+ end
9
+
10
+ it 'reports no smells via the Dir matcher' do
11
+ Dir['lib/**/*.rb'].should_not reek
12
+ end
13
+ end
14
+
15
+ describe 'RakeTask' do
16
+ it 'should report no duplication' do
17
+ report = `rake reek`.split("\n")
18
+ report.length.should == 1
19
+ end
20
+ end
@@ -0,0 +1,55 @@
1
+ require 'reek'
2
+
3
+ describe 'version number' do
4
+ it 'should report the correct value' do
5
+ actual = `ruby -Ilib bin/reek --version`.split
6
+ $?.exitstatus.should == 0
7
+ actual[0].should == 'reek'
8
+ actual[1].should == Reek::VERSION
9
+ end
10
+ end
11
+
12
+ describe 'exit status', 'when reek is used incorrectly' do
13
+ it 'should return non-zero status on bad option' do
14
+ `ruby -Ilib bin/reek --no-such-option`
15
+ $?.exitstatus.should == 1
16
+ end
17
+
18
+ it 'should complain about missing file' do
19
+ `ruby -Ilib bin/reek nosuchfile.rb`
20
+ $?.exitstatus.should == 1
21
+ end
22
+
23
+ it 'should return non-zero status on missing argument' do
24
+ `ruby -Ilib bin/reek -f 2>/dev/null`
25
+ $?.exitstatus.should == 1
26
+ end
27
+ end
28
+
29
+ describe 'exit status', 'when reek is used correctly' do
30
+ it 'should return non-zero status when smells are reported' do
31
+ `echo "def x() 3; end" | ruby -Ilib bin/reek`
32
+ $?.exitstatus.should == 2
33
+ end
34
+
35
+ it 'should return zero status with no smells' do
36
+ `echo "def simple() @fred = 3 end" | ruby -Ilib bin/reek`
37
+ $?.exitstatus.should == 0
38
+ end
39
+ end
40
+
41
+ describe 'report format', 'with one source' do
42
+ it 'should output nothing with empty source' do
43
+ `echo "" | ruby -Ilib bin/reek`.should be_empty
44
+ end
45
+
46
+ it 'should output nothing when no smells' do
47
+ `echo "def simple() @fred = 3; end" | ruby -Ilib bin/reek`.should be_empty
48
+ end
49
+
50
+ it 'should not adorn the list of warnings' do
51
+ report = `echo "class Turn; def y() @x = 3; end end" | ruby -Ilib bin/reek`
52
+ report.split(/\n/).length.should == 2
53
+ report.should_not match(/\n\n/)
54
+ end
55
+ end
@@ -0,0 +1,198 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/class_context'
4
+ require 'reek/stop_context'
5
+ require 'reek/smells/feature_envy'
6
+
7
+ include Reek
8
+ include Reek::Smells
9
+
10
+ describe ClassContext do
11
+ it 'should report Long Parameter List' do
12
+ ruby = 'class Inner; def simple(arga, argb, argc, argd) f(3);true end end'
13
+ ruby.should reek_of(:LongParameterList, /Inner/, /simple/, /4 parameters/)
14
+ end
15
+
16
+ it 'should report two different methods' do
17
+ src = <<EOEX
18
+ class Fred
19
+ def simple(arga, argb, argc, argd) f(3);true end
20
+ def simply(arga, argb, argc, argd) f(3);false end
21
+ end
22
+ EOEX
23
+ src.should reek_of(:LongParameterList, /Fred/, /simple/)
24
+ src.should reek_of(:LongParameterList, /Fred/, /simply/)
25
+ end
26
+
27
+ it 'should report many different methods' do
28
+ src = <<EOEX
29
+ class Fred
30
+ def textile_bq(tag, atts, cite, content) f(3);end
31
+ def textile_p(tag, atts, cite, content) f(3);end
32
+ def textile_fn_(tag, num, atts, cite, content) f(3);end
33
+ def textile_popup_help(name, windowW, windowH) f(3);end
34
+ end
35
+ EOEX
36
+ src.should reek_of(:LongParameterList, /Fred/, /textile_bq/)
37
+ src.should reek_of(:LongParameterList, /Fred/, /textile_fn_/)
38
+ src.should reek_of(:LongParameterList, /Fred/, /textile_p/)
39
+ end
40
+ end
41
+
42
+ describe Class do
43
+
44
+ module Insert
45
+ def meth_a() end
46
+ private
47
+ def meth_b() end
48
+ protected
49
+ def meth_c() end
50
+ end
51
+
52
+ class Parent
53
+ def meth1() end
54
+ private
55
+ def meth2() end
56
+ protected
57
+ def meth3() end
58
+ end
59
+
60
+ class FullChild < Parent
61
+ include Insert
62
+ def meth7() end
63
+ private
64
+ def meth8() end
65
+ protected
66
+ def meth6() end
67
+ end
68
+
69
+ describe 'with no superclass or modules' do
70
+ it 'should report correct number of methods' do
71
+ Parent.non_inherited_methods.length.should == 3
72
+ end
73
+ end
74
+
75
+ describe 'with superclass and modules' do
76
+ it 'should report correct number of methods' do
77
+ FullChild.non_inherited_methods.length.should == 3
78
+ end
79
+ end
80
+ end
81
+
82
+ describe ClassContext, 'overridden methods' do
83
+ class Above
84
+ def above() end
85
+ def both() end
86
+ end
87
+
88
+ class Below < Above
89
+ def both() end
90
+ def below() end
91
+ end
92
+
93
+ describe 'of loaded class' do
94
+ before :each do
95
+ @ctx = ClassContext.create(StopContext.new, [0, :Below])
96
+ end
97
+
98
+ it 'should recognise non-overridden method' do
99
+ @ctx.is_overriding_method?('below').should == false
100
+ @ctx.is_overriding_method?('above').should == false
101
+ end
102
+
103
+ it 'should recognise overridden method' do
104
+ @ctx.is_overriding_method?('both').should == true
105
+ end
106
+
107
+ it 'should recognise methods in current codebase' do
108
+ ctx = ClassContext.create(StopContext.new, [0, :FeatureEnvy])
109
+ ctx.is_overriding_method?('examine_context').should == true
110
+ end
111
+ end
112
+
113
+ describe 'of non-loaded class' do
114
+ before :each do
115
+ @ctx = ClassContext.create(StopContext.new, [0, :Missing])
116
+ end
117
+
118
+ it 'should recognise non-overridden method' do
119
+ @ctx.is_overriding_method?('below').should == false
120
+ @ctx.is_overriding_method?('above').should == false
121
+ end
122
+
123
+ it 'should recognise overridden method' do
124
+ @ctx.is_overriding_method?('both').should == false
125
+ end
126
+ end
127
+ end
128
+
129
+ describe 'Integration defect:' do
130
+ it 'should not report UtilityFunction for FeatureEnvy#examine_context' do
131
+ kelement = ClassContext.create(StopContext.new, [0, :FeatureEnvy, s(:const, :SmellDetector)])
132
+ meth = Name.new(:examine_context)
133
+ kelement.is_overriding_method?(meth).should == true
134
+ melement = MethodContext.new(kelement, [0, :examine_context])
135
+ melement.is_overriding_method?(meth).should == true
136
+ melement.depends_on_instance?.should == true
137
+ end
138
+ end
139
+
140
+ describe CodeContext, 'find class' do
141
+ module Mod1
142
+ class Klass1
143
+ module Mod2
144
+ class Klass2
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ before :each do
151
+ @stop = StopContext.new
152
+ @mod1 = ModuleContext.create(@stop, [0, :Mod1])
153
+ @klass1 = ClassContext.create(@mod1, [0, :Klass1])
154
+ @mod2 = ModuleContext.create(@klass1, [0, :Mod2])
155
+ @klass2 = ClassContext.create(@mod2, [0, :Klass2])
156
+ end
157
+
158
+ describe StopContext do
159
+ it 'should not find unqualified class' do
160
+ @stop.find_module('Klass2').should == nil
161
+ end
162
+
163
+ it 'should find unqualified module' do
164
+ @stop.find_module('Mod1').name.should == 'Mod1'
165
+ end
166
+ end
167
+
168
+ describe ModuleContext do
169
+ it 'should find local name' do
170
+ @mod1.find_module('Klass1').name.should == 'Mod1::Klass1'
171
+ @mod2.find_module('Klass2').name.should == 'Mod1::Klass1::Mod2::Klass2'
172
+ end
173
+
174
+ it 'should not find deeper class' do
175
+ @mod1.find_module('Klass2').should == nil
176
+ end
177
+
178
+ it 'should find own Module' do
179
+ @mod1.myself.name.should == 'Mod1'
180
+ @mod2.myself.name.should == 'Mod1::Klass1::Mod2'
181
+ end
182
+ end
183
+
184
+ describe ClassContext do
185
+ it 'should find local module' do
186
+ @klass1.find_module('Mod2').name.should == 'Mod1::Klass1::Mod2'
187
+ end
188
+
189
+ it 'should not find deeper module' do
190
+ @klass1.find_module('Klass2').should == nil
191
+ end
192
+
193
+ it 'should find own Class' do
194
+ @klass1.myself.name.should == 'Mod1::Klass1'
195
+ @klass2.myself.name.should == 'Mod1::Klass1::Mod2::Klass2'
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,92 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/block_context'
4
+ require 'reek/if_context'
5
+ require 'reek/class_context'
6
+ require 'reek/module_context'
7
+ require 'reek/method_context'
8
+ require 'reek/stop_context'
9
+
10
+ include Reek
11
+
12
+ describe CodeContext, 'to_s' do
13
+
14
+ it "should report full context" do
15
+ element = StopContext.new
16
+ element = ModuleContext.new(element, [0, :mod])
17
+ element = ClassContext.new(element, [0, :klass])
18
+ element = MethodContext.new(element, [0, :bad])
19
+ element = BlockContext.new(element, nil)
20
+ element.to_s.should match(/bad/)
21
+ element.to_s.should match(/klass/)
22
+ element.to_s.should match(/mod/)
23
+ end
24
+
25
+ it "should report method name via if context" do
26
+ element1 = StopContext.new
27
+ element2 = MethodContext.new(element1, [0, :bad])
28
+ element3 = IfContext.new(element2, [0,1])
29
+ BlockContext.new(element3, nil).to_s.should match(/bad/)
30
+ end
31
+
32
+ it "should report method name via nested blocks" do
33
+ element1 = StopContext.new
34
+ element2 = MethodContext.new(element1, [0, :bad])
35
+ element3 = BlockContext.new(element2, nil)
36
+ BlockContext.new(element3, nil).to_s.should match(/bad/)
37
+ end
38
+ end
39
+
40
+ describe CodeContext, 'instance variables' do
41
+ it 'should pass instance variables down to the first class' do
42
+ element = StopContext.new
43
+ element = ModuleContext.new(element, [0, :mod])
44
+ class_element = ClassContext.new(element, [0, :klass])
45
+ element = MethodContext.new(class_element, [0, :bad])
46
+ element = BlockContext.new(element, nil)
47
+ element.record_instance_variable(:fred)
48
+ class_element.variable_names.should == [Name.new(:fred)]
49
+ end
50
+ end
51
+
52
+ describe CodeContext, 'generics' do
53
+ it 'should pass unknown method calls down the stack' do
54
+ stop = StopContext.new
55
+ def stop.bananas(arg1, arg2) arg1 + arg2 + 43 end
56
+ element = ModuleContext.new(stop, [0, :mod])
57
+ class_element = ClassContext.new(element, [0, :klass])
58
+ element = MethodContext.new(class_element, [0, :bad])
59
+ element = BlockContext.new(element, nil)
60
+ element.bananas(17, -5).should == 55
61
+ end
62
+ end
63
+
64
+ describe CodeContext do
65
+ it 'should recognise itself in a collection of names' do
66
+ element = StopContext.new
67
+ element = ModuleContext.new(element, [0, :mod])
68
+ element.matches?(['banana', 'mod']).should == true
69
+ end
70
+
71
+ it 'should recognise itself in a collection of REs' do
72
+ element = StopContext.new
73
+ element = ModuleContext.new(element, [0, :mod])
74
+ element.matches?([/banana/, /mod/]).should == true
75
+ end
76
+
77
+ it 'should recognise its fq name in a collection of names' do
78
+ element = StopContext.new
79
+ element = ModuleContext.new(element, [0, :mod])
80
+ element = ClassContext.create(element, [0, :klass])
81
+ element.matches?(['banana', 'mod']).should == true
82
+ element.matches?(['banana', 'mod::klass']).should == true
83
+ end
84
+
85
+ it 'should recognise its fq name in a collection of names' do
86
+ element = StopContext.new
87
+ element = ModuleContext.new(element, [0, :mod])
88
+ element = ClassContext.create(element, [0, :klass])
89
+ element.matches?([/banana/, /mod/]).should == true
90
+ element.matches?([/banana/, /mod::klass/]).should == true
91
+ end
92
+ end
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/code_parser'
4
+ require 'reek/report'
5
+
6
+ include Reek
7
+
8
+ describe CodeParser, "with no method definitions" do
9
+ it 'should report no problems for empty source code' do
10
+ ''.should_not reek
11
+ end
12
+ it 'should report no problems for empty class' do
13
+ 'class Fred; end'.should_not reek
14
+ end
15
+ end
16
+
17
+ describe CodeParser, 'with a global method definition' do
18
+ it 'should report no problems for simple method' do
19
+ 'def Outermost::fred() true; end'.should_not reek
20
+ end
21
+ end
22
+
23
+ describe CodeParser, 'when given a C extension' do
24
+ before(:each) do
25
+ @cchk = CodeParser.new(Report.new, SmellConfig.new.smell_listeners)
26
+ end
27
+
28
+ it 'should ignore :cfunc' do
29
+ @cchk.check_object(Enumerable)
30
+ end
31
+ end
32
+
33
+ describe CodeParser, 'when a yield is the receiver' do
34
+ it 'should report no problems' do
35
+ source = 'def values(*args)
36
+ @to_sql += case
37
+ when block_given? then " #{yield.to_sql}"
38
+ else " values (#{args.to_sql})"
39
+ end
40
+ self
41
+ end'
42
+ source.should_not reek
43
+ end
44
+ end
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/smells/smells'
4
+ require 'yaml'
5
+
6
+ include Reek
7
+
8
+ describe 'Config' do
9
+ before :each do
10
+ @first = {
11
+ 'one' => {'two' => 3, 'three' => 4},
12
+ 'two' => {'four' => true}
13
+ }
14
+ end
15
+
16
+ it 'should deep merge Hashes' do
17
+ other = Hash.new {|hash,key| hash[key] = {} }
18
+ other['one']['gunk'] = 45
19
+ other['two']['four'] = false
20
+ @first.value_merge!(other).to_yaml
21
+ @first['two']['four'].should == false
22
+ @first['one'].keys.length.should == 3
23
+ end
24
+
25
+ it 'should deep copy Hashes' do
26
+ second = @first.deep_copy
27
+ second['two'].object_id.should_not be_eql(@first['two'].object_id)
28
+ end
29
+
30
+ it 'should merge array values' do
31
+ @first['three'] = [1,2,3]
32
+ end
33
+ end
34
+
35
+ describe Config, 'merging arrays' do
36
+ it 'should merge array values' do
37
+ first = {'key' => {'one' => [1,2,3]}}
38
+ second = {'key' => {'one' => [4,5]}}
39
+ first.value_merge!(second)
40
+ first['key']['one'].should == [1,2,3,4,5]
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require 'reek/module_context'
3
+ require 'reek/stop_context'
4
+
5
+ include Reek
6
+
7
+ describe ModuleContext do
8
+ it 'should report module name for smell in method' do
9
+ 'module Fred; def simple(x) true; end; end'.should reek_of(:UncommunicativeName, /x/, /simple/, /Fred/)
10
+ end
11
+
12
+ it 'should not report module with empty class' do
13
+ 'module Fred; class Jim; end; end'.should_not reek
14
+ end
15
+
16
+ it 'should handle module with empty class' do
17
+ stop = StopContext.new
18
+ modctx = ModuleContext.create(stop, [:module, :Fred, []])
19
+ modctx.find_module(Name.new(:Jim)).should be_nil
20
+ end
21
+ end
22
+
23
+ describe ModuleContext do
24
+ it 'should recognise global constant' do
25
+ 'module ::Global class Inside; end; end'.should_not reek
26
+ end
27
+
28
+ it 'should not find missing global constant' do
29
+ element = ModuleContext.create(StopContext.new, [:module, [:colon3, :Global], nil])
30
+ element.myself.should be_nil
31
+ end
32
+
33
+ it 'should find global constant' do
34
+ module ::GlobalTestModule; end
35
+ element = ModuleContext.create(StopContext.new, [:module, [:colon3, :GlobalTestModule], nil])
36
+ element.myself.name.should == 'GlobalTestModule'
37
+ end
38
+ end
@@ -0,0 +1,129 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/object_refs'
4
+
5
+ include Reek
6
+
7
+ describe ObjectRefs, 'when empty' do
8
+ before(:each) do
9
+ @refs = ObjectRefs.new
10
+ end
11
+
12
+ it 'should report one ref to self' do
13
+ @refs.refs_to_self.should == 1
14
+ end
15
+ end
16
+
17
+ describe ObjectRefs, 'with no refs to self' do
18
+ before(:each) do
19
+ @refs = ObjectRefs.new
20
+ @refs.record_ref('a')
21
+ @refs.record_ref('b')
22
+ @refs.record_ref('a')
23
+ end
24
+
25
+ it 'should report no refs to self' do
26
+ @refs.refs_to_self.should == 1
27
+ end
28
+
29
+ it 'should report :a as the max' do
30
+ @refs.max_keys.should == ['a']
31
+ end
32
+
33
+ it 'should not report self as the max' do
34
+ @refs.self_is_max?.should == false
35
+ end
36
+ end
37
+
38
+ describe ObjectRefs, 'with one ref to self' do
39
+ before(:each) do
40
+ @refs = ObjectRefs.new
41
+ @refs.record_ref('a')
42
+ @refs.record_ref('b')
43
+ @refs.record_ref('a')
44
+ @refs.record_reference_to_self
45
+ end
46
+
47
+ it 'should report 1 ref to self' do
48
+ @refs.refs_to_self.should == 2
49
+ end
50
+
51
+ it 'should report self among the max' do
52
+ @refs.max_keys.should be_include('a')
53
+ @refs.max_keys.should be_include(Sexp.from_array([:lit, :self]))
54
+ end
55
+
56
+ it 'should report self as the max' do
57
+ @refs.self_is_max?.should == true
58
+ end
59
+ end
60
+
61
+ describe ObjectRefs, 'with many refs to self' do
62
+ before(:each) do
63
+ @refs = ObjectRefs.new
64
+ @refs.record_reference_to_self
65
+ @refs.record_ref('a')
66
+ @refs.record_reference_to_self
67
+ @refs.record_ref('b')
68
+ @refs.record_ref('a')
69
+ @refs.record_reference_to_self
70
+ end
71
+
72
+ it 'should report all refs to self' do
73
+ @refs.refs_to_self.should == 4
74
+ end
75
+
76
+ it 'should report self among the max' do
77
+ @refs.max_keys.should == [Sexp.from_array([:lit, :self])]
78
+ end
79
+
80
+ it 'should report self as the max' do
81
+ @refs.self_is_max?.should == true
82
+ end
83
+ end
84
+
85
+ describe ObjectRefs, 'when self is not the only max' do
86
+ before(:each) do
87
+ @refs = ObjectRefs.new
88
+ @refs.record_ref('a')
89
+ @refs.record_reference_to_self
90
+ @refs.record_ref('b')
91
+ @refs.record_ref('a')
92
+ end
93
+
94
+ it 'should report all refs to self' do
95
+ @refs.refs_to_self.should == 2
96
+ end
97
+
98
+ it 'should report self among the max' do
99
+ @refs.max_keys.should be_include('a')
100
+ @refs.max_keys.should be_include(Sexp.from_array([:lit, :self]))
101
+ end
102
+
103
+ it 'should report self as the max' do
104
+ @refs.self_is_max?.should == true
105
+ end
106
+ end
107
+
108
+ describe ObjectRefs, 'when self is not among the max' do
109
+ before(:each) do
110
+ @refs = ObjectRefs.new
111
+ @refs.record_ref('a')
112
+ @refs.record_ref('b')
113
+ @refs.record_ref('a')
114
+ @refs.record_ref('b')
115
+ end
116
+
117
+ it 'should report all refs to self' do
118
+ @refs.refs_to_self.should == 1
119
+ end
120
+
121
+ it 'should not report self among the max' do
122
+ @refs.max_keys.should be_include('a')
123
+ @refs.max_keys.should be_include('b')
124
+ end
125
+
126
+ it 'should not report self as the max' do
127
+ @refs.self_is_max?.should == false
128
+ end
129
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/options'
4
+
5
+ include Reek
6
+
7
+ describe Options, ' when given no arguments' do
8
+ it "should retain the default sort order" do
9
+ default_order = Options[:format]
10
+ Options.parse ['nosuchfile.rb']
11
+ Options[:format].should == default_order
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ require 'reek/smells/smell_detector'
4
+ require 'reek/report'
5
+ require 'reek/source'
6
+ require 'reek/smells/feature_envy'
7
+
8
+ include Reek
9
+
10
+ describe Report, " when empty" do
11
+ before(:each) do
12
+ @rpt = Report.new
13
+ end
14
+
15
+ it 'should have zero length' do
16
+ @rpt.length.should == 0
17
+ end
18
+
19
+ it 'should claim to be empty' do
20
+ @rpt.should be_empty
21
+ end
22
+ end
23
+
24
+ describe Report, "to_s" do
25
+ before(:each) do
26
+ rpt = Source.from_s('def simple(a) a[3] end').report
27
+ @report = rpt.to_s.split("\n")
28
+ end
29
+
30
+ it 'should place each detailed report on a separate line' do
31
+ @report.length.should == 2
32
+ end
33
+
34
+ it 'should mention every smell name' do
35
+ @report[0].should match(/[Utility Function]/)
36
+ @report[1].should match(/[Feature Envy]/)
37
+ end
38
+ end
39
+
40
+ describe Report, " as a SortedSet" do
41
+ it 'should only add a smell once' do
42
+ rpt = Report.new
43
+ rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
44
+ rpt.length.should == 1
45
+ rpt << SmellWarning.new(Smells::FeatureEnvy.new, "self", 'too many!')
46
+ rpt.length.should == 1
47
+ end
48
+ end