reek 1.2.7.3 → 1.2.8

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