reek 1.2.7.3 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/History.txt +17 -0
  2. data/README.md +32 -48
  3. data/config/defaults.reek +7 -1
  4. data/features/api.feature +20 -0
  5. data/features/masking_smells.feature +41 -0
  6. data/features/options.feature +4 -0
  7. data/features/rake_task.feature +14 -0
  8. data/features/yaml.feature +8 -8
  9. data/lib/reek.rb +1 -1
  10. data/lib/reek/cli/command_line.rb +9 -2
  11. data/lib/reek/cli/reek_command.rb +5 -4
  12. data/lib/reek/cli/yaml_command.rb +2 -2
  13. data/lib/reek/core/code_context.rb +10 -1
  14. data/lib/reek/core/method_context.rb +2 -2
  15. data/lib/reek/core/sniffer.rb +3 -1
  16. data/lib/reek/core/stop_context.rb +4 -0
  17. data/lib/reek/examiner.rb +2 -2
  18. data/lib/reek/rake/task.rb +16 -0
  19. data/lib/reek/smell_warning.rb +3 -2
  20. data/lib/reek/smells/attribute.rb +13 -9
  21. data/lib/reek/smells/boolean_parameter.rb +14 -9
  22. data/lib/reek/smells/class_variable.rb +16 -5
  23. data/lib/reek/smells/control_couple.rb +11 -6
  24. data/lib/reek/smells/data_clump.rb +33 -30
  25. data/lib/reek/smells/duplication.rb +39 -8
  26. data/lib/reek/smells/feature_envy.rb +7 -8
  27. data/lib/reek/smells/irresponsible_module.rb +12 -3
  28. data/lib/reek/smells/large_class.rb +31 -15
  29. data/lib/reek/smells/long_method.rb +15 -5
  30. data/lib/reek/smells/long_parameter_list.rb +14 -7
  31. data/lib/reek/smells/long_yield_list.rb +12 -9
  32. data/lib/reek/smells/nested_iterators.rb +46 -11
  33. data/lib/reek/smells/simulated_polymorphism.rb +16 -8
  34. data/lib/reek/smells/smell_detector.rb +13 -13
  35. data/lib/reek/smells/uncommunicative_method_name.rb +12 -20
  36. data/lib/reek/smells/uncommunicative_module_name.rb +17 -19
  37. data/lib/reek/smells/uncommunicative_parameter_name.rb +22 -15
  38. data/lib/reek/smells/uncommunicative_variable_name.rb +24 -18
  39. data/lib/reek/smells/utility_function.rb +6 -6
  40. data/lib/reek/source/code_comment.rb +19 -1
  41. data/lib/reek/source/tree_dresser.rb +40 -22
  42. data/reek.gemspec +6 -4
  43. data/spec/matchers/smell_of_matcher.rb +58 -0
  44. data/spec/reek/core/code_context_spec.rb +4 -2
  45. data/spec/reek/core/code_parser_spec.rb +2 -1
  46. data/spec/reek/core/method_context_spec.rb +5 -5
  47. data/spec/reek/smells/attribute_spec.rb +2 -4
  48. data/spec/reek/smells/boolean_parameter_spec.rb +32 -42
  49. data/spec/reek/smells/class_variable_spec.rb +22 -6
  50. data/spec/reek/smells/control_couple_spec.rb +15 -14
  51. data/spec/reek/smells/data_clump_spec.rb +29 -111
  52. data/spec/reek/smells/duplication_spec.rb +79 -49
  53. data/spec/reek/smells/feature_envy_spec.rb +1 -2
  54. data/spec/reek/smells/irresponsible_module_spec.rb +43 -22
  55. data/spec/reek/smells/large_class_spec.rb +34 -59
  56. data/spec/reek/smells/long_method_spec.rb +15 -10
  57. data/spec/reek/smells/long_parameter_list_spec.rb +24 -24
  58. data/spec/reek/smells/long_yield_list_spec.rb +13 -14
  59. data/spec/reek/smells/nested_iterators_spec.rb +93 -76
  60. data/spec/reek/smells/smell_detector_shared.rb +4 -2
  61. data/spec/reek/smells/uncommunicative_method_name_spec.rb +10 -27
  62. data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -23
  63. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +36 -26
  64. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +45 -48
  65. data/spec/reek/smells/utility_function_spec.rb +14 -13
  66. data/spec/reek/source/code_comment_spec.rb +61 -3
  67. data/spec/reek/source/tree_dresser_spec.rb +96 -1
  68. data/spec/samples/config/allow_duplication.reek +3 -0
  69. data/spec/samples/config/deeper_nested_iterators.reek +3 -0
  70. data/spec/samples/demo/demo.rb +8 -0
  71. data/spec/samples/inline_config/dirty.rb +16 -0
  72. data/spec/samples/inline_config/masked.reek +7 -0
  73. data/spec/samples/mask_some/dirty.rb +8 -0
  74. data/spec/samples/mask_some/some.reek +8 -0
  75. data/spec/spec_helper.rb +2 -0
  76. metadata +15 -5
