kevinrutherford-reek 0.3.1.4

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