cuke_sniffer 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cuke_sniffer.rb +51 -34
- data/lib/cuke_sniffer.rb +13 -13
- data/lib/cuke_sniffer/cli.rb +246 -226
- data/lib/cuke_sniffer/constants.rb +22 -35
- data/lib/cuke_sniffer/feature.rb +107 -116
- data/lib/cuke_sniffer/report/markup.rhtml +385 -310
- data/lib/cuke_sniffer/rule_config.rb +161 -161
- data/lib/cuke_sniffer/rules_evaluator.rb +50 -41
- data/lib/cuke_sniffer/scenario.rb +164 -163
- data/lib/cuke_sniffer/step_definition.rb +143 -116
- metadata +10 -4
@@ -1,161 +1,161 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module CukeSniffer
|
4
|
-
module RuleConfig
|
5
|
-
|
6
|
-
FATAL = 100 #will prevent suite from executing properly
|
7
|
-
ERROR = 25 #will cause problem with debugging
|
8
|
-
WARNING = 10
|
9
|
-
INFO = 1
|
10
|
-
|
11
|
-
SHARED_RULES = {
|
12
|
-
:too_many_tags => {
|
13
|
-
:enabled => true,
|
14
|
-
:phrase => "{class} has too many tags.",
|
15
|
-
:score => INFO,
|
16
|
-
:max => 8
|
17
|
-
},
|
18
|
-
:no_description => {
|
19
|
-
:enabled => true,
|
20
|
-
:phrase => "{class} has no description.",
|
21
|
-
:score => ERROR,
|
22
|
-
},
|
23
|
-
:numbers_in_description => {
|
24
|
-
:enabled => true,
|
25
|
-
:phrase => "{class} has numbers in the description.",
|
26
|
-
:score => WARNING,
|
27
|
-
},
|
28
|
-
:long_name => {
|
29
|
-
:enabled => true,
|
30
|
-
:phrase => "{class} has a long description.",
|
31
|
-
:score => INFO,
|
32
|
-
:max => 180
|
33
|
-
},
|
34
|
-
:implementation_word => {
|
35
|
-
:enabled => true,
|
36
|
-
:phrase => "Implementation word used: {word}.",
|
37
|
-
:score => INFO,
|
38
|
-
:words => ["page", "site", "url", "button", "drop down", "dropdown", "select list", "click", "text box", "radio button", "check box", "xml", "window", "pop up", "pop-up", "screen"]
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
|
-
FEATURE_RULES = {
|
43
|
-
:background_with_no_scenarios => {
|
44
|
-
:enabled => true,
|
45
|
-
:phrase => "Feature has a background with no scenarios.",
|
46
|
-
:score => WARNING,
|
47
|
-
},
|
48
|
-
:background_with_one_scenario => {
|
49
|
-
:enabled => true,
|
50
|
-
: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,
|
63
|
-
},
|
64
|
-
}
|
65
|
-
|
66
|
-
SCENARIO_RULES = {
|
67
|
-
:too_many_steps => {
|
68
|
-
:enabled => true,
|
69
|
-
:phrase => "Scenario with too many steps.",
|
70
|
-
:score => WARNING,
|
71
|
-
:max => 7,
|
72
|
-
},
|
73
|
-
:out_of_order_steps => {
|
74
|
-
:enabled => true,
|
75
|
-
:phrase => "Scenario steps out of Given/When/Then order.",
|
76
|
-
:score => WARNING,
|
77
|
-
},
|
78
|
-
:invalid_first_step => {
|
79
|
-
:enabled => true,
|
80
|
-
:phrase => "Invalid first step. Began with And/But.",
|
81
|
-
:score => WARNING,
|
82
|
-
},
|
83
|
-
:asterisk_step => {
|
84
|
-
:enabled => true,
|
85
|
-
:phrase => "Step includes a * instead of Given/When/Then/And/But.",
|
86
|
-
:score => WARNING,
|
87
|
-
},
|
88
|
-
:commented_step => {
|
89
|
-
:enabled => true,
|
90
|
-
:phrase => "Commented step.",
|
91
|
-
:score => ERROR,
|
92
|
-
},
|
93
|
-
:commented_example => {
|
94
|
-
:enabled => true,
|
95
|
-
:phrase => "Commented example.",
|
96
|
-
:score => ERROR,
|
97
|
-
},
|
98
|
-
:no_examples => {
|
99
|
-
:enabled => true,
|
100
|
-
:phrase => "Scenario Outline with no examples.",
|
101
|
-
:score => FATAL,
|
102
|
-
},
|
103
|
-
:one_example => {
|
104
|
-
:enabled => true,
|
105
|
-
:phrase => "Scenario Outline with only one example.",
|
106
|
-
:score => WARNING,
|
107
|
-
},
|
108
|
-
:no_examples_table => {
|
109
|
-
:enabled => true,
|
110
|
-
:phrase => "Scenario Outline with no examples table.",
|
111
|
-
:score => FATAL,
|
112
|
-
},
|
113
|
-
:too_many_examples => {
|
114
|
-
:enabled => true,
|
115
|
-
:phrase => "Scenario Outline with too many examples.",
|
116
|
-
:score => WARNING,
|
117
|
-
:max => 10
|
118
|
-
},
|
119
|
-
:date_used => {
|
120
|
-
:enabled => true,
|
121
|
-
:phrase => "Date used.",
|
122
|
-
:score => INFO,
|
123
|
-
},
|
124
|
-
:no_steps => {
|
125
|
-
:enabled => true,
|
126
|
-
:phrase => "No steps in Scenario.",
|
127
|
-
:score => ERROR,
|
128
|
-
},
|
129
|
-
}
|
130
|
-
|
131
|
-
STEP_DEFINITION_RULES = {
|
132
|
-
:no_code => {
|
133
|
-
:enabled => true,
|
134
|
-
:phrase => "No code in Step Definition.",
|
135
|
-
:score => ERROR,
|
136
|
-
},
|
137
|
-
:too_many_parameters => {
|
138
|
-
:enabled => true,
|
139
|
-
:phrase => "Too many parameters in Step Definition.",
|
140
|
-
:score => WARNING,
|
141
|
-
:max => 4
|
142
|
-
},
|
143
|
-
:nested_step => {
|
144
|
-
:enabled => true,
|
145
|
-
:phrase => "Nested step call.",
|
146
|
-
:score => INFO,
|
147
|
-
},
|
148
|
-
:recursive_nested_step => {
|
149
|
-
:enabled => true,
|
150
|
-
:phrase => "Recursive nested step call.",
|
151
|
-
:score => FATAL,
|
152
|
-
},
|
153
|
-
:commented_code => {
|
154
|
-
:enabled => true,
|
155
|
-
:phrase => "Commented code in Step Definition.",
|
156
|
-
:score => INFO,
|
157
|
-
},
|
158
|
-
}
|
159
|
-
|
160
|
-
end
|
161
|
-
end
|
1
|
+
|
2
|
+
|
3
|
+
module CukeSniffer
|
4
|
+
module RuleConfig
|
5
|
+
|
6
|
+
FATAL = 100 #will prevent suite from executing properly
|
7
|
+
ERROR = 25 #will cause problem with debugging
|
8
|
+
WARNING = 10 #readibility/misuse of cucumber
|
9
|
+
INFO = 1 #Small improvements that can be made
|
10
|
+
|
11
|
+
SHARED_RULES = {
|
12
|
+
:too_many_tags => {
|
13
|
+
:enabled => true,
|
14
|
+
:phrase => "{class} has too many tags.",
|
15
|
+
:score => INFO,
|
16
|
+
:max => 8
|
17
|
+
},
|
18
|
+
:no_description => {
|
19
|
+
:enabled => true,
|
20
|
+
:phrase => "{class} has no description.",
|
21
|
+
:score => ERROR,
|
22
|
+
},
|
23
|
+
:numbers_in_description => {
|
24
|
+
:enabled => true,
|
25
|
+
:phrase => "{class} has numbers in the description.",
|
26
|
+
:score => WARNING,
|
27
|
+
},
|
28
|
+
:long_name => {
|
29
|
+
:enabled => true,
|
30
|
+
:phrase => "{class} has a long description.",
|
31
|
+
:score => INFO,
|
32
|
+
:max => 180
|
33
|
+
},
|
34
|
+
:implementation_word => {
|
35
|
+
:enabled => true,
|
36
|
+
:phrase => "Implementation word used: {word}.",
|
37
|
+
:score => INFO,
|
38
|
+
:words => ["page", "site", "url", "button", "drop down", "dropdown", "select list", "click", "text box", "radio button", "check box", "xml", "window", "pop up", "pop-up", "screen"]
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
FEATURE_RULES = {
|
43
|
+
:background_with_no_scenarios => {
|
44
|
+
:enabled => true,
|
45
|
+
:phrase => "Feature has a background with no scenarios.",
|
46
|
+
:score => WARNING,
|
47
|
+
},
|
48
|
+
:background_with_one_scenario => {
|
49
|
+
:enabled => true,
|
50
|
+
: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,
|
63
|
+
},
|
64
|
+
}
|
65
|
+
|
66
|
+
SCENARIO_RULES = {
|
67
|
+
:too_many_steps => {
|
68
|
+
:enabled => true,
|
69
|
+
:phrase => "Scenario with too many steps.",
|
70
|
+
:score => WARNING,
|
71
|
+
:max => 7,
|
72
|
+
},
|
73
|
+
:out_of_order_steps => {
|
74
|
+
:enabled => true,
|
75
|
+
:phrase => "Scenario steps out of Given/When/Then order.",
|
76
|
+
:score => WARNING,
|
77
|
+
},
|
78
|
+
:invalid_first_step => {
|
79
|
+
:enabled => true,
|
80
|
+
:phrase => "Invalid first step. Began with And/But.",
|
81
|
+
:score => WARNING,
|
82
|
+
},
|
83
|
+
:asterisk_step => {
|
84
|
+
:enabled => true,
|
85
|
+
:phrase => "Step includes a * instead of Given/When/Then/And/But.",
|
86
|
+
:score => WARNING,
|
87
|
+
},
|
88
|
+
:commented_step => {
|
89
|
+
:enabled => true,
|
90
|
+
:phrase => "Commented step.",
|
91
|
+
:score => ERROR,
|
92
|
+
},
|
93
|
+
:commented_example => {
|
94
|
+
:enabled => true,
|
95
|
+
:phrase => "Commented example.",
|
96
|
+
:score => ERROR,
|
97
|
+
},
|
98
|
+
:no_examples => {
|
99
|
+
:enabled => true,
|
100
|
+
:phrase => "Scenario Outline with no examples.",
|
101
|
+
:score => FATAL,
|
102
|
+
},
|
103
|
+
:one_example => {
|
104
|
+
:enabled => true,
|
105
|
+
:phrase => "Scenario Outline with only one example.",
|
106
|
+
:score => WARNING,
|
107
|
+
},
|
108
|
+
:no_examples_table => {
|
109
|
+
:enabled => true,
|
110
|
+
:phrase => "Scenario Outline with no examples table.",
|
111
|
+
:score => FATAL,
|
112
|
+
},
|
113
|
+
:too_many_examples => {
|
114
|
+
:enabled => true,
|
115
|
+
:phrase => "Scenario Outline with too many examples.",
|
116
|
+
:score => WARNING,
|
117
|
+
:max => 10
|
118
|
+
},
|
119
|
+
:date_used => {
|
120
|
+
:enabled => true,
|
121
|
+
:phrase => "Date used.",
|
122
|
+
:score => INFO,
|
123
|
+
},
|
124
|
+
:no_steps => {
|
125
|
+
:enabled => true,
|
126
|
+
:phrase => "No steps in Scenario.",
|
127
|
+
:score => ERROR,
|
128
|
+
},
|
129
|
+
}
|
130
|
+
|
131
|
+
STEP_DEFINITION_RULES = {
|
132
|
+
:no_code => {
|
133
|
+
:enabled => true,
|
134
|
+
:phrase => "No code in Step Definition.",
|
135
|
+
:score => ERROR,
|
136
|
+
},
|
137
|
+
:too_many_parameters => {
|
138
|
+
:enabled => true,
|
139
|
+
:phrase => "Too many parameters in Step Definition.",
|
140
|
+
:score => WARNING,
|
141
|
+
:max => 4
|
142
|
+
},
|
143
|
+
:nested_step => {
|
144
|
+
:enabled => true,
|
145
|
+
:phrase => "Nested step call.",
|
146
|
+
:score => INFO,
|
147
|
+
},
|
148
|
+
:recursive_nested_step => {
|
149
|
+
:enabled => true,
|
150
|
+
:phrase => "Recursive nested step call.",
|
151
|
+
:score => FATAL,
|
152
|
+
},
|
153
|
+
:commented_code => {
|
154
|
+
:enabled => true,
|
155
|
+
:phrase => "Commented code in Step Definition.",
|
156
|
+
:score => INFO,
|
157
|
+
},
|
158
|
+
}
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
@@ -1,41 +1,50 @@
|
|
1
|
-
module CukeSniffer
|
2
|
-
class RulesEvaluator
|
3
|
-
attr_accessor :location, :score, :rules_hash
|
4
|
-
|
5
|
-
def initialize(location)
|
6
|
-
@location = location
|
7
|
-
@score = 0
|
8
|
-
@rules_hash = {}
|
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
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
1
|
+
module CukeSniffer
|
2
|
+
class RulesEvaluator
|
3
|
+
attr_accessor :location, :score, :rules_hash
|
4
|
+
|
5
|
+
def initialize(location)
|
6
|
+
@location = location
|
7
|
+
@score = 0
|
8
|
+
@rules_hash = {}
|
9
|
+
@class_type = self.class.to_s.gsub(/.*::/, "")
|
10
|
+
end
|
11
|
+
|
12
|
+
def evaluate_score
|
13
|
+
end
|
14
|
+
|
15
|
+
def good?
|
16
|
+
score <= Constants::THRESHOLDS[@class_type]
|
17
|
+
end
|
18
|
+
|
19
|
+
def problem_percentage
|
20
|
+
score.to_f / Constants::THRESHOLDS[@class_type].to_f
|
21
|
+
end
|
22
|
+
|
23
|
+
def store_rule(rule)
|
24
|
+
if rule[:enabled]
|
25
|
+
@score += rule[:score]
|
26
|
+
@rules_hash[rule[:phrase]] ||= 0
|
27
|
+
@rules_hash[rule[:phrase]] += 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def store_updated_rule(rule, phrase)
|
32
|
+
store_rule({:enabled => rule[:enabled], :score => rule[:score], :phrase => phrase})
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def is_comment?(line)
|
37
|
+
if line =~ /^\#.*$/
|
38
|
+
true
|
39
|
+
else
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def == (comparison_object)
|
45
|
+
comparison_object.location == location
|
46
|
+
comparison_object.score == score
|
47
|
+
comparison_object.rules_hash == rules_hash
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,163 +1,164 @@
|
|
1
|
-
require 'cuke_sniffer/constants'
|
2
|
-
require 'cuke_sniffer/rule_config'
|
3
|
-
|
4
|
-
module CukeSniffer
|
5
|
-
class Scenario < FeatureRulesEvaluator
|
6
|
-
include CukeSniffer::Constants
|
7
|
-
include CukeSniffer::RuleConfig
|
8
|
-
|
9
|
-
attr_accessor :start_line, :type, :steps, :inline_tables, :examples_table
|
10
|
-
|
11
|
-
def initialize(location, scenario)
|
12
|
-
super(location)
|
13
|
-
@start_line = location.match(/:(?<line>\d*)$/)[:line].to_i
|
14
|
-
@steps = []
|
15
|
-
@inline_tables = {}
|
16
|
-
@examples_table = []
|
17
|
-
split_scenario(scenario)
|
18
|
-
evaluate_score
|
19
|
-
end
|
20
|
-
|
21
|
-
def split_scenario(scenario)
|
22
|
-
index = 0
|
23
|
-
until index >= scenario.length or scenario[index] =~ SCENARIO_TITLE_STYLES
|
24
|
-
update_tag_list(scenario[index])
|
25
|
-
index += 1
|
26
|
-
end
|
27
|
-
|
28
|
-
until index >= scenario.length or scenario[index].match STEP_REGEX or scenario[index].include?("Examples:")
|
29
|
-
match = scenario[index].match(SCENARIO_TITLE_STYLES)
|
30
|
-
@type = match[:type] unless match.nil?
|
31
|
-
create_name(scenario[index], SCENARIO_TITLE_STYLES)
|
32
|
-
index += 1
|
33
|
-
end
|
34
|
-
|
35
|
-
until index >= scenario.length or scenario[index].include?("Examples:")
|
36
|
-
if scenario[index] =~
|
37
|
-
step = scenario[index - 1]
|
38
|
-
@inline_tables[step] = []
|
39
|
-
until index >= scenario.length or scenario[index] =~ STEP_REGEX
|
40
|
-
@inline_tables[step] << scenario[index]
|
41
|
-
index += 1
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
index
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
comparison_object.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
match = line.match(STEP_REGEX)
|
69
|
-
order << match[:style] unless match.nil?
|
70
|
-
}
|
71
|
-
order
|
72
|
-
end
|
73
|
-
|
74
|
-
def evaluate_score
|
75
|
-
super
|
76
|
-
rule_empty_scenario
|
77
|
-
rule_too_many_steps
|
78
|
-
rule_step_order
|
79
|
-
rule_invalid_first_step
|
80
|
-
rule_asterisk_step
|
81
|
-
rule_commented_step
|
82
|
-
rule_implementation_words
|
83
|
-
rule_date_used_in_step
|
84
|
-
evaluate_outline_scores if type == "Scenario Outline"
|
85
|
-
end
|
86
|
-
|
87
|
-
def evaluate_outline_scores
|
88
|
-
rule_no_examples_table
|
89
|
-
rule_no_examples
|
90
|
-
rule_one_example
|
91
|
-
rule_too_many_examples
|
92
|
-
rule_commented_example
|
93
|
-
end
|
94
|
-
|
95
|
-
def rule_empty_scenario
|
96
|
-
store_rule(SCENARIO_RULES[:no_steps]) if @steps.empty?
|
97
|
-
end
|
98
|
-
|
99
|
-
def rule_too_many_steps
|
100
|
-
rule = SCENARIO_RULES[:too_many_steps]
|
101
|
-
store_rule(rule) if @steps.size >= rule[:max]
|
102
|
-
end
|
103
|
-
|
104
|
-
def rule_step_order
|
105
|
-
step_order = get_step_order.uniq
|
106
|
-
%w(But * And).each { |type| step_order.delete(type) }
|
107
|
-
store_rule(SCENARIO_RULES[:out_of_order_steps]) unless step_order == %w(Given When Then) or step_order == %w(When Then)
|
108
|
-
end
|
109
|
-
|
110
|
-
def rule_invalid_first_step
|
111
|
-
first_step = get_step_order.first
|
112
|
-
store_rule(SCENARIO_RULES[:invalid_first_step]) if %w(And But).include?(first_step)
|
113
|
-
end
|
114
|
-
|
115
|
-
def rule_asterisk_step
|
116
|
-
get_step_order.count('*').times { store_rule(SCENARIO_RULES[:asterisk_step]) }
|
117
|
-
end
|
118
|
-
|
119
|
-
def rule_commented_step
|
120
|
-
@steps.each do |step|
|
121
|
-
store_rule(SCENARIO_RULES[:commented_step]) if is_comment?(step)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def rule_implementation_words
|
126
|
-
rule = SHARED_RULES[:implementation_word]
|
127
|
-
@steps.each do |step|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
end
|
1
|
+
require 'cuke_sniffer/constants'
|
2
|
+
require 'cuke_sniffer/rule_config'
|
3
|
+
|
4
|
+
module CukeSniffer
|
5
|
+
class Scenario < FeatureRulesEvaluator
|
6
|
+
include CukeSniffer::Constants
|
7
|
+
include CukeSniffer::RuleConfig
|
8
|
+
|
9
|
+
attr_accessor :start_line, :type, :steps, :inline_tables, :examples_table
|
10
|
+
|
11
|
+
def initialize(location, scenario)
|
12
|
+
super(location)
|
13
|
+
@start_line = location.match(/:(?<line>\d*)$/)[:line].to_i
|
14
|
+
@steps = []
|
15
|
+
@inline_tables = {}
|
16
|
+
@examples_table = []
|
17
|
+
split_scenario(scenario)
|
18
|
+
evaluate_score
|
19
|
+
end
|
20
|
+
|
21
|
+
def split_scenario(scenario)
|
22
|
+
index = 0
|
23
|
+
until index >= scenario.length or scenario[index] =~ SCENARIO_TITLE_STYLES
|
24
|
+
update_tag_list(scenario[index])
|
25
|
+
index += 1
|
26
|
+
end
|
27
|
+
|
28
|
+
until index >= scenario.length or scenario[index].match STEP_REGEX or scenario[index].include?("Examples:")
|
29
|
+
match = scenario[index].match(SCENARIO_TITLE_STYLES)
|
30
|
+
@type = match[:type] unless match.nil?
|
31
|
+
create_name(scenario[index], SCENARIO_TITLE_STYLES)
|
32
|
+
index += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
until index >= scenario.length or scenario[index].include?("Examples:")
|
36
|
+
if scenario[index] =~ /^\|.*\|/
|
37
|
+
step = scenario[index - 1]
|
38
|
+
@inline_tables[step] = []
|
39
|
+
until index >= scenario.length or scenario[index] =~ STEP_REGEX
|
40
|
+
@inline_tables[step] << scenario[index]
|
41
|
+
index += 1
|
42
|
+
end
|
43
|
+
else
|
44
|
+
@steps << scenario[index] if scenario[index] =~ STEP_REGEX
|
45
|
+
index += 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if index < scenario.length and scenario[index].include?("Examples:")
|
50
|
+
index += 1
|
51
|
+
until index >= scenario.length
|
52
|
+
@examples_table << scenario[index] unless scenario[index].empty?
|
53
|
+
index += 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def ==(comparison_object)
|
59
|
+
super(comparison_object)
|
60
|
+
comparison_object.steps == steps
|
61
|
+
comparison_object.examples_table == examples_table
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_step_order
|
65
|
+
order = []
|
66
|
+
@steps.each { |line|
|
67
|
+
next if is_comment?(line)
|
68
|
+
match = line.match(STEP_REGEX)
|
69
|
+
order << match[:style] unless match.nil?
|
70
|
+
}
|
71
|
+
order
|
72
|
+
end
|
73
|
+
|
74
|
+
def evaluate_score
|
75
|
+
super
|
76
|
+
rule_empty_scenario
|
77
|
+
rule_too_many_steps
|
78
|
+
rule_step_order
|
79
|
+
rule_invalid_first_step
|
80
|
+
rule_asterisk_step
|
81
|
+
rule_commented_step
|
82
|
+
rule_implementation_words
|
83
|
+
rule_date_used_in_step
|
84
|
+
evaluate_outline_scores if type == "Scenario Outline"
|
85
|
+
end
|
86
|
+
|
87
|
+
def evaluate_outline_scores
|
88
|
+
rule_no_examples_table
|
89
|
+
rule_no_examples
|
90
|
+
rule_one_example
|
91
|
+
rule_too_many_examples
|
92
|
+
rule_commented_example
|
93
|
+
end
|
94
|
+
|
95
|
+
def rule_empty_scenario
|
96
|
+
store_rule(SCENARIO_RULES[:no_steps]) if @steps.empty?
|
97
|
+
end
|
98
|
+
|
99
|
+
def rule_too_many_steps
|
100
|
+
rule = SCENARIO_RULES[:too_many_steps]
|
101
|
+
store_rule(rule) if @steps.size >= rule[:max]
|
102
|
+
end
|
103
|
+
|
104
|
+
def rule_step_order
|
105
|
+
step_order = get_step_order.uniq
|
106
|
+
%w(But * And).each { |type| step_order.delete(type) }
|
107
|
+
store_rule(SCENARIO_RULES[:out_of_order_steps]) unless step_order == %w(Given When Then) or step_order == %w(When Then)
|
108
|
+
end
|
109
|
+
|
110
|
+
def rule_invalid_first_step
|
111
|
+
first_step = get_step_order.first
|
112
|
+
store_rule(SCENARIO_RULES[:invalid_first_step]) if %w(And But).include?(first_step)
|
113
|
+
end
|
114
|
+
|
115
|
+
def rule_asterisk_step
|
116
|
+
get_step_order.count('*').times { store_rule(SCENARIO_RULES[:asterisk_step]) }
|
117
|
+
end
|
118
|
+
|
119
|
+
def rule_commented_step
|
120
|
+
@steps.each do |step|
|
121
|
+
store_rule(SCENARIO_RULES[:commented_step]) if is_comment?(step)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def rule_implementation_words
|
126
|
+
rule = SHARED_RULES[:implementation_word]
|
127
|
+
@steps.each do |step|
|
128
|
+
next if is_comment?(step)
|
129
|
+
rule[:words].each do |word|
|
130
|
+
store_updated_rule(rule, rule[:phrase].gsub(/{.*}/, word)) if step.include?(word)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def rule_date_used_in_step
|
136
|
+
@steps.each do |step|
|
137
|
+
store_rule(SCENARIO_RULES[:date_used]) if step =~ DATE_REGEX
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def rule_no_examples_table
|
142
|
+
store_rule(SCENARIO_RULES[:no_examples_table]) if @examples_table.empty?
|
143
|
+
end
|
144
|
+
|
145
|
+
def rule_no_examples
|
146
|
+
store_rule(SCENARIO_RULES[:no_examples]) if @examples_table.size == 1
|
147
|
+
end
|
148
|
+
|
149
|
+
def rule_one_example
|
150
|
+
store_rule(SCENARIO_RULES[:one_example]) if @examples_table.size == 2 and !is_comment?(@examples_table[1])
|
151
|
+
end
|
152
|
+
|
153
|
+
def rule_too_many_examples
|
154
|
+
store_rule(SCENARIO_RULES[:too_many_examples]) if (@examples_table.size - 1) >= 8
|
155
|
+
end
|
156
|
+
|
157
|
+
def rule_commented_example
|
158
|
+
@examples_table.each do |example|
|
159
|
+
store_rule(SCENARIO_RULES[:commented_example]) if is_comment?(example)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|