@@ -8,29 +8,63 @@ include Reek
8
8
  include Reek::Smells
9
9
 
10
10
  describe Duplication do
11
+
12
+ context 'when a smell is reported' do
13
+ before :each do
14
+ @source_name = 'copy-cat'
15
+ @detector = Duplication.new(@source_name)
16
+ src = <<EOS
17
+ def double_thing(other)
18
+ other[@thing]
19
+ not_the_sam(at = all)
20
+ other[@thing]
21
+ end
22
+ EOS
23
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
24
+ smells = @detector.examine_context(ctx)
25
+ smells.length.should == 1
26
+ @warning = smells[0]
27
+ end
28
+
29
+ it_should_behave_like 'SmellDetector'
30
+ it_should_behave_like 'common fields set correctly'
31
+
32
+ it 'reports the call' do
33
+ @warning.smell[Duplication::CALL_KEY].should == 'other[@thing]'
34
+ end
35
+ it 'reports the correct lines' do
36
+ @warning.lines.should == [2,4]
37
+ end
38
+ end
39
+
11
40
  context "with repeated method calls" do
12
41
  it 'reports repeated call' do
13
- 'def double_thing() @other.thing + @other.thing end'.should reek_only_of(:Duplication, /@other.thing/)
42
+ src = 'def double_thing() @other.thing + @other.thing end'
43
+ src.should smell_of(Duplication, Duplication::CALL_KEY => '@other.thing')
14
44
  end
15
45
  it 'reports repeated call to lvar' do
16
- 'def double_thing(other) other[@thing] + other[@thing] end'.should reek_only_of(:Duplication, /other\[@thing\]/)
46
+ src = 'def double_thing(other) other[@thing] + other[@thing] end'
47
+ src.should smell_of(Duplication, Duplication::CALL_KEY => 'other[@thing]')
17
48
  end
18
49
  it 'reports call parameters' do
19
- 'def double_thing() @other.thing(2,3) + @other.thing(2,3) end'.should reek_only_of(:Duplication, /@other.thing\(2, 3\)/)
50
+ src = 'def double_thing() @other.thing(2,3) + @other.thing(2,3) end'
51
+ src.should smell_of(Duplication, Duplication::CALL_KEY => '@other.thing(2, 3)')
20
52
  end
21
53
  it 'should report nested calls' do
22
- ruby = 'def double_thing() @other.thing.foo + @other.thing.foo end'
23
- ruby.should reek_of(:Duplication, /@other.thing[^\.]/)
24
- ruby.should reek_of(:Duplication, /@other.thing.foo/)
54
+ src = 'def double_thing() @other.thing.foo + @other.thing.foo end'
55
+ src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing'},
56
+ {Duplication::CALL_KEY => '@other.thing.foo'})
25
57
  end
26
58
  it 'should ignore calls to new' do
27
- 'def double_thing() @other.new + @other.new end'.should_not reek
59
+ src = 'def double_thing() @other.new + @other.new end'
60
+ src.should_not smell_of(Duplication)
28
61
  end
29
62
  end
30
63
 
31
64
  context 'with repeated attribute assignment' do
32
65
  it 'reports repeated assignment' do
33
- 'def double_thing(thing) @other[thing] = true; @other[thing] = true; end'.should reek_only_of(:Duplication, /@other\[thing\] = true/)
66
+ src = 'def double_thing(thing) @other[thing] = true; @other[thing] = true; end'
67
+ src.should smell_of(Duplication, Duplication::CALL_KEY => '@other[thing] = true')
34
68
  end
