cuke_sniffer 0.0.6 → 0.0.7

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.
@@ -14,7 +14,9 @@ Other Options for Running include:
14
14
  -p, --project <project_root> : Root directory of project.
15
15
  -f, --features <feature_path> : Path to features directory.
16
16
  -s, --step_definitions <step_def_path> : Path to step definitions directory.
17
- -hk, --hooks <hooks_path> : Path to support directory. "
17
+ -hk, --hooks <hooks_path> : Path to support directory.
18
+ -nc, --no_catalog : Disable cataloging of steps. Reduced runtime and no
19
+ "
18
20
 
19
21
  def find_index_by_regex_match(list, regex)
20
22
  list.each do |item|
@@ -29,6 +31,7 @@ def build_cli_hash(argv)
29
31
  :features_location => /-f|--features/,
30
32
  :step_definitions_location => /-s|--step_definitions/,
31
33
  :project_location => /-p|--project/}
34
+
32
35
  cli_hash = {}
33
36
  cucumber_hash.each do |symbol, regex|
34
37
  index_of_key = find_index_by_regex_match(argv, regex)
@@ -36,6 +39,8 @@ def build_cli_hash(argv)
36
39
  cli_hash[symbol] = argv[index_of_key + 1]
37
40
  end
38
41
  end
42
+
43
+ cli_hash[:no_catalog] = true if find_index_by_regex_match(argv, /-nc|--no_catalog/)
39
44
  cli_hash
40
45
  end
41
46
 
@@ -22,6 +22,7 @@ module CukeSniffer
22
22
  xml_accessor :features, :as => [CukeSniffer::Feature], :in => "features"
23
23
  xml_accessor :step_definitions, :as => [CukeSniffer::StepDefinition], :in => "step_definitions"
24
24
  xml_accessor :hooks, :as => [CukeSniffer::Hook], :in => "hooks"
25
+ xml_accessor :cataloged
25
26
 
26
27
 
27
28
  # Feature array: All Features gathered from the specified folder
@@ -53,6 +54,9 @@ module CukeSniffer
53
54
  # Rules hash: All the rules that exist at runtime and their corresponding data
54
55
  attr_accessor :rules
55
56
 
57
+ # Boolean: Status of if the projects step definitions were cataloged for calls
58
+ attr_accessor :cataloged
59
+
56
60
 
57
61
  # Does analysis against the passed features and step definition locations
58
62
  #
@@ -73,6 +77,9 @@ module CukeSniffer
73
77
  # Against folders
74
78
  # cuke_sniffer = CukeSniffer::CLI.new({:features_location =>"my_features_directory\", :step_definitions_location =>"my_steps_directory\"})
75
79
  #
80
+ # Disabling cataloging for improved runtime and no dead steps identified
81
+ # cuke_sniffer = CukeSniffer::CLI.new({:no_catalog => true})
82
+ #
76
83
  # You can mix and match all of the above examples
77
84
  #
78
85
  # Displays the sequence and a . indicator for each new loop in that process.
@@ -82,7 +89,7 @@ module CukeSniffer
82
89
  def initialize(parameters = {})
83
90
  initialize_rule_targets(parameters)
84
91
  evaluate_rules
85
- catalog_step_calls
92
+ catalog_step_calls if @cataloged
86
93
  assess_score
87
94
  end
88
95
 
@@ -155,6 +162,21 @@ module CukeSniffer
155
162
  CukeSniffer::CukeSnifferHelper.catalog_possible_dead_steps(@step_definitions, converted_steps)
156
163
  end
157
164
 
165
+ def assess_score
166
+ puts "\nAssessing Score: "
167
+ initialize_summary
168
+ summarize(:features, @features, "Feature")
169
+ summarize(:scenarios, @scenarios, "Scenario")
170
+ summarize(:step_definitions, @step_definitions, "StepDefinition")
171
+ summarize(:hooks, @hooks, "Hook")
172
+ @summary[:improvement_list] = CukeSniffer::SummaryHelper.sort_improvement_list(@summary[:improvement_list])
173
+ @improvement_list = @summary[:improvement_list]
174
+ end
175
+
176
+ def cataloged?
177
+ @cataloged
178
+ end
179
+
158
180
  private
