cuke_sniffer 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cuke_sniffer.rb +8 -23
- data/lib/cuke_sniffer/cli.rb +38 -5
- data/lib/cuke_sniffer/constants.rb +1 -1
- data/lib/cuke_sniffer/cuke_sniffer_helper.rb +1 -1
- data/lib/cuke_sniffer/dead_steps_helper.rb +1 -1
- data/lib/cuke_sniffer/feature.rb +109 -104
- data/lib/cuke_sniffer/feature_rules_evaluator.rb +55 -56
- data/lib/cuke_sniffer/formatter.rb +1 -1
- data/lib/cuke_sniffer/hook.rb +103 -77
- data/lib/cuke_sniffer/report/rules.html.erb +0 -5
- data/lib/cuke_sniffer/rule.rb +26 -27
- data/lib/cuke_sniffer/rule_config.rb +114 -128
- data/lib/cuke_sniffer/rule_target.rb +78 -62
- data/lib/cuke_sniffer/rules_evaluator.rb +52 -64
- data/lib/cuke_sniffer/scenario.rb +123 -102
- data/lib/cuke_sniffer/step_definition.rb +176 -163
- data/lib/cuke_sniffer/summary_helper.rb +1 -1
- data/lib/cuke_sniffer/summary_node.rb +17 -18
- metadata +2 -2
@@ -1,62 +1,78 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
include
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
#
|
21
|
-
attr_accessor :
|
22
|
-
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
# Return:
|
45
|
-
def
|
46
|
-
score
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
1
|
+
require 'cuke_sniffer/constants'
|
2
|
+
require 'cuke_sniffer/rule_config'
|
3
|
+
|
4
|
+
module CukeSniffer
|
5
|
+
|
6
|
+
# Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
|
7
|
+
# Copyright:: Copyright (C) 2014 Robert Cochran
|
8
|
+
# License:: Distributes under the MIT License
|
9
|
+
# Parent class for all objects that have rules executed against it
|
10
|
+
# Mixins: CukeSniffer::Constants, CukeSniffer::RuleConfig, ROXML
|
11
|
+
class RuleTarget
|
12
|
+
include CukeSniffer::Constants
|
13
|
+
include CukeSniffer::RuleConfig
|
14
|
+
include ROXML
|
15
|
+
|
16
|
+
xml_accessor :score, :location
|
17
|
+
xml_accessor :rules_hash, :as => {:key => "phrase", :value => "score"}, :in => "rules", :from => "rule"
|
18
|
+
xml_accessor :type
|
19
|
+
|
20
|
+
# int: Sum of the rules fired
|
21
|
+
attr_accessor :score
|
22
|
+
|
23
|
+
# string: Location in which the object was found
|
24
|
+
attr_accessor :location
|
25
|
+
|
26
|
+
# hash: Contains the phrase every rule fired against the object and times it fired
|
27
|
+
# * Key: string
|
28
|
+
# * Value: int
|
29
|
+
attr_accessor :rules_hash
|
30
|
+
|
31
|
+
# string: Type of the object being evaluated
|
32
|
+
attr_accessor :type
|
33
|
+
|
34
|
+
# Location must be in the format of "file_path\file_name.rb:line_number"
|
35
|
+
def initialize(location)
|
36
|
+
@location = location
|
37
|
+
@score = 0
|
38
|
+
@rules_hash = {}
|
39
|
+
@class_type = self.class.to_s.gsub(/.*::/, "")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Compares the score against the objects threshold
|
43
|
+
# If a score is below the threshold it is good and returns true
|
44
|
+
# Return: Boolean
|
45
|
+
def good?
|
46
|
+
score <= Constants::THRESHOLDS[@class_type]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Calculates the score to threshold percentage of an object
|
50
|
+
# Return: Float
|
51
|
+
def problem_percentage
|
52
|
+
score.to_f / Constants::THRESHOLDS[@class_type].to_f
|
53
|
+
end
|
54
|
+
|
55
|
+
def == (comparison_object) # :nodoc:
|
56
|
+
comparison_object.location == location &&
|
57
|
+
comparison_object.score == score &&
|
58
|
+
comparison_object.rules_hash == rules_hash
|
59
|
+
end
|
60
|
+
|
61
|
+
#TODO Abstraction needed for this regex matcher (constants?)
|
62
|
+
def is_comment?(line)
|
63
|
+
true if line =~ /^\#.*$/
|
64
|
+
end
|
65
|
+
|
66
|
+
def store_rule(rule, phrase = rule.phrase)
|
67
|
+
@score += rule.score
|
68
|
+
@rules_hash[phrase] ||= 0
|
69
|
+
@rules_hash[phrase] += 1
|
70
|
+
end
|
71
|
+
|
72
|
+
def store_rule_many_times(rule, count, phrase = rule.phrase)
|
73
|
+
count.times do
|
74
|
+
store_rule(rule, phrase)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,65 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
def store_rule(object, rule, phrase = rule.phrase)
|
56
|
-
object.score += rule.score
|
57
|
-
object.rules_hash[phrase] ||= 0
|
58
|
-
object.rules_hash[phrase] += 1
|
59
|
-
end
|
60
|
-
|
61
|
-
def is_comment?(line)
|
62
|
-
true if line =~ /^\#.*$/
|
63
|
-
end
|
64
|
-
end
|
1
|
+
module CukeSniffer
|
2
|
+
|
3
|
+
# Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
|
4
|
+
# Copyright:: Copyright (C) 2014 Robert Cochran
|
5
|
+
# License:: Distributes under the MIT License
|
6
|
+
# Evaluates all cucumber components found in CukeSniffer with the passed rules
|
7
|
+
class RulesEvaluator
|
8
|
+
include CukeSniffer::Constants
|
9
|
+
attr_accessor :rules
|
10
|
+
|
11
|
+
def initialize(cli, rules)
|
12
|
+
raise "A CLI must be provided for evaluation." if cli.nil?
|
13
|
+
raise "Rules must be provided for evaluation." if rules.nil? or rules.empty?
|
14
|
+
@rules = rules
|
15
|
+
judge_features(cli.features)
|
16
|
+
judge_objects(cli.step_definitions, "StepDefinition")
|
17
|
+
judge_objects(cli.hooks, "Hook")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def judge_features(features)
|
23
|
+
features.each do |feature|
|
24
|
+
judge_feature(feature)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def judge_feature(feature)
|
29
|
+
judge_object(feature, "Feature")
|
30
|
+
judge_object(feature.background, "Background") unless feature.background.nil?
|
31
|
+
judge_objects(feature.scenarios, "Scenario")
|
32
|
+
feature.total_score += feature.update_score
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def judge_objects(objects, type)
|
37
|
+
objects.each do | object |
|
38
|
+
judge_object(object, type)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def judge_object(object, type)
|
43
|
+
@rules.each do |rule|
|
44
|
+
fail "No targets for rule: #{rule.phrase}" if rule.targets.nil? or rule.targets.empty?
|
45
|
+
next unless rule.targets.include? type and rule.enabled
|
46
|
+
if rule.reason.(object, rule) == true
|
47
|
+
phrase = rule.phrase.gsub("{class}", type)
|
48
|
+
object.store_rule(rule, phrase)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
65
53
|
end
|
@@ -1,102 +1,123 @@
|
|
1
|
-
module CukeSniffer
|
2
|
-
|
3
|
-
# Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
|
4
|
-
# Copyright:: Copyright (C)
|
5
|
-
# License:: Distributes under the MIT License
|
6
|
-
# This class is a representation of the cucumber objects
|
7
|
-
# Background, Scenario, Scenario Outline
|
8
|
-
#
|
9
|
-
# Extends CukeSniffer::FeatureRulesEvaluator
|
10
|
-
class Scenario < FeatureRuleTarget
|
11
|
-
|
12
|
-
xml_accessor :start_line
|
13
|
-
xml_accessor :steps, :as => [], :in => "steps"
|
14
|
-
xml_accessor :examples_table, :as => [], :in => "examples"
|
15
|
-
|
16
|
-
# int: Line on which the scenario begins
|
17
|
-
attr_accessor :start_line
|
18
|
-
|
19
|
-
# string: The type of scenario
|
20
|
-
# Background, Scenario, Scenario Outline
|
21
|
-
attr_accessor :type
|
22
|
-
|
23
|
-
# string array: List of each step call in a scenario
|
24
|
-
attr_accessor :steps
|
25
|
-
|
26
|
-
# hash: Keeps each location and content of an inline table
|
27
|
-
# * Key: Step string the inline table is attached to
|
28
|
-
# * Value: Array of all of the lines in the table
|
29
|
-
attr_accessor :inline_tables
|
30
|
-
|
31
|
-
# string array: List of each example row in a scenario outline
|
32
|
-
attr_accessor :examples_table
|
33
|
-
|
34
|
-
# Location must be in the format of "file_path\file_name.rb:line_number"
|
35
|
-
# Scenario must be a string array containing everything from the first tag to the last example table
|
36
|
-
# where applicable.
|
37
|
-
def initialize(location, scenario)
|
38
|
-
super(location)
|
39
|
-
@start_line = location.match(/:(?<line>\d*)$/)[:line].to_i
|
40
|
-
@steps = []
|
41
|
-
@inline_tables = {}
|
42
|
-
@examples_table = []
|
43
|
-
split_scenario(scenario)
|
44
|
-
end
|
45
|
-
|
46
|
-
def ==(comparison_object) # :nodoc:
|
47
|
-
super(comparison_object) &&
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
def get_step_order
|
53
|
-
order = []
|
54
|
-
@steps.each do |line|
|
55
|
-
next if is_comment?(line)
|
56
|
-
match = line.match(STEP_REGEX)
|
57
|
-
order << match[:style] unless match.nil?
|
58
|
-
end
|
59
|
-
order
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
1
|
+
module CukeSniffer
|
2
|
+
|
3
|
+
# Author:: Robert Cochran (mailto:cochrarj@miamioh.edu)
|
4
|
+
# Copyright:: Copyright (C) 2014 Robert Cochran
|
5
|
+
# License:: Distributes under the MIT License
|
6
|
+
# This class is a representation of the cucumber objects
|
7
|
+
# Background, Scenario, Scenario Outline
|
8
|
+
#
|
9
|
+
# Extends CukeSniffer::FeatureRulesEvaluator
|
10
|
+
class Scenario < FeatureRuleTarget
|
11
|
+
|
12
|
+
xml_accessor :start_line
|
13
|
+
xml_accessor :steps, :as => [], :in => "steps"
|
14
|
+
xml_accessor :examples_table, :as => [], :in => "examples"
|
15
|
+
|
16
|
+
# int: Line on which the scenario begins
|
17
|
+
attr_accessor :start_line
|
18
|
+
|
19
|
+
# string: The type of scenario
|
20
|
+
# Background, Scenario, Scenario Outline
|
21
|
+
attr_accessor :type
|
22
|
+
|
23
|
+
# string array: List of each step call in a scenario
|
24
|
+
attr_accessor :steps
|
25
|
+
|
26
|
+
# hash: Keeps each location and content of an inline table
|
27
|
+
# * Key: Step string the inline table is attached to
|
28
|
+
# * Value: Array of all of the lines in the table
|
29
|
+
attr_accessor :inline_tables
|
30
|
+
|
31
|
+
# string array: List of each example row in a scenario outline
|
32
|
+
attr_accessor :examples_table
|
33
|
+
|
34
|
+
# Location must be in the format of "file_path\file_name.rb:line_number"
|
35
|
+
# Scenario must be a string array containing everything from the first tag to the last example table
|
36
|
+
# where applicable.
|
37
|
+
def initialize(location, scenario)
|
38
|
+
super(location)
|
39
|
+
@start_line = location.match(/:(?<line>\d*)$/)[:line].to_i
|
40
|
+
@steps = []
|
41
|
+
@inline_tables = {}
|
42
|
+
@examples_table = []
|
43
|
+
split_scenario(scenario)
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(comparison_object) # :nodoc:
|
47
|
+
super(comparison_object) &&
|
48
|
+
comparison_object.steps == steps &&
|
49
|
+
comparison_object.examples_table == examples_table
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_step_order
|
53
|
+
order = []
|
54
|
+
@steps.each do |line|
|
55
|
+
next if is_comment?(line)
|
56
|
+
match = line.match(STEP_REGEX)
|
57
|
+
order << match[:style] unless match.nil?
|
58
|
+
end
|
59
|
+
order
|
60
|
+
end
|
61
|
+
|
62
|
+
def outline?
|
63
|
+
type === 'Scenario Outline'
|
64
|
+
end
|
65
|
+
|
66
|
+
def commented_examples
|
67
|
+
@examples_table.select do |example|
|
68
|
+
is_comment?(example)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_steps(step_start)
|
73
|
+
if step_start != "*"
|
74
|
+
regex = /^\s*#{step_start}/
|
75
|
+
else
|
76
|
+
regex = /^\s*[*]/
|
77
|
+
end
|
78
|
+
@steps.select do |step|
|
79
|
+
step =~ regex
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def split_scenario(scenario)
|
86
|
+
index = 0
|
87
|
+
until index >= scenario.length or scenario[index] =~ SCENARIO_TITLE_STYLES
|
88
|
+
update_tag_list(scenario[index])
|
89
|
+
index += 1
|
90
|
+
end
|
91
|
+
|
92
|
+
until index >= scenario.length or scenario[index].match STEP_REGEX or scenario[index].include?("Examples:")
|
93
|
+
match = scenario[index].match(SCENARIO_TITLE_STYLES)
|
94
|
+
@type = match[:type] unless match.nil?
|
95
|
+
create_name(scenario[index], SCENARIO_TITLE_STYLES)
|
96
|
+
index += 1
|
97
|
+
end
|
98
|
+
|
99
|
+
until index >= scenario.length or scenario[index].include?("Examples:")
|
100
|
+
if scenario[index] =~ /^\|.*\|/
|
101
|
+
step = scenario[index - 1]
|
102
|
+
@inline_tables[step] = []
|
103
|
+
until index >= scenario.length or scenario[index] =~ /(#{STEP_REGEX}|^\s*Examples:)/
|
104
|
+
@inline_tables[step] << scenario[index]
|
105
|
+
index += 1
|
106
|
+
end
|
107
|
+
else
|
108
|
+
@steps << scenario[index] if scenario[index] =~ STEP_REGEX
|
109
|
+
index += 1
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if index < scenario.length and scenario[index].include?("Examples:")
|
114
|
+
index += 1
|
115
|
+
until index >= scenario.length
|
116
|
+
index += 2 if scenario[index].include?("Examples:")
|
117
|
+
@examples_table << scenario[index] if scenario[index] =~ /#{COMMENT_REGEX}\|.*\|/
|
118
|
+
index += 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|