35
69
  it 'does not report multi-assignments' do
36
70
  src = <<EOS
@@ -39,58 +73,54 @@ def _parse ctxt
39
73
  error, ctxt.index = @err, @err_ind
40
74
  end
41
75
  EOS
42
- src.should_not reek
76
+ src.should_not smell_of(Duplication)
43
77
  end
44
78
  end
45
- end
46
-
47
- describe Duplication, "non-repeated method calls" do
48
- it 'should not report similar calls' do
49
- 'def equals(other) other.thing == self.thing end'.should_not reek
50
- end
51
79
 
52
- it 'should respect call parameters' do
53
- 'def double_thing() @other.thing(3) + @other.thing(2) end'.should_not reek
54
- end
55
- end
56
-
57
- describe Duplication do
58
- before(:each) do
59
- @source_name = 'copy-cat'
60
- @detector = Duplication.new(@source_name)
80
+ context "non-repeated method calls" do
81
+ it 'should not report similar calls' do
82
+ src = 'def equals(other) other.thing == self.thing end'
83
+ src.should_not smell_of(Duplication)
84
+ end
85
+ it 'should respect call parameters' do
86
+ src = 'def double_thing() @other.thing(3) + @other.thing(2) end'
87
+ src.should_not smell_of(Duplication)
88
+ end
61
89
  end
62
90
 
63
- it_should_behave_like 'SmellDetector'
64
-
65
- context 'when a smell is reported' do
91
+ context "allowing up to 3 calls" do
66
92
  before :each do
67
- src = <<EOS
68
- def double_thing(other)
69
- other[@thing]
70
- not_the_sam(at = all)
71
- other[@thing]
72
- end
73
- EOS
74
- source = src.to_reek_source
75
- sniffer = Core::Sniffer.new(source)
76
- @mctx = Core::CodeParser.new(sniffer).process_defn(source.syntax_tree)
77
- @detector.examine(@mctx)
78
- @warning = @detector.smells_found.to_a[0] # SMELL: too cumbersome!
93
+ @config = {Duplication::MAX_ALLOWED_CALLS_KEY => 3}
79
94
  end
80
- it 'reports the source' do
81
- @warning.source.should == @source_name
95
+ it 'does not report double calls' do
96
+ src = 'def double_thing() @other.thing + @other.thing end'
97
+ src.should_not smell_of(Duplication).with_config(@config)
82
98
  end
83
- it 'reports the class' do
84
- @warning.smell_class.should == 'Duplication'
99
+ it 'does not report triple calls' do
100
+ src = 'def double_thing() @other.thing + @other.thing + @other.thing end'
101
+ src.should_not smell_of(Duplication).with_config(@config)
85
102
  end
86
- it 'reports the subclass' do
87
- @warning.subclass.should == 'DuplicateMethodCall'
103
+ it 'reports quadruple calls' do
104
+ src = 'def double_thing() @other.thing + @other.thing + @other.thing + @other.thing end'
105
+ src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing', Duplication::OCCURRENCES_KEY => 4}).with_config(@config)
88
106
  end
89
- it 'reports the call' do
90
- @warning.smell['call'].should == 'other[@thing]'
107
+ end
108
+
109
+ context "allowing calls to some methods" do
110
+ before :each do
111
+ @config = {Duplication::ALLOW_CALLS_KEY => ['@some.thing',/puts/]}
91
112
  end
92
- it 'reports the correct lines' do
93
- @warning.lines.should == [2,4]
113
+ it 'does not report calls to some methods' do
114
+ src = 'def double_some_thing() @some.thing + @some.thing end'
115
+ src.should_not smell_of(Duplication).with_config(@config)
116
+ end
117
+ it 'reports calls to other methods' do
118
+ src = 'def double_other_thing() @other.thing + @other.thing end'
119
+ src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing'}).with_config(@config)
120
+ end
121
+ it 'does not report calls to methods specifed with a regular expression' do
122
+ src = 'def double_puts() puts @other.thing; puts @other.thing end'
123
+ src.should smell_of(Duplication, {Duplication::CALL_KEY => '@other.thing'}).with_config(@config)
94
124
  end
95
125
  end
96
126
  end
@@ -190,8 +190,7 @@ EOS
190
190
  source = src.to_reek_source