159
181
 
160
182
  def initialize_rule_targets(parameters)
@@ -166,6 +188,8 @@ module CukeSniffer
166
188
 
167
189
  puts("\nHooks:")
168
190
  @hooks = build_objects_for_extension_from_location(@hooks_location, "rb") { |location| build_hooks(location) }
191
+
192
+ initialize_catalog_status(parameters)
169
193
  end
170
194
 
171
195
  def initialize_locations(parameters)
@@ -180,6 +204,14 @@ module CukeSniffer
180
204
  @scenarios = CukeSniffer::CukeSnifferHelper.get_all_scenarios(@features)
181
205
  end
182
206
 
207
+ def initialize_catalog_status(parameters)
208
+ if parameters[:no_catalog] == true
209
+ @cataloged = false
210
+ else
211
+ @cataloged = true
212
+ end
213
+ end
214
+
183
215
  def evaluate_rules
184
216
  @rules = CukeSniffer::CukeSnifferHelper.build_rules(RULES)
185
217
  CukeSniffer::RulesEvaluator.new(self, @rules)
@@ -192,20 +224,9 @@ module CukeSniffer
192
224
  }
193
225
  end
194
226
 
195
- def assess_score
196
- puts "\nAssessing Score: "
197
- initialize_summary
198
- summarize(:features, @features, "Feature", @features_summary)
199
- summarize(:scenarios, @scenarios, "Scenario", @scenarios_summary)
200
- summarize(:step_definitions, @step_definitions, "StepDefinition", @step_definitions_summary)
201
- summarize(:hooks, @hooks, "Hook", @hooks_summary)
202
- @summary[:improvement_list] = CukeSniffer::SummaryHelper.sort_improvement_list(@summary[:improvement_list])
203
- @improvement_list = @summary[:improvement_list]
204
- end
205
-
206
- def summarize(symbol, list, name, summary_object)
227
+ def summarize(symbol, list, name)
207
228
  @summary[symbol] = CukeSniffer::SummaryHelper.assess_rule_target_list(list, name)
208
- @summary[:total_score] = @summary[symbol][:total_score]
229
+ @summary[:total_score] += @summary[symbol][:total_score]
209
230
  @summary[symbol][:improvement_list].each do |phrase, count|
210
231
  @summary[:improvement_list][phrase] ||= 0
211
232
  @summary[:improvement_list][phrase] += @summary[symbol][:improvement_list][phrase]
