cuke_sniffer 0.0.3 → 0.0.5

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.
@@ -1,173 +1,256 @@
1
1
  module CukeSniffer
2
+
3
+ # Contains the rules and various scores used in evaluating objects
2
4
  module RuleConfig
3
5
 
4
- FATAL = 100 #will prevent suite from executing properly
5
- ERROR = 25 #will cause problem with debugging
6
- WARNING = 10 #readibility/misuse of cucumber
7
- INFO = 1 #Small improvements that can be made
6
+ # Will prevent suite from executing properly
7
+ FATAL = 100
8
8
 
9
- RULES = {
10
- :too_many_tags => {
9
+ # Will cause problem with debugging
10
+ ERROR = 25
11
+
12
+ # Readability/misuse of cucumber
13
+ WARNING = 10
14
+
15
+ # Small improvements that can be made
16
+ INFO = 1
17
+
18
+ fatal_rules = {
19
+ :no_examples => {
11
20
  :enabled => true,
12
- :phrase => "{class} has too many tags.",
13
- :score => INFO,
14
- :max => 8
21
+ :phrase => "Scenario Outline with no examples.",
22
+ :score => FATAL
15
23
  },
24
+ :no_examples_table => {
25
+ :enabled => true,
26
+ :phrase => "Scenario Outline with no examples table.",
27
+ :score => FATAL
28
+ },
29
+ :recursive_nested_step => {
30
+ :enabled => true,
31
+ :phrase => "Recursive nested step call.",
32
+ :score => FATAL
33
+ },
34
+ :background_with_tag => {
35
+ :enabled => true,
36
+ :phrase => "There is a background with a tag. This feature file cannot run!",
37
+ :score => FATAL
38
+ },
39
+ :comment_after_tag => {
40
+ :enabled => true,
41
+ :phrase => "Comment comes between tag and properly executing line. This feature file cannot run!",
42
+ :score => FATAL
43
+ }
44
+ }
45
+
46
+ error_rules = {
16
47
  :no_description => {
17
48
  :enabled => true,
18
49
  :phrase => "{class} has no description.",
19
- :score => ERROR,
50
+ :score => ERROR
20
51
  },
21
- :numbers_in_description => {
52
+ :no_scenarios => {
22
53
  :enabled => true,
23
- :phrase => "{class} has numbers in the description.",
24
- :score => WARNING,
54
+ :phrase => "Feature with no scenarios.",
55
+ :score => ERROR
25
56
  },
26
- :long_name => {
57
+ :commented_step => {
27
58
  :enabled => true,
28
- :phrase => "{class} has a long description.",
29
- :score => INFO,
30
- :max => 180
59
+ :phrase => "Commented step.",
60
+ :score => ERROR
31
61
  },
32
- :implementation_word => {
62
+ :commented_example => {
33
63
  :enabled => true,
34
- :phrase => "Implementation word used: {word}.",
35
- :score => INFO,
36
- :words => ["page", "site", "url", "button", "drop down", "dropdown", "select list", "click", "text box", "radio button", "check box", "xml", "window", "pop up", "pop-up", "screen"]
64
+ :phrase => "Commented example.",
65
+ :score => ERROR
66
+ },
67
+ :no_steps => {
68
+ :enabled => true,
69
+ :phrase => "No steps in Scenario.",
70
+ :score => ERROR
71
+ },
72
+ :one_word_step => {
73
+ :enabled => true,
74
+ :phrase => "Step that is only one word long.",
75
+ :score => ERROR
76
+ },
77
+ :no_code => {
78
+ :enabled => true,
79
+ :phrase => "No code in Step Definition.",
80
+ :score => ERROR
81
+ },
82
+ :around_hook_without_2_parameters => {
83
+ :enabled => true,
84
+ :phrase => "Around hook without 2 parameters for Scenario and Block.",
85
+ :score => ERROR
86
+ },
87
+ :around_hook_no_block_call => {
88
+ :enabled => true,
89
+ :phrase => "Around hook does not call its block.",
90
+ :score => ERROR
91
+ },
92
+ :hook_no_debugging => {
93
+ :enabled => true,
94
+ :phrase => "Hook without a begin/rescue. Reduced visibility when debugging.",
95
+ :score => ERROR
96
+ },
97
+ :hook_conflicting_tags => {
98
+ :enabled => true,
99
+ :phrase => "Hook that both expects and ignores the same tag. This hook will not function as expected.",
100
+ :score => ERROR
101
+ },
102
+ }
103
+
104
+ warning_rules = {
105
+ :numbers_in_description => {
106
+ :enabled => true,
107
+ :phrase => "{class} has numbers in the description.",
108
+ :score => WARNING
37
109
  },
38
110
  :empty_feature => {
39
111
  :enabled => true,
40
112
  :phrase => "Feature file has no content.",
41
- :score => WARNING,
113
+ :score => WARNING
42
114
  },
43
115
  :background_with_no_scenarios => {
44
116
  :enabled => true,
45
117
  :phrase => "Feature has a background with no scenarios.",
46
- :score => WARNING,
118
+ :score => WARNING
47
119
  },
48
120
  :background_with_one_scenario => {
49
121
  :enabled => true,
50
122
  :phrase => "Feature has a background with one scenario.",
51
- :score => WARNING,
52
- },
53
- :no_scenarios => {
54
- :enabled => true,
55
- :phrase => "Feature with no scenarios.",
56
- :score => ERROR,
57
- },
58
- :too_many_scenarios => {
59
- :enabled => true,
60
- :phrase => "Feature with too many scenarios.",
61
- :score => INFO,
62
- :max => 10,
123
+ :score => WARNING
63
124
  },
64
125
  :too_many_steps => {
65
126
  :enabled => true,
66
- :phrase => "Scenario with too many steps.",
127
+ :phrase => "{class} with too many steps.",
67
128
  :score => WARNING,
68
- :max => 7,
129
+ :max => 7
69
130
  },
70
131
  :out_of_order_steps => {
71
132
  :enabled => true,
72
133
  :phrase => "Scenario steps out of Given/When/Then order.",
73
- :score => WARNING,
134
+ :score => WARNING
74
135
  },
75
136
  :invalid_first_step => {
76
137
  :enabled => true,
77
138
  :phrase => "Invalid first step. Began with And/But.",
78
- :score => WARNING,
139
+ :score => WARNING
79
140
  },
80
141
  :asterisk_step => {
81
142
  :enabled => true,
82
143
  :phrase => "Step includes a * instead of Given/When/Then/And/But.",
83
- :score => WARNING,
144
+ :score => WARNING
84
145
  },
85
- :commented_step => {
146
+ :one_example => {
86
147
  :enabled => true,
87
- :phrase => "Commented step.",
88
- :score => ERROR,
148
+ :phrase => "Scenario Outline with only one example.",
149
+ :score => WARNING
89
150
  },
90
- :commented_example => {
151
+ :too_many_examples => {
91
152
  :enabled => true,
92
- :phrase => "Commented example.",
93
- :score => ERROR,
153
+ :phrase => "Scenario Outline with too many examples.",
154
+ :score => WARNING,
155
+ :max => 10
94
156
  },
95
- :no_examples => {
157
+ :multiple_given_when_then => {
96
158
  :enabled => true,
97
- :phrase => "Scenario Outline with no examples.",
98
- :score => FATAL,
159
+ :phrase => "Given/When/Then used multiple times in the same {class}.",
160
+ :score => WARNING
99
161
  },
100
- :one_example => {
162
+ :too_many_parameters => {
101
163
  :enabled => true,
102
- :phrase => "Scenario Outline with only one example.",
164
+ :phrase => "Too many parameters in Step Definition.",
103
165
  :score => WARNING,
166
+ :max => 4
104
167
  },
105
- :no_examples_table => {
168
+ :lazy_debugging => {
106
169
  :enabled => true,
107
- :phrase => "Scenario Outline with no examples table.",
108
- :score => FATAL,
170
+ :phrase => "Lazy Debugging through puts, p, or print",
171
+ :score => WARNING
109
172
  },
110
- :too_many_examples => {
173
+ :pending => {
111
174
  :enabled => true,
112
- :phrase => "Scenario Outline with too many examples.",
113
- :score => WARNING,
114
- :max => 10
175
+ :phrase => "Pending step definition. Implement or remove.",
176
+ :score => WARNING
115
177
  },
116
- :date_used => {
178
+ :feature_same_tag => {
117
179
  :enabled => true,
118
- :phrase => "Date used.",
119
- :score => INFO,
180
+ :phrase => "Same tag appears on Feature.",
181
+ :score => WARNING
120
182
  },
121
- :no_steps => {
183
+ :scenario_same_tag => {
122
184
  :enabled => true,
123
- :phrase => "No steps in Scenario.",
124
- :score => ERROR,
185
+ :phrase => "Tag appears on all scenarios.",
186
+ :score => WARNING
125
187
  },
126
- :one_word_step => {
188
+ :commas_in_description => {
127
189
  :enabled => true,
128
- :phrase => "Step that is only one word long.",
129
- :score => ERROR,
190
+ :phrase => "There are commas in the description, creating possible multirunning scenarios or features.",
191
+ :score => WARNING
130
192
  },
131
- :multiple_given_when_then => {
193
+ :commented_tag => {
132
194
  :enabled => true,
133
- :phrase => "Given/When/Then used multiple times in the same scenario.",
134
- :score => WARNING,
195
+ :phrase => "{class} has a commented out tag",
196
+ :score => WARNING
135
197
  },
136
- :no_code => {
198
+ :empty_hook => {
137
199
  :enabled => true,
138
- :phrase => "No code in Step Definition.",
139
- :score => ERROR,
200
+ :phrase => "Hook with no content.",
201
+ :score => WARNING
140
202
  },
141
- :too_many_parameters => {
203
+ :hook_all_comments => {
142
204
  :enabled => true,
143
- :phrase => "Too many parameters in Step Definition.",
144
- :score => WARNING,
145
- :max => 4
205
+ :phrase => "Hook is only comments.",
206
+ :score => WARNING
146
207
  },
147
- :nested_step => {
208
+ :hook_duplicate_tags => {
148
209
  :enabled => true,
149
- :phrase => "Nested step call.",
210
+ :phrase => "Hook has duplicate tags.",
211
+ :score => WARNING
212
+ }
213
+ }
214
+
215
+ info_rules = {
216
+ :too_many_tags => {
217
+ :enabled => true,
218
+ :phrase => "{class} has too many tags.",
150
219
  :score => INFO,
220
+ :max => 8
151
221
  },
152
- :recursive_nested_step => {
222
+ :long_name => {
153
223
  :enabled => true,
154
- :phrase => "Recursive nested step call.",
155
- :score => FATAL,
224
+ :phrase => "{class} has a long description.",
225
+ :score => INFO,
226
+ :max => 180
156
227
  },
157
- :commented_code => {
228
+ :implementation_word => {
158
229
  :enabled => true,
159
- :phrase => "Commented code in Step Definition.",
230
+ :phrase => "Implementation word used: {word}.",
160
231
  :score => INFO,
232
+ :words => ["page", "site", "url", "button", "drop down", "dropdown", "select list", "click", "text box", "radio button", "check box", "xml", "window", "pop up", "pop-up", "screen"]
161
233
  },
162
- :lazy_debugging => {
234
+ :too_many_scenarios => {
163
235
  :enabled => true,
164
- :phrase => "Lazy Debugging through puts, p, or print",
165
- :score => WARNING,
236
+ :phrase => "Feature with too many scenarios.",
237
+ :score => INFO,
238
+ :max => 10
166
239
  },
167
- :pending => {
240
+ :date_used => {
168
241
  :enabled => true,
169
- :phrase => "Pending step definition. Implement or remove.",
170
- :score => WARNING,
242
+ :phrase => "Date used.",
243
+ :score => INFO
244
+ },
245
+ :nested_step => {
246
+ :enabled => true,
247
+ :phrase => "Nested step call.",
248
+ :score => INFO
249
+ },
250
+ :commented_code => {
251
+ :enabled => true,
252
+ :phrase => "Commented code in Step Definition.",
253
+ :score => INFO
171
254
  },
172
255
  :small_sleep => {
173
256
  :enabled => true,
@@ -176,17 +259,32 @@ module CukeSniffer
176
259
  :max => 2
177
260
  },
178
261
  :large_sleep => {
179
- :enabled => true,
180
- :phrase => "Large sleeps used. Use a wait_until like method.",
181
- :score => INFO,
182
- :min => 2
262
+ :enabled => true,
263
+ :phrase => "Large sleeps used. Use a wait_until like method.",
264
+ :score => INFO,
265
+ :min => 2
183
266
  },
184
267
  :todo => {
185
268
  :enabled => true,
186
269
  :phrase => "Todo found. Resolve it.",
270
+ :score => INFO
271
+ },
272
+ :hook_not_in_hooks_file => {
273
+ :enabled => true,
274
+ :phrase => "Hook found outside of the designated hooks file",
187
275
  :score => INFO,
276
+ :file => "hooks.rb"
188
277
  },
189
278
  }
190
279
 
280
+ # Master hash used for rule data
281
+ # * +:enabled+
282
+ # * +:phrase+
283
+ # * +:score+
284
+ # Optional:
285
+ # * +:words+
286
+ # * +:max+
287
+ # * +:min+
288
+ RULES = {}.merge fatal_rules.merge error_rules.merge warning_rules.merge info_rules
191
289
  end
192
290
  end
@@ -1,53 +1,70 @@
1
- require 'roxml'
2
- module CukeSniffer
3
- class RulesEvaluator
4
- include ROXML
5
- xml_accessor :score, :location
6
- xml_accessor :rules_hash, :as => {:key => "phrase", :value => "score"}, :in => "rules", :from => "rule"
7
-
8
- def initialize(location)
9
- @location = location
10
- @score = 0
11
- @rules_hash = {}
12
- @class_type = self.class.to_s.gsub(/.*::/, "")
13
- end
14
-
15
- def evaluate_score
16
- end
17
-
18
- def good?
19
- score <= Constants::THRESHOLDS[@class_type]
20
- end
21
-
22
- def problem_percentage
23
- score.to_f / Constants::THRESHOLDS[@class_type].to_f
24
- end
25
-
26
- def store_rule(rule)
27
- if rule[:enabled]
28
- @score += rule[:score]
29
- @rules_hash[rule[:phrase]] ||= 0
30
- @rules_hash[rule[:phrase]] += 1
31
- end
32
- end
33
-
34
- def store_updated_rule(rule, phrase)
35
- store_rule({:enabled => rule[:enabled], :score => rule[:score], :phrase => phrase})
36
- end
37
-
38
-
39
- def is_comment?(line)
40
- if line =~ /^\#.*$/
41
- true
42
- else
43
- false
44
- end
45
- end
46
-
47
- def == (comparison_object)
48
- comparison_object.location == location
49
- comparison_object.score == score
50
- comparison_object.rules_hash == rules_hash
51
- end
52
- end
53
- end
1
+ require 'roxml'
2
+ module CukeSniffer
3
+
4
+ # Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
5
+ # Copyright:: Copyright (C) 2013 Robert Cochran
6
+ # License:: Distributes under the MIT License
7
+ # Parent class for all objects that have rules executed against it
8
+ # Mixins: CukeSniffer::Constants, CukeSniffer::RuleConfig, ROXML
9
+ class RulesEvaluator
10
+ include CukeSniffer::Constants
11
+ include CukeSniffer::RuleConfig
12
+ include ROXML
13
+
14
+ xml_accessor :score, :location
15
+ xml_accessor :rules_hash, :as => {:key => "phrase", :value => "score"}, :in => "rules", :from => "rule"
16
+
17
+ # int: Sum of the rules fired
18
+ attr_accessor :score
19
+
20
+ # string: Location in which the object was found
21
+ attr_accessor :location
22
+
23
+ # hash: Contains the phrase every rule fired against the object and times it fired
24
+ # * Key: string
25
+ # * Value: int
26
+ attr_accessor :rules_hash
27
+
28
+ # Location must be in the format of "file_path\file_name.rb:line_number"
29
+ def initialize(location)
30
+ @location = location
31
+ @score = 0
32
+ @rules_hash = {}
33
+ @class_type = self.class.to_s.gsub(/.*::/, "")
34
+ end
35
+
36
+ # Compares the score against the objects threshold
37
+ # If a score is below the threshold it is good and returns true
38
+ # Return: Boolean
39
+ def good?
40
+ score <= Constants::THRESHOLDS[@class_type]
41
+ end
42
+
43
+ # Calculates the score to threshold percentage of an object
44
+ # Return: Float
45
+ def problem_percentage
46
+ score.to_f / Constants::THRESHOLDS[@class_type].to_f
47
+ end
48
+
49
+ def == (comparison_object) # :nodoc:
50
+ comparison_object.location == location &&
51
+ comparison_object.score == score &&
52
+ comparison_object.rules_hash == rules_hash
53
+ end
54
+
55
+ def store_rule(rule, phrase = rule[:phrase])
56
+ if rule[:enabled]
57
+ @score += rule[:score]
58
+ @rules_hash[phrase] ||= 0
59
+ @rules_hash[phrase] += 1
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ #TODO Abstraction needed for this regex matcher (constants?)
66
+ def is_comment?(line)
67
+ true if line =~ /^\#.*$/
68
+ end
69
+ end
70
+ end