191
191
  sniffer = Sniffer.new(source)
192
192
  @mctx = CodeParser.new(sniffer).process_defn(source.syntax_tree)
193
- @detector.examine_context(@mctx)
194
- @smells = @detector.smells_found.to_a
193
+ @smells = @detector.examine_context(@mctx)
195
194
  end
196
195
  it 'reports only that smell' do
197
196
  @smells.length.should == 1
@@ -5,33 +5,54 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shar
5
5
  include Reek::Smells
6
6
 
7
7
  describe IrresponsibleModule do
8
- ['class'].each do |unit|
9
- it "does not report a #{unit} having a comment" do
10
- src = <<EOS
11
- # test #{unit}
12
- #{unit} Responsible; end
8
+ before(:each) do
9
+ @bad_module_name = 'WrongUn'
10
+ @detector = IrresponsibleModule.new('yoof')
11
+ end
12
+
13
+ it_should_behave_like 'SmellDetector'
14
+
15
+ it "does not report a class having a comment" do
16
+ src = <<EOS
17
+ # test class
18
+ class Responsible; end
13
19
  EOS
14
- src.should_not reek
15
- end
16
- it "reports a #{unit} without a comment" do
17
- "#{unit} Responsible; end".should reek_only_of(:IrresponsibleModule, /Responsible/)
18
- end
19
- it "reports a #{unit} with an empty comment" do
20
- src = <<EOS
20
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
21
+ @detector.examine_context(ctx).should be_empty
22
+ end
23
+ it "reports a class without a comment" do
24
+ src = "class #{@bad_module_name}; end"
25
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
26
+ smells = @detector.examine_context(ctx)
27
+ smells.length.should == 1
28
+ smells[0].smell_class.should == IrresponsibleModule::SMELL_CLASS
29
+ smells[0].subclass.should == IrresponsibleModule::SMELL_SUBCLASS
30
+ smells[0].lines.should == [1]
31
+ smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY].should == @bad_module_name
32
+ end
33
+ it "reports a class with an empty comment" do
34
+ src = <<EOS
21
35
  #
22
36
  #
23
37
  #
24
- #{unit} Responsible; end
38
+ class #{@bad_module_name}; end
25
39
  EOS
26
- src.should reek_only_of(:IrresponsibleModule, /Responsible/)
27
- end
40
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
41
+ smells = @detector.examine_context(ctx)
42
+ smells.length.should == 1
43
+ smells[0].smell_class.should == IrresponsibleModule::SMELL_CLASS
44
+ smells[0].subclass.should == IrresponsibleModule::SMELL_SUBCLASS
45
+ smells[0].lines.should == [4]
46
+ smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY].should == @bad_module_name
28
47
  end