@@ -1,165 +1,166 @@
1
- module CukeSniffer
2
- # Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
3
- # Copyright:: Copyright (C) 2013 Robert Cochran
4
- # License:: Distributes under the MIT License
5
- # Static class used for aiding cuke_sniffer in various tasks
6
- class CukeSnifferHelper
7
-
8
- # Iterates over the passed features list and returns all steps found in scenarios and backgrounds.
9
- def self.extract_steps_from_features(features)
10
- steps = {}
11
- features.each do |feature|
12
- steps.merge! extract_scenario_steps(feature.background) unless feature.background.nil?
13
- feature.scenarios.each do |scenario|
14
- if scenario.type == "Scenario Outline"
15
- steps.merge! extract_scenario_outline_steps(scenario)
16
- else
17
- steps.merge! extract_scenario_steps(scenario)
18
- end
19
- end
20
- end
21
- steps
22
- end
23
-
24
- # Iterates over the passed features list and returns all scenarios and backgrounds found.
25
- def self.get_all_scenarios(features)
26
- scenarios = []
27
- features.each do |feature|
28
- scenarios << feature.background unless feature.background.nil?
29
- scenarios << feature.scenarios
30
- end
31
- scenarios.flatten
32
- end
33
-
34
- # Grabs the values from an example without the bars
35
- def self.extract_variables_from_example(example)
36
- example = example[example.index('|')..example.length]
37
- example.split(/\s*\|\s*/) - [""]
38
- end
39
-
40
- # Creates a step call from the details of an example table
41
- def self.build_updated_step_from_example(step, variable_list, row_variables)
42
- new_step = step.dup
43
- variable_list.each do |variable|
44
- if step.include? variable
45
- table_variable_to_insert = row_variables[variable_list.index(variable)]
46
- table_variable_to_insert ||= ""
47
- new_step.gsub!("<#{variable}>", table_variable_to_insert)
48
- end
49
- end
50
- new_step
51
- end
52
-
53
- # Creates a hash of steps with the build up example step calls.
54
- def self.extract_scenario_outline_steps(scenario)
55
- steps = {}
56
- examples = scenario.examples_table
57
- return {} if examples.empty?
58
- variable_list = extract_variables_from_example(examples.first)
59
- (1...examples.size).each do |example_counter|
60
- #TODO Abstraction needed for this regex matcher (constants?)
61
- next if examples[example_counter] =~ /^\#.*$/
62
- row_variables = extract_variables_from_example(examples[example_counter])
63
- step_counter = 1
64
- scenario.steps.each do |step|
65
- step_line = scenario.start_line + step_counter
66
- location = "#{scenario.location.gsub(/\d+$/, step_line.to_s)}(Example #{example_counter})"
67
- steps[location] = build_updated_step_from_example(step, variable_list, row_variables)
68
- step_counter += 1
69
- end
70
- end
71
- steps
72
- end
73
-
74
- # Returns all steps found in a scenario
75
- def self.extract_scenario_steps(scenario)
76
- steps_hash = {}
77
- counter = 1
78
- scenario.steps.each do |step|
79
- location = scenario.location.gsub(/:\d*$/, ":#{scenario.start_line + counter}")
80
- steps_hash[location] = step
81
- counter += 1
82
- end
83
- steps_hash
84
- end
85
-
86
- # Builds a list of rule objects out of a hash. See CukeSniffer::RulesConfig for hash example.
87
- def self.build_rules(rules)
88
- return [] if rules.nil?
89
- rules.collect do |key, value|
90
- CukeSniffer::CukeSnifferHelper.build_rule(value)
91
- end
92
- end
93
-
94
- # Builds rule object out of a hash. See CukeSniffer::RulesConfig for hash example.
95
- def self.build_rule(rule_hash)
96
- rule = CukeSniffer::Rule.new
97
- rule.phrase = rule_hash[:phrase]
98
- rule.score = rule_hash[:score]
99
- rule.enabled = rule_hash[:enabled]
100
- conditional_keys = rule_hash.keys - [:phrase, :score, :enabled, :targets, :reason]
101
- conditions = {}
102
- conditional_keys.each do |key|
103
- conditions[key] = (rule_hash[key].kind_of? Array) ? Array.new(rule_hash[key]) : rule_hash[key]
104
- end
105
- rule.conditions = conditions
106
- rule.reason = rule_hash[:reason]
107
- rule.targets = rule_hash[:targets]
108
- rule
109
- end
110
-
111
- # Returns a list of all nested step calls found in a step definition.
112
- def self.extract_steps_from_step_definitions(step_definitions)
113
- steps = {}
114
- step_definitions.each do |definition|
115
- definition.nested_steps.each_key do |key|
116
- steps[key] = definition.nested_steps[key]
117
- end
118
- end
119
- steps
120
- end
121
-
122
- # Returns a fuzzy match for a step definition for cataloging steps.
123
- def self.convert_steps_with_expressions(steps_with_expressions)
124
- step_regex_hash = {}
125
- steps_with_expressions.each do |step_location, step_value|
126
- modified_step = step_value.gsub(/\#{[^}]*}/, '.*')
127
- step_regex_hash[step_location] = Regexp.new('^' + modified_step + '$')
128
- end
129
- step_regex_hash
130
- end
131
-
132
- # Extracts all possible step calls from the passed features and step definitions.
133
- def self.get_all_steps(features, step_definitions)
134
- feature_steps = CukeSniffer::CukeSnifferHelper.extract_steps_from_features(features)
135
- step_definition_steps = CukeSniffer::CukeSnifferHelper.extract_steps_from_step_definitions(step_definitions)
136
- feature_steps.merge step_definition_steps
137
- end
138
-
139
- # Applies all possible fuzzy calls to a step definition.
140
- def self.catalog_possible_dead_steps(step_definitions, steps_with_expressions)
141
- step_definitions.each do |step_definition|
142
- next unless step_definition.calls.empty?
143
- regex_as_string = step_definition.regex.to_s.gsub(/\(\?-mix:\^?/, "").gsub(/\$\)$/, "")
144
- steps_with_expressions.each do |step_location, step_value|
145
- if regex_as_string =~ step_value
146
- step_definition.add_call(step_location, step_value)
147
- end
148
- end
149
- end
150
- step_definitions
151
- end
152
-
153
- # Returns a list of all step definitions with a capture group
154
- def self.get_steps_with_expressions(steps)
155
- steps_with_expressions = {}
156
- steps.each do |step_location, step_value|
157
- if step_value =~ /\#{.*}/
158
- steps_with_expressions[step_location] = step_value
159
- end
160
- end
161
- steps_with_expressions
162
- end
163
-
164
- end
1
+ module CukeSniffer
2
+ # Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
3
+ # Copyright:: Copyright (C) 2013 Robert Cochran
4
+ # License:: Distributes under the MIT License
5
+ # Static class used for aiding cuke_sniffer in various tasks
6
+ class CukeSnifferHelper
7
+
8
+ # Iterates over the passed features list and returns all steps found in scenarios and backgrounds.
9
+ def self.extract_steps_from_features(features)
10
+ steps = {}
11
+ features.each do |feature|
12
+ steps.merge! extract_scenario_steps(feature.background) unless feature.background.nil?
13
+ feature.scenarios.each do |scenario|
14
+ if scenario.type == "Scenario Outline"
15
+ steps.merge! extract_scenario_outline_steps(scenario)
16
+ else
17
+ steps.merge! extract_scenario_steps(scenario)
18
+ end
19
+ end
20
+ end
21
+ steps
22
+ end
23
+
24
+ # Iterates over the passed features list and returns all scenarios and backgrounds found.
25
+ def self.get_all_scenarios(features)
26
+ scenarios = []
27
+ features.each do |feature|
28
+ scenarios << feature.background unless feature.background.nil?
29
+ scenarios << feature.scenarios
30
+ end
31
+ scenarios.flatten
32
+ end
33
+
34
+ # Grabs the values from an example without the bars
35
+ def self.extract_variables_from_example(example)
36
+ example = example[example.index('|')..example.length]
37
+ example.split(/\s*\|\s*/) - [""]
38
+ end
39
+
40
+ # Creates a step call from the details of an example table
41
+ def self.build_updated_step_from_example(step, variable_list, row_variables)
42
+ new_step = step.dup
43
+ variable_list.each do |variable|
44
+ if step.include? variable
45
+ table_variable_to_insert = row_variables[variable_list.index(variable)]
46
+ table_variable_to_insert ||= ""
47
+ new_step.gsub!("<#{variable}>", table_variable_to_insert)
48
+ end
49
+ end
50
+ new_step
51
+ end
52
+
53
+ # Creates a hash of steps with the build up example step calls.
54
+ def self.extract_scenario_outline_steps(scenario)
55
+ steps = {}
56
+ examples = scenario.examples_table
57
+ return {} if examples.empty?
58
+ variable_list = extract_variables_from_example(examples.first)
59
+ (1...examples.size).each do |example_counter|
60
+ #TODO Abstraction needed for this regex matcher (constants?)
61
+ next if examples[example_counter] =~ /^\#.*$/
62
+ row_variables = extract_variables_from_example(examples[example_counter])
63
+ step_counter = 1
64
+ scenario.steps.each do |step|
65
+ step_line = scenario.start_line + step_counter
66
+ location = "#{scenario.location.gsub(/\d+$/, step_line.to_s)}(Example #{example_counter})"
67
+ steps[location] = build_updated_step_from_example(step, variable_list, row_variables)
68
+ step_counter += 1
69
+ end
70
+ end
71
+ steps
72
+ end
73
+
74
+ # Returns all steps found in a scenario
75
+ def self.extract_scenario_steps(scenario)
76
+ steps_hash = {}
77
+ counter = 1
78
+ scenario.steps.each do |step|
79
+ location = scenario.location.gsub(/:\d*$/, ":#{scenario.start_line + counter}")
80
+ steps_hash[location] = step
81
+ counter += 1
82
+ end
83
+ steps_hash
84
+ end
85
+
86
+ # Builds a list of rule objects out of a hash. See CukeSniffer::RulesConfig for hash example.
87
+ def self.build_rules(rules)
88
+ return [] if rules.nil?
89
+ rules.collect do |key, value|
90
+ CukeSniffer::CukeSnifferHelper.build_rule(value)
91
+ end
92
+ end
93
+
94
+ # Builds rule object out of a hash. See CukeSniffer::RulesConfig for hash example.
95
+ def self.build_rule(rule_hash)
96
+ rule = CukeSniffer::Rule.new
97
+ rule.phrase = rule_hash[:phrase]
98
+ rule.score = rule_hash[:score]
99
+ rule.enabled = rule_hash[:enabled]
100
+ conditional_keys = rule_hash.keys - [:phrase, :score, :enabled, :targets, :reason]
101
+ conditions = {}
102
+ conditional_keys.each do |key|
103
+ conditions[key] = (rule_hash[key].kind_of? Array) ? Array.new(rule_hash[key]) : rule_hash[key]
104
+ end
105
+ rule.conditions = conditions
106
+ rule.reason = rule_hash[:reason]
107
+ rule.targets = rule_hash[:targets]
108
+ rule
109
+ end
110
+
111
+ # Returns a list of all nested step calls found in a step definition.
112
+ def self.extract_steps_from_step_definitions(step_definitions)
113
+ steps = {}
114
+ step_definitions.each do |definition|
115
+ definition.nested_steps.each do |location, step|
116
+ steps[location] = step
117
+ end
118
+ end
119
+ steps
120
+ end
121
+
122
+ # Returns a fuzzy match for a step definition for cataloging steps.
123
+ def self.convert_steps_with_expressions(steps_with_expressions)
124
+ step_regex_hash = {}
125
+ steps_with_expressions.each do |step_location, step_value|
126
+ modified_step = step_value.gsub(/\#{[^}]*}/, '.*')
127
+ next if modified_step == '.*'
128
+ step_regex_hash[step_location] = Regexp.new('^' + modified_step + '$')
129
+ end
130
+ step_regex_hash
131
+ end
132
+
133
+ # Extracts all possible step calls from the passed features and step definitions.
134
+ def self.get_all_steps(features, step_definitions)
135
+ feature_steps = CukeSniffer::CukeSnifferHelper.extract_steps_from_features(features)
136
+ step_definition_steps = CukeSniffer::CukeSnifferHelper.extract_steps_from_step_definitions(step_definitions)
137
+ feature_steps.merge step_definition_steps
138
+ end
139
+
140
+ # Applies all possible fuzzy calls to a step definition.
141
+ def self.catalog_possible_dead_steps(step_definitions, steps_with_expressions)
142
+ step_definitions.each do |step_definition|
143
+ next unless step_definition.calls.empty?
144
+ regex_as_string = step_definition.regex.to_s.gsub(/\(\?-mix:\^?/, "").gsub(/\$\)$/, "")
145
+ steps_with_expressions.each do |step_location, step_value|
146
+ if regex_as_string =~ step_value
147
+ step_definition.add_call(step_location, step_value)
148
+ end
149
+ end
150
+ end
151
+ step_definitions
152
+ end
153
+
154
+ # Returns a list of all step definitions with a capture group
155
+ def self.get_steps_with_expressions(steps)
156
+ steps_with_expressions = {}
157
+ steps.each do |step_location, step_value|
158
+ if step_value =~ /\#{.*}/
159
+ steps_with_expressions[step_location] = step_value
160
+ end
161
+ end
162
+ steps_with_expressions
163
+ end
164
+
165
+ end
165
166
  end