29
- end
30
-
31
- describe IrresponsibleModule do
32
- before(:each) do
33
- @detector = IrresponsibleModule.new('yoof')
48
+ it 'reports a fq module name correctly' do
49
+ src = 'class Foo::Bar; end'
50
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
51
+ smells = @detector.examine_context(ctx)
52
+ smells.length.should == 1
53
+ smells[0].smell_class.should == IrresponsibleModule::SMELL_CLASS
54
+ smells[0].subclass.should == IrresponsibleModule::SMELL_SUBCLASS
55
+ smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY].should == 'Foo::Bar'
56
+ smells[0].context.should match(/#{smells[0].smell[IrresponsibleModule::MODULE_NAME_KEY]}/)
34
57
  end
35
-
36
- it_should_behave_like 'SmellDetector'
37
58
  end
@@ -7,7 +7,13 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'smell_detector_shar
7
7
  include Reek
8
8
  include Reek::Smells
9
9
 
10
- describe LargeClass, 'checking source code' do
10
+ describe LargeClass do
11
+ before(:each) do
12
+ @source_name = 'elephant'
13
+ @detector = LargeClass.new(@source_name)
14
+ end
15
+
16
+ it_should_behave_like 'SmellDetector'
11
17
 
12
18
  context 'counting instance variables' do
13
19
  it 'should not report 9 ivars' do
@@ -49,7 +55,8 @@ class Full
49
55
  def me41x()3 end;def me42x()3 end;def me43x()3 end;def me44x()3 end;def me45x()3 end
50
56
  end
51
57
  EOS
52
- src.should_not reek
58
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
59
+ @detector.examine_context(ctx).should be_empty
53
60
  end
54
61
 
55
62
  it 'should report 26 methods' do
@@ -63,7 +70,11 @@ class Full
63
70
  def me51x()3 end
64
71
  end
65
72
  EOS
66
- src.should reek_of(:LargeClass)
73
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
74
+ smells = @detector.examine_context(ctx)
75
+ smells.length.should == 1
76
+ smells[0].subclass.should == LargeClass::SUBCLASS_TOO_MANY_METHODS
77
+ smells[0].smell[LargeClass::METHOD_COUNT_KEY].should == 26
67
78
  end
68
79
  end
69
80
 
@@ -79,22 +90,13 @@ class Full
79
90
  def me51x()3 end
80
91
  end
81
92
  EOS
82
- src.should_not reek_of(:LargeClass)
93
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
94
+ @detector.examine_context(ctx).should be_empty
83
95
  end
84
96
  end
85
- end
86
-
87
- describe LargeClass, 'looking at the YAML' do
88
- before(:each) do
89
- @source_name = 'elephant'
90
- @detector = LargeClass.new(@source_name)
91
- end
92
-
93
- it_should_behave_like 'SmellDetector'
94
97
 
95
- context 'when the class has many methods' do
96
- before :each do
97
- src = <<EOS
98
+ it 'reports correctly when the class has many methods' do
99
+ src = <<EOS
98
100
  class Full
99
101
  def me01x()3 end;def me02x()3 end;def me03x()3 end;def me04x()3 end;def me05x()3 end
100
102
  def me11x()3 end;def me12x()3 end;def me13x()3 end;def me14x()3 end;def me15x()3 end
@@ -104,29 +106,17 @@ class Full
104
106
  def me51x()3 end
105
107
  end
106
108
  EOS
107
- @yaml = Examiner.new(src).smells[0].to_yaml
108
- end
109
- it 'reports the source' do
110
- @yaml.should match(/source:\s*string/)
111
- end
112
- it 'reports the correct class' do
113
- @yaml.should match(/\sclass:\s*LargeClass/)
114
- end
115
- it 'reports the correct subclass' do
116
- @yaml.should match(/\ssubclass:\s*#{LargeClass::SUBCLASS_TOO_MANY_METHODS}/)
117
- end
118
- it 'reports the number of methods' do
119
- @yaml.should match(/method_count:[\s]*26/)
120
- # SMELL: many tests duplicate the names of the YAML fields
121
- end
122
- it 'reports the line number of the declaration' do
123
- @yaml.should match(/lines:\s*- 1/)
124
- end
109
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
110
+ @warning = @detector.examine_context(ctx)[0]
111
+ @warning.source.should == @source_name
112
+ @warning.smell_class.should == 'LargeClass'
113
+ @warning.subclass.should == LargeClass::SUBCLASS_TOO_MANY_METHODS
114
+ @warning.smell[LargeClass::METHOD_COUNT_KEY].should == 26
115
+ @warning.lines.should == [1]
125
116
  end
126
117
 
127
- context 'when the class has 30 instance variables' do
128
- before :each do
129
- src = <<EOS
118
+ it 'reports correctly when the class has 30 instance variables' do
119
+ src = <<EOS
130
120
  # smelly class for testing purposes
131
121
  class Empty
132
122
  def ivars
@@ -134,27 +124,12 @@ class Empty
134
124
  end
135
125
  end
136
126
  EOS
137
- source = src.to_reek_source
138
- sniffer = Core::Sniffer.new(source)
139
- ctx = Core::CodeParser.new(sniffer).process_class(source.syntax_tree)
140
- @detector.examine_context(ctx)
141
- @yaml = @detector.smells_found.to_a[0].to_yaml # SMELL: too cumbersome!
142
- end
143
- it 'reports the source' do
144
- @yaml.should match(/source:\s*#{@source_name}/)
145
- end
146
- it 'reports the correct class' do
147
- @yaml.should match(/\sclass:\s*LargeClass/)
148
- end
149
- it 'reports the correct subclass' do
150
- @yaml.should match(/\ssubclass:\s*#{LargeClass::SUBCLASS_TOO_MANY_IVARS}/)
151
- end
152
- it 'reports the number of methods' do
153
- @yaml.should match(/ivar_count:\s*10/)
154
- # SMELL: many tests duplicate the names of the YAML fields
155
- end
156
- it 'reports the line number of the declaration' do
157
- @yaml.should match(/lines:\s*- 2/)
158
- end
127
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
128
+ @warning = @detector.examine_context(ctx)[0]
129
+ @warning.source.should == @source_name
130
+ @warning.smell_class.should == 'LargeClass'
131
+ @warning.subclass.should == LargeClass::SUBCLASS_TOO_MANY_IVARS
132
+ @warning.smell[LargeClass::IVAR_COUNT_KEY].should == 10
133
+ @warning.lines.should == [2]
159
134
  end
160
135
  end
@@ -15,15 +15,18 @@ end
15
15
 
16
16
  describe LongMethod do
17
17
  it 'should not report short methods' do
18
- 'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'.should_not reek
18
+ src = 'def short(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;end'
19
+ src.should_not smell_of(LongMethod)
19
20
  end
20
21
 
21
22
  it 'should report long methods' do
22
- 'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should reek_only_of(:LongMethod, /6 statements/)
23
+ src = 'def long(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'
24
+ src.should reek_only_of(:LongMethod, /6 statements/)
23
25
  end
24
26
 
25
27
  it 'should not report initialize' do
26
- 'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'.should_not reek
28
+ src = 'def initialize(arga) alf = f(1);@bet = 2;@cut = 3;@dit = 4; @emp = 5;@fry = 6;end'
29
+ src.should_not smell_of(LongMethod)
27
30
  end
28
31
 
29
32
  it 'should only report a long method once' do
@@ -205,17 +208,19 @@ describe LongMethod do
205
208
  context 'when the method has 30 statements' do
206
209
  before :each do
207
210
  @num_statements = 30
208
- @ctx = mock('method_context', :null_object => true)
209
- @ctx.should_receive(:num_statements).and_return(@num_statements)
210
- @detector.examine_context(@ctx)
211
- @yaml = @detector.smells_found.to_a[0].to_yaml # SMELL: too cumbersome!
211
+ ctx = mock('method_context', :null_object => true)
212
+ ctx.should_receive(:num_statements).and_return(@num_statements)
213
+ ctx.should_receive(:config).and_return({})
214
+ @smells = @detector.examine_context(ctx)
215
+ end
216
+ it 'reports only 1 smell' do
217
+ @smells.length.should == 1
212
218
  end
213
219
  it 'reports the number of statements' do
214
- @yaml.should match(/statement_count:[\s]*#{@num_statements}/)
215
- # SMELL: many tests duplicate the names of the YAML fields
220
+ @smells[0].smell[LongMethod::STATEMENT_COUNT_KEY].should == @num_statements
216
221
  end
217
222
  it 'reports the correct subclass' do
218
- @yaml.should match(/subclass:[\s]*#{LongMethod::SUBCLASS_TOO_MANY_STATEMENTS}/)
223
+ @smells[0].subclass.should == LongMethod::SUBCLASS_TOO_MANY_STATEMENTS
219
224
  end
220
225
  end
221
226
  end
@@ -6,51 +6,56 @@ include Reek
6
6
  include Reek::Smells
7
7
 
8
8
  describe LongParameterList do
9
-
10
- describe 'for methods with few parameters' do
9
+
10
+ context 'for methods with few parameters' do
11
11
  it 'should report nothing for no parameters' do
12
- 'def simple; f(3);true; end'.should_not reek
12
+ 'def simple; f(3);true; end'.should_not smell_of(LongParameterList)
13
13
  end
14
14
  it 'should report nothing for 1 parameter' do
15
- 'def simple(yep) f(3);true end'.should_not reek
15
+ 'def simple(yep) f(3);true end'.should_not smell_of(LongParameterList)
16
16
  end
17
17
  it 'should report nothing for 2 parameters' do
18
- 'def simple(yep,zero) f(3);true end'.should_not reek
18
+ 'def simple(yep,zero) f(3);true end'.should_not smell_of(LongParameterList)
19
19
  end
20
20
  it 'should not count an optional block' do
21
- 'def simple(alpha, yep, zero, &opt) f(3);true end'.should_not reek
21
+ 'def simple(alpha, yep, zero, &opt) f(3);true end'.should_not smell_of(LongParameterList)
22
22
  end
23
23
  it 'should not report inner block with too many parameters' do
24
- 'def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end'.should_not reek
24
+ src = 'def simple(yep,zero); m[3]; rand(34); f.each { |arga, argb, argc, argd| true}; end'
25
+ src.should_not smell_of(LongParameterList)
25
26
  end
26
27
 
27
28
  describe 'and default values' do
28
29
  it 'should report nothing for 1 parameter' do
29
- 'def simple(zero=nil) f(3);false end'.should_not reek
30
+ 'def simple(zero=nil) f(3);false end'.should_not smell_of(LongParameterList)
30
31
  end
31
32
  it 'should report nothing for 2 parameters with 1 default' do
32
- 'def simple(yep, zero=nil) f(3);false end'.should_not reek
33
+ 'def simple(yep, zero=nil) f(3);false end'.should_not smell_of(LongParameterList)
33
34
  end
34
35
  it 'should report nothing for 2 defaulted parameters' do
35
- 'def simple(yep=4, zero=nil) f(3);false end'.should_not reek
36
+ 'def simple(yep=4, zero=nil) f(3);false end'.should_not smell_of(LongParameterList)
36
37
  end
37
38
  end
38
39
  end
39
40
 
40
41
  describe 'for methods with too many parameters' do
41
42
  it 'should report 4 parameters' do
42
- 'def simple(arga, argb, argc, argd) f(3);true end'.should reek_only_of(:LongParameterList, /4 parameters/)
43
+ src = 'def simple(arga, argb, argc, argd) f(3);true end'
44
+ src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 4)
43
45
  end
44
46
  it 'should report 8 parameters' do
45
- 'def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end'.should reek_only_of(:LongParameterList, /8 parameters/)
47
+ src = 'def simple(arga, argb, argc, argd,arge, argf, argg, argh) f(3);true end'
48
+ src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 8)
46
49
  end
47
50
 
48
51
  describe 'and default values' do
49
52
  it 'should report 3 with 1 defaulted' do
50
- 'def simple(polly, queue, yep, zero=nil) f(3);false end'.should reek_only_of(:LongParameterList, /4 parameters/)
53
+ src = 'def simple(polly, queue, yep, zero=nil) f(3);false end'
54
+ src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 4)
51
55
  end
52
56
  it 'should report with 3 defaulted' do
53
- 'def simple(aarg, polly=2, yep=:truth, zero=nil) f(3);false end'.should reek_only_of(:LongParameterList, /4 parameters/)
57
+ src = 'def simple(aarg, polly=2, yep=:truth, zero=nil) f(3);false end'
58
+ src.should smell_of(LongParameterList, LongParameterList::PARAMETER_COUNT_KEY => 4)
54
59
  end
55
60
  end
56
61
  end
@@ -59,9 +64,7 @@ end
59
64
  describe LongParameterList do
60
65
  before(:each) do
61
66
  @source_name = 'smokin'
62
- @detector = LongParameterList.new(@source_name, {})
63
- # SMELL: can't use the default config, because that contains an override,
64
- # which causes the mocked matches?() method to be called twice!!
67
+ @detector = LongParameterList.new(@source_name)
65
68
  end
66
69
 
67
70
  it_should_behave_like 'SmellDetector'
@@ -74,18 +77,15 @@ def badguy(arga, argb, argc, argd)
74
77
  true
75
78
  end
76
79
  EOS
77
- source = src.to_reek_source
78
- sniffer = Sniffer.new(source)
79
- mctx = CodeParser.new(sniffer).process_defn(source.syntax_tree)
80
- @detector.examine_context(mctx)
81
- @warning = @detector.smells_found.to_a[0] # SMELL: too cumbersome!
80
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
81
+ @smells = @detector.examine_context(ctx)
82
+ @warning = @smells[0]
82
83
  end
83
84
 
84
85
  it_should_behave_like 'common fields set correctly'
85
86
 
86
87
  it 'reports the number of parameters' do
87
- @warning.smell['parameter_count'].should == 4
88
- # SMELL: many tests duplicate the names of the YAML fields
88
+ @warning.smell[LongParameterList::PARAMETER_COUNT_KEY].should == 4
89
89
  end
90
90
  it 'reports the line number of the method' do
91
91
  @warning.lines.should == [1]