cucumber_analytics 0.0.2 → 0.0.3

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.
data/History.rdoc ADDED
@@ -0,0 +1,16 @@
1
+ === Version 0.0.3 / 2012-11-10
2
+
3
+ * 'But' has been added to the list of recognized step keywords (formerly Given,
4
+ When,Then, And, and *)
5
+ * Bug fix: the number of test cases a feature is considered to contain now
6
+ properly takes into account an outline's example rows.
7
+
8
+
9
+ === Version 0.0.2 / 2012-11-1
10
+
11
+ * Bug fix: descriptions are no longer cut short due to the presence of keywords
12
+
13
+
14
+ === Version 0.0.1 / 2012-10-28
15
+
16
+ * Initial release
@@ -19,4 +19,5 @@ Gem::Specification.new do |gem|
19
19
  gem.add_development_dependency("cucumber")
20
20
  gem.add_development_dependency("wrong")
21
21
  gem.add_development_dependency("simplecov")
22
+ gem.add_development_dependency("log4r")
22
23
  end
@@ -26,13 +26,14 @@ Feature: Background elements can be modeled.
26
26
  # Basically, if it's not a step keyword or tag then I will accept
27
27
  # it as description here. Cucumber might not but but that's between
28
28
  # you and its lexxer/parser. ;)
29
- * this *parameterized* step takes a table:
29
+ Given this *parameterized* step takes a table:
30
30
  | data |
31
31
  | more data |
32
- * some setup step
32
+ When some setup step
33
+ But some setup step
33
34
  #
34
- * a step with a *parameter*
35
- * some big setup step:
35
+ Then a step with a *parameter*
36
+ And some big setup step:
36
37
  #random comment
37
38
  \"\"\"
38
39
  some text
@@ -47,6 +48,8 @@ Feature: Background elements can be modeled.
47
48
  Given
48
49
  When
49
50
  Then
51
+ And
52
+ But
50
53
  *
51
54
  some more text
52
55
  \"\"\"
@@ -78,40 +81,45 @@ Feature: Background elements can be modeled.
78
81
 
79
82
  Scenario: The background steps are modeled.
80
83
  Then the background's steps are as follows:
81
- | * this *parameterized* step takes a table: |
82
- | \| data \| |
83
- | \| more data \| |
84
- | * some setup step |
85
- | * a step with a *parameter* |
86
- | * some big setup step: |
87
- | """ |
88
- | 'some text' |
89
- | '' |
90
- | '#some comments' |
91
- | 'Scenario:' |
92
- | 'Scenario Outline:' |
93
- | 'Examples:' |
94
- | '@' |
95
- | 'Feature:' |
96
- | '\|' |
97
- | 'Given' |
98
- | 'When' |
99
- | 'Then' |
100
- | '*' |
101
- | ' some more text' |
102
- | """ |
103
- | * *lots* *of* *parameters* |
84
+ | Given this *parameterized* step takes a table: |
85
+ | \| data \| |
86
+ | \| more data \| |
87
+ | When some setup step |
88
+ | But some setup step |
89
+ | Then a step with a *parameter* |
90
+ | And some big setup step: |
91
+ | """ |
92
+ | 'some text' |
93
+ | '' |
94
+ | '#some comments' |
95
+ | 'Scenario:' |
96
+ | 'Scenario Outline:' |
97
+ | 'Examples:' |
98
+ | '@' |
99
+ | 'Feature:' |
100
+ | '\|' |
101
+ | 'Given' |
102
+ | 'When' |
103
+ | 'Then' |
104
+ | 'And' |
105
+ | 'But' |
106
+ | '*' |
107
+ | ' some more text' |
108
+ | """ |
109
+ | * *lots* *of* *parameters* |
104
110
  And the background's steps "without" arguments are as follows:
105
- | * this ** step takes a table: |
106
- | * some setup step |
107
- | * a step with a ** |
108
- | * some big setup step: |
109
- | * ** ** ** |
111
+ | Given this ** step takes a table: |
112
+ | When some setup step |
113
+ | But some setup step |
114
+ | Then a step with a ** |
115
+ | And some big setup step: |
116
+ | * ** ** ** |
110
117
  And the background's steps "without" keywords are as follows:
111
118
  | this *parameterized* step takes a table: |
112
119
  | \| data \| |
113
120
  | \| more data \| |
114
121
  | some setup step |
122
+ | some setup step |
115
123
  | a step with a *parameter* |
116
124
  | some big setup step: |
117
125
  | """ |
@@ -127,6 +135,8 @@ Feature: Background elements can be modeled.
127
135
  | 'Given' |
128
136
  | 'When' |
129
137
  | 'Then' |
138
+ | 'And' |
139
+ | 'But' |
130
140
  | '*' |
131
141
  | ' some more text' |
132
142
  | """ |
@@ -134,13 +144,14 @@ Feature: Background elements can be modeled.
134
144
  And the background's steps "without" arguments "without" keywords are as follows:
135
145
  | this ** step takes a table: |
136
146
  | some setup step |
147
+ | some setup step |
137
148
  | a step with a ** |
138
149
  | some big setup step: |
139
150
  | ** ** ** |
140
151
  And step "1" of the background has the following block:
141
152
  | \| data \| |
142
153
  | \| more data \| |
143
- And step "4" of the background has the following block:
154
+ And step "5" of the background has the following block:
144
155
  | """ |
145
156
  | 'some text' |
146
157
  | '' |
@@ -154,6 +165,8 @@ Feature: Background elements can be modeled.
154
165
  | 'Given' |
155
166
  | 'When' |
156
167
  | 'Then' |
168
+ | 'And' |
169
+ | 'But' |
157
170
  | '*' |
158
171
  | ' some more text' |
159
172
  | """ |
@@ -30,6 +30,7 @@ Feature: Features can be modeled.
30
30
  Given some description that uses keywords
31
31
  And more of it
32
32
  When I chuck the kitchen sink at it:
33
+ But
33
34
  *
34
35
  |
35
36
 
@@ -79,6 +80,7 @@ Feature: Features can be modeled.
79
80
  Examples: some examples with different significance and a tag
80
81
  | param1 | param2 |
81
82
  | a | b |
83
+ | c | d |
82
84
 
83
85
 
84
86
  Scenario: The second scenario's name.
@@ -113,7 +115,7 @@ Feature: Features can be modeled.
113
115
  Then feature "1" is found to have the following properties:
114
116
  | name | The test feature name. |
115
117
  | test_count | 3 |
116
- | test_case_count | 4 |
118
+ | test_case_count | 5 |
117
119
  And feature "2" is found to have the following properties:
118
120
  | name | |
119
121
  | test_count | 2 |
@@ -132,6 +134,7 @@ Feature: Features can be modeled.
132
134
  | Given some description that uses keywords |
133
135
  | And more of it |
134
136
  | When I chuck the kitchen sink at it: |
137
+ | But |
135
138
  | * |
136
139
  | \| |
137
140
  | Scenario Outline |
@@ -36,9 +36,10 @@ Feature: Scenario Outline elements can be modeled.
36
36
  | <param1> |
37
37
  | <param2> |
38
38
  And some setup step
39
+ * some setup step
39
40
  #
40
41
  When a step with a *parameter*
41
- And a big step:
42
+ But a big step:
42
43
  #random comment
43
44
  \"\"\"
44
45
  some text
@@ -53,6 +54,8 @@ Feature: Scenario Outline elements can be modeled.
53
54
  Given
54
55
  When
55
56
  Then
57
+ And
58
+ But
56
59
  *
57
60
  some more text
58
61
  \"\"\"
@@ -103,8 +106,9 @@ Feature: Scenario Outline elements can be modeled.
103
106
  | \| <param1> \| |
104
107
  | \| <param2> \| |
105
108
  | And some setup step |
109
+ | * some setup step |
106
110
  | When a step with a *parameter* |
107
- | And a big step: |
111
+ | But a big step: |
108
112
  | """ |
109
113
  | 'some text' |
110
114
  | '' |
@@ -118,6 +122,8 @@ Feature: Scenario Outline elements can be modeled.
118
122
  | 'Given' |
119
123
  | 'When' |
120
124
  | 'Then' |
125
+ | 'And' |
126
+ | 'But' |
121
127
  | '*' |
122
128
  | ' some more text' |
123
129
  | """ |
@@ -125,14 +131,16 @@ Feature: Scenario Outline elements can be modeled.
125
131
  And the test steps "without" arguments are as follows:
126
132
  | Given this ** step takes a table: |
127
133
  | And some setup step |
134
+ | * some setup step |
128
135
  | When a step with a ** |
129
- | And a big step: |
136
+ | But a big step: |
130
137
  | Then ** ** ** |
131
138
  And the test steps "without" keywords are as follows:
132
139
  | this *parameterized* step takes a table: |
133
140
  | \| <param1> \| |
134
141
  | \| <param2> \| |
135
142
  | some setup step |
143
+ | some setup step |
136
144
  | a step with a *parameter* |
137
145
  | a big step: |
138
146
  | """ |
@@ -148,6 +156,8 @@ Feature: Scenario Outline elements can be modeled.
148
156
  | 'Given' |
149
157
  | 'When' |
150
158
  | 'Then' |
159
+ | 'And' |
160
+ | 'But' |
151
161
  | '*' |
152
162
  | ' some more text' |
153
163
  | """ |
@@ -155,13 +165,14 @@ Feature: Scenario Outline elements can be modeled.
155
165
  And the test steps "without" arguments "without" keywords are as follows:
156
166
  | this ** step takes a table: |
157
167
  | some setup step |
168
+ | some setup step |
158
169
  | a step with a ** |
159
170
  | a big step: |
160
171
  | ** ** ** |
161
172
  And the test step "1" has the following block:
162
173
  | \| <param1> \| |
163
174
  | \| <param2> \| |
164
- And the test step "4" has the following block:
175
+ And the test step "5" has the following block:
165
176
  | """ |
166
177
  | 'some text' |
167
178
  | '' |
@@ -175,6 +186,8 @@ Feature: Scenario Outline elements can be modeled.
175
186
  | 'Given' |
176
187
  | 'When' |
177
188
  | 'Then' |
189
+ | 'And' |
190
+ | 'But' |
178
191
  | '*' |
179
192
  | ' some more text' |
180
193
  | """ |
@@ -36,9 +36,10 @@ Feature: Scenario elements can be modeled.
36
36
  | data |
37
37
  | more data |
38
38
  And some setup step
39
+ * some setup step
39
40
  #
40
41
  When a step with a *parameter*
41
- And a big step:
42
+ But a big step:
42
43
  #random comment
43
44
  \"\"\"
44
45
  some text
@@ -53,6 +54,8 @@ Feature: Scenario elements can be modeled.
53
54
  Given
54
55
  When
55
56
  Then
57
+ And
58
+ But
56
59
  *
57
60
  some more text
58
61
  \"\"\"
@@ -69,13 +72,13 @@ Feature: Scenario elements can be modeled.
69
72
 
70
73
  Scenario: The scenario description is modeled.
71
74
  Then the test descriptive lines are as follows:
72
- | My big hunk of perfectly valid description: |
73
- | \| |
74
- | Scenario Outline |
75
- | Examples |
76
- | """ |
77
- | Background |
78
- | this is still one big valid description |
75
+ | My big hunk of perfectly valid description: |
76
+ | \| |
77
+ | Scenario Outline |
78
+ | Examples |
79
+ | """ |
80
+ | Background |
81
+ | this is still one big valid description |
79
82
 
80
83
  Scenario: The scenario steps are modeled.
81
84
  Then the test steps are as follows:
@@ -83,8 +86,9 @@ Feature: Scenario elements can be modeled.
83
86
  | \| data \| |
84
87
  | \| more data \| |
85
88
  | And some setup step |
89
+ | * some setup step |
86
90
  | When a step with a *parameter* |
87
- | And a big step: |
91
+ | But a big step: |
88
92
  | """ |
89
93
  | 'some text' |
90
94
  | '' |
@@ -98,6 +102,8 @@ Feature: Scenario elements can be modeled.
98
102
  | 'Given' |
99
103
  | 'When' |
100
104
  | 'Then' |
105
+ | 'And' |
106
+ | 'But' |
101
107
  | '*' |
102
108
  | ' some more text' |
103
109
  | """ |
@@ -105,14 +111,16 @@ Feature: Scenario elements can be modeled.
105
111
  And the test steps "without" arguments are as follows:
106
112
  | Given this ** step takes a table: |
107
113
  | And some setup step |
114
+ | * some setup step |
108
115
  | When a step with a ** |
109
- | And a big step: |
116
+ | But a big step: |
110
117
  | Then ** ** ** |
111
118
  And the test steps "without" keywords are as follows:
112
119
  | this *parameterized* step takes a table: |
113
120
  | \| data \| |
114
121
  | \| more data \| |
115
122
  | some setup step |
123
+ | some setup step |
116
124
  | a step with a *parameter* |
117
125
  | a big step: |
118
126
  | """ |
@@ -128,6 +136,8 @@ Feature: Scenario elements can be modeled.
128
136
  | 'Given' |
129
137
  | 'When' |
130
138
  | 'Then' |
139
+ | 'And' |
140
+ | 'But' |
131
141
  | '*' |
132
142
  | ' some more text' |
133
143
  | """ |
@@ -135,13 +145,14 @@ Feature: Scenario elements can be modeled.
135
145
  And the test steps "without" arguments "without" keywords are as follows:
136
146
  | this ** step takes a table: |
137
147
  | some setup step |
148
+ | some setup step |
138
149
  | a step with a ** |
139
150
  | a big step: |
140
151
  | ** ** ** |
141
152
  And the test step "1" has the following block:
142
153
  | \| data \| |
143
154
  | \| more data \| |
144
- And the test step "4" has the following block:
155
+ And the test step "5" has the following block:
145
156
  | """ |
146
157
  | 'some text' |
147
158
  | '' |
@@ -155,6 +166,8 @@ Feature: Scenario elements can be modeled.
155
166
  | 'Given' |
156
167
  | 'When' |
157
168
  | 'Then' |
169
+ | 'And' |
170
+ | 'But' |
158
171
  | '*' |
159
172
  | ' some more text' |
160
173
  | """ |
@@ -6,6 +6,15 @@ include Wrong
6
6
 
7
7
  require File.dirname(__FILE__) + '/../../lib/cucumber_analytics'
8
8
 
9
+ Log4r::Logger.root.level = Log4r::OFF
10
+
11
+ Log4r::FileOutputter.new('logfile',
12
+ :filename=>'test_log.txt',
13
+ :trunc=>true,
14
+ :level=>Log4r::DEBUG)
15
+
16
+ CucumberAnalytics::Logging.logger.add('logfile')
17
+
9
18
 
10
19
  DEFAULT_FEATURE_FILE_NAME = 'test_feature.feature'
11
20
  DEFAULT_STEP_FILE_NAME = 'test_steps.rb'
@@ -1,4 +1,7 @@
1
+ require "log4r"
2
+
1
3
  require 'cucumber_analytics/version'
4
+ require 'cucumber_analytics/logging'
2
5
  require 'cucumber_analytics/parsed_file'
3
6
  require 'cucumber_analytics/parsed_directory'
4
7
  require 'cucumber_analytics/feature_element.rb'
@@ -8,6 +8,8 @@ module CucumberAnalytics
8
8
 
9
9
  # Creates a new FeatureElement object.
10
10
  def initialize(source_lines = nil)
11
+ CucumberAnalytics::Logging.logger.info('FeatureElement#initialize')
12
+
11
13
  @name = ''
12
14
  @description =[]
13
15
  end
@@ -17,25 +19,41 @@ module CucumberAnalytics
17
19
 
18
20
 
19
21
  def parse_feature_element(source_lines)
22
+ CucumberAnalytics::Logging.logger.info('FeatureElement#parse_feature_element')
23
+
20
24
  parse_feature_element_name(source_lines)
21
25
  parse_feature_element_description(source_lines)
22
26
  end
23
27
 
24
28
  #todo - move this elsewhere
25
29
  def parse_feature_element_tags(source_lines)
26
- source_lines.take_while { |line| !(line =~/^\s*(?:[A-Z a-z])+:/) }.tap do |tag_lines|
30
+ CucumberAnalytics::Logging.logger.info('FeatureElement#parse_feature_element_tags')
31
+ CucumberAnalytics::Logging.logger.debug('source lines')
32
+ source_lines.each do |line|
33
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
34
+ end
35
+
36
+ source_lines.take_while { |line| line !~ /^\s*(?:[A-Z a-z])+:/ }.tap do |tag_lines|
37
+ tag_lines.delete_if { |line| World.ignored_line?(line)}
38
+
27
39
  tag_lines.join(' ').delete(' ').split('@').each do |tag|
28
40
  @tags << "@#{tag.strip}"
29
41
  end
30
42
  end
31
43
  @tags.shift
32
44
 
33
- while source_lines.first =~ /^\s*@/
45
+ while source_lines.first !~ /^\s*(?:[A-Z a-z])+:/
34
46
  source_lines.shift
35
47
  end
36
48
  end
37
49
 
38
50
  def parse_feature_element_name(source_lines)
51
+ CucumberAnalytics::Logging.logger.info('FeatureElement#parse_feature_element_name')
52
+ CucumberAnalytics::Logging.logger.debug('source lines')
53
+ source_lines.each do |line|
54
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
55
+ end
56
+
39
57
  @name.replace source_lines.first.match(/^\s*(?:[A-Z a-z])+:(.*)/)[1].strip
40
58
  source_lines.shift
41
59
  end
@@ -0,0 +1,9 @@
1
+ module CucumberAnalytics
2
+ module Logging
3
+
4
+ def self.logger
5
+ @logger ||= Log4r::Logger.new('ca_logger')
6
+ end
7
+
8
+ end
9
+ end
@@ -9,6 +9,12 @@ module CucumberAnalytics
9
9
  # Creates a new OutlineExample object and, if *source_lines* is provided,
10
10
  # populates the object.
11
11
  def initialize(source_lines = nil)
12
+ CucumberAnalytics::Logging.logger.info('OutlineExample#initialize')
13
+ CucumberAnalytics::Logging.logger.debug('source lines')
14
+ source_lines.each do |line|
15
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
16
+ end
17
+
12
18
  super
13
19
 
14
20
  @tags = []
@@ -22,16 +28,29 @@ module CucumberAnalytics
22
28
 
23
29
 
24
30
  def parse_example(source_lines)
31
+ CucumberAnalytics::Logging.logger.info('OutlineExample#parse_example')
32
+
25
33
  parse_feature_element_tags(source_lines)
26
34
  parse_feature_element(source_lines)
35
+
36
+ source_lines.delete_if { |line| World.ignored_line?(line)}
27
37
  rows.concat source_lines.collect { |line| line.strip }
28
38
  end
29
39
 
30
40
  def parse_feature_element_description(source_lines)
41
+ CucumberAnalytics::Logging.logger.info('OutlineExample#parse_feature_element_description')
42
+ CucumberAnalytics::Logging.logger.debug('source lines')
43
+ source_lines.each do |line|
44
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
45
+ end
46
+
31
47
  until source_lines.first =~ /^\s*\|/ or
32
48
  source_lines.empty?
33
49
 
34
- @description << source_lines.first.strip
50
+ unless World.ignored_line?(source_lines.first)
51
+ @description << source_lines.first.strip
52
+ end
53
+
35
54
  source_lines.shift
36
55
  end
37
56
  end
@@ -5,6 +5,8 @@ module CucumberAnalytics
5
5
  # Creates a new ParsedBackground object and, if *source_lines* is provided,
6
6
  # populates the object.
7
7
  def initialize(source_lines = nil)
8
+ CucumberAnalytics::Logging.logger.info('ParsedBackground#initialize')
9
+
8
10
  super
9
11
 
10
12
  parse_background(source_lines) if source_lines
@@ -15,15 +17,26 @@ module CucumberAnalytics
15
17
 
16
18
 
17
19
  def parse_background(source_lines)
20
+ CucumberAnalytics::Logging.logger.info('ParsedBackground#parse_background')
21
+
18
22
  parse_feature_element(source_lines)
19
23
  parse_test_element_steps(source_lines)
20
24
  end
21
25
 
22
26
  def parse_feature_element_description(source_lines)
27
+ CucumberAnalytics::Logging.logger.info('ParsedBackground#parse_feature_element_description')
28
+ CucumberAnalytics::Logging.logger.debug('source lines')
29
+ source_lines.each do |line|
30
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
31
+ end
32
+
23
33
  until source_lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* ))/ or
24
34
  source_lines.empty?
25
35
 
26
- @description << source_lines.first.strip
36
+ unless World.ignored_line?(source_lines.first)
37
+ @description << source_lines.first.strip
38
+ end
39
+
27
40
  source_lines.shift
28
41
  end
29
42
  end
@@ -9,6 +9,8 @@ module CucumberAnalytics
9
9
  # Creates a new ParsedDirectory object and, if *directory_parsed* is
10
10
  # provided, populates the object.
11
11
  def initialize(directory_parsed = nil)
12
+ CucumberAnalytics::Logging.logger.info('ParsedDirectory#initialize')
13
+
12
14
  @directory = directory_parsed
13
15
 
14
16
  @feature_files = []
@@ -10,6 +10,8 @@ module CucumberAnalytics
10
10
  # Creates a new ParsedFeature object and, if *source_lines* is provided,
11
11
  # populates the object.
12
12
  def initialize(source_lines = nil)
13
+ CucumberAnalytics::Logging.logger.info('ParsedFeature#initialize')
14
+
13
15
  super
14
16
 
15
17
  @tags = []
@@ -50,7 +52,11 @@ module CucumberAnalytics
50
52
 
51
53
  # Returns the number of test cases contained in the feature.
52
54
  def test_case_count
53
- scenario_count + outlines.reduce(0) { |sum, outline| sum += outline.examples.count }
55
+ scenario_count + outlines.reduce(0) { |outline_sum, outline|
56
+ outline_sum += outline.examples.reduce(0) { |example_sum, example|
57
+ example_sum += example.rows.count - 1
58
+ }
59
+ }
54
60
  end
55
61
 
56
62
  def contains
@@ -62,11 +68,21 @@ module CucumberAnalytics
62
68
 
63
69
 
64
70
  def parse_feature(source_lines)
71
+ CucumberAnalytics::Logging.logger.info('ParsedFeature#parse_feature')
72
+
65
73
  parse_feature_element_tags(source_lines)
66
74
  parse_feature_element(source_lines)
67
75
  end
68
76
 
69
77
  def parse_feature_element_description(source_lines)
78
+ CucumberAnalytics::Logging.logger.info('ParsedFeature#parse_feature_element_description')
79
+ CucumberAnalytics::Logging.logger.debug('source lines')
80
+ source_lines.each do |line|
81
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
82
+ end
83
+
84
+ source_lines.delete_if { |line| World.ignored_line?(line)}
85
+
70
86
  until source_lines.first =~ /^\s*(?:(?:Scenario: )|(?:Scenario Outline: )|(?:Background: )|(?:@ ))/ or
71
87
  source_lines.empty?
72
88
 
@@ -8,6 +8,8 @@ module CucumberAnalytics
8
8
  # Creates a new ParsedFile object and, if *file_parsed* is provided,
9
9
  # populates the object.
10
10
  def initialize(file_parsed = nil)
11
+ CucumberAnalytics::Logging.logger.info('ParsedFile#initialize')
12
+
11
13
  parse_file(file_parsed) if file_parsed
12
14
  end
13
15
 
@@ -30,6 +32,8 @@ module CucumberAnalytics
30
32
 
31
33
 
32
34
  def parse_file(file_parsed)
35
+ CucumberAnalytics::Logging.logger.info('ParsedFile#parse_file')
36
+
33
37
  @file = file_parsed
34
38
 
35
39
  file_lines = []
@@ -40,47 +44,44 @@ module CucumberAnalytics
40
44
 
41
45
  # collect feature tag lines
42
46
  until file_lines.first =~ /^s*Feature:/
43
- unless ignored_line?(file_lines.first)
44
- feature_lines << file_lines.first
45
- end
47
+ feature_lines << file_lines.first
46
48
  file_lines.shift
47
49
  end
48
50
 
49
51
  # collect everything else until the end of the feature section
50
- until file_lines.first =~ /^\s*(?:@|Background:|Scenario:|(?:Scenario Outline:))/ or file_lines.empty?
51
- unless ignored_line?(file_lines.first)
52
- feature_lines << file_lines.first
53
- end
52
+ until file_lines.first =~ /^\s*(?:@|Background:|Scenario:|(?:Scenario Outline:))/ or
53
+ file_lines.empty?
54
+
55
+ feature_lines << file_lines.first
54
56
  file_lines.shift
55
57
  end
56
58
 
59
+ # create a new feature bases on the collected lines
60
+ @feature = ParsedFeature.new(feature_lines)
61
+
57
62
  if file_lines.first =~ /^\s*Background:/
58
63
 
59
64
  # collect the background description lines
60
- until (file_lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )|@|Scenario:|(?:Scenario Outline:))/) or file_lines.empty?
61
- unless ignored_line?(file_lines.first)
62
- background_lines << file_lines.first
63
- end
65
+ until (file_lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )|@|Scenario:|(?:Scenario Outline:))/) or
66
+ file_lines.empty?
67
+
68
+ background_lines << file_lines.first
64
69
  file_lines.shift
65
70
  end
66
71
 
67
72
  # collect everything else up to the first test
68
- until file_lines.first =~ /^\s*(?:@|Scenario:|(?:Scenario Outline:))/ or file_lines.empty?
73
+ until file_lines.first =~ /^\s*(?:@|Scenario:|(?:Scenario Outline:))/ or
74
+ file_lines.empty?
75
+
69
76
  if file_lines.first =~ /^\s*"""/
70
77
  background_lines.concat(extract_doc_string!(file_lines))
71
78
  else
72
- unless ignored_line?(file_lines.first)
73
- background_lines << file_lines.first
74
- end
79
+ background_lines << file_lines.first
75
80
  file_lines.shift
76
81
  end
77
82
  end
78
83
 
79
- end
80
-
81
- @feature = ParsedFeature.new(feature_lines)
82
-
83
- unless background_lines.empty?
84
+ # create a new background based on the collected lines
84
85
  @feature.background = ParsedBackground.new(background_lines)
85
86
  end
86
87
 
@@ -88,18 +89,22 @@ module CucumberAnalytics
88
89
  end
89
90
 
90
91
  def parse_tests(lines)
91
- test_lines = []
92
+ CucumberAnalytics::Logging.logger.info('ParsedFile#parse_tests')
93
+ CucumberAnalytics::Logging.logger.debug('lines')
94
+ lines.each do |line|
95
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
96
+ end
92
97
 
93
98
  until lines.empty?
94
99
  # we'll need this in order to figure out whether we are dealing with a
95
100
  # scenario or an outline
96
101
  current_test_line = lines.index { |line| line =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/ }
97
102
 
103
+ test_lines = []
104
+
98
105
  # collect the tag lines
99
106
  until lines.first =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/
100
- unless ignored_line?(lines.first)
101
- test_lines << lines.first
102
- end
107
+ test_lines << lines.first
103
108
  lines.shift
104
109
  end
105
110
 
@@ -107,28 +112,28 @@ module CucumberAnalytics
107
112
  lines.shift
108
113
 
109
114
  # collect the description lines
110
- until (lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )|Scenario:|(?:Scenario Outline:))/) or lines.empty?
111
- unless ignored_line?(lines.first)
112
- test_lines << lines.first
113
- end
115
+ until (lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )|Scenario:|(?:Scenario Outline:))/) or
116
+ lines.empty?
117
+
118
+ test_lines << lines.first
114
119
  lines.shift
115
120
  end
116
121
 
117
122
  # collect everything else up to the next test
118
- until (lines.first =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/) or lines.empty?
123
+ until (lines.first =~ /^\s*(?:Scenario:|(?:Scenario Outline:))/) or
124
+ lines.empty?
125
+
119
126
  if (lines.first =~ /^\s*"""/)
120
127
  test_lines.concat(extract_doc_string!(lines))
121
128
  else
122
- unless ignored_line?(lines.first)
123
- test_lines << lines.first
124
- end
129
+ test_lines << lines.first
125
130
  lines.shift
126
131
  end
127
132
  end
128
133
 
129
134
  # backtrack in order to not end up stealing the next test's tag lines
130
135
  unless lines.empty?
131
- while (test_lines.last =~ /^\s*@/)
136
+ while (test_lines.last =~ /^\s*@/) or World.ignored_line?(test_lines.last)
132
137
  lines = [test_lines.pop].concat(lines)
133
138
  end
134
139
  end
@@ -145,6 +150,12 @@ module CucumberAnalytics
145
150
  end
146
151
 
147
152
  def extract_doc_string!(lines)
153
+ CucumberAnalytics::Logging.logger.info('ParsedFile#extract_doc_string!')
154
+ CucumberAnalytics::Logging.logger.debug('lines')
155
+ lines.each do |line|
156
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
157
+ end
158
+
148
159
  doc_block = []
149
160
 
150
161
  doc_block << lines.first
@@ -161,9 +172,5 @@ module CucumberAnalytics
161
172
  doc_block
162
173
  end
163
174
 
164
- def ignored_line?(line)
165
- line =~ /^\s*#/ or !(line =~ /\S/)
166
- end
167
-
168
175
  end
169
176
  end
@@ -8,6 +8,12 @@ module CucumberAnalytics
8
8
  # Creates a new ParsedScenario object and, if *source_lines* is provided,
9
9
  # populates the object.
10
10
  def initialize(source_lines = nil)
11
+ CucumberAnalytics::Logging.logger.info('ParsedScenario#initialize')
12
+ CucumberAnalytics::Logging.logger.debug('source lines')
13
+ source_lines.each do |line|
14
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
15
+ end
16
+
11
17
  super
12
18
 
13
19
  @tags = []
@@ -20,16 +26,27 @@ module CucumberAnalytics
20
26
 
21
27
 
22
28
  def parse_scenario(source_lines)
29
+ CucumberAnalytics::Logging.logger.info('ParsedScenario#parse_scenario')
30
+
23
31
  parse_feature_element_tags(source_lines)
24
32
  parse_feature_element(source_lines)
25
33
  parse_test_element_steps(source_lines)
26
34
  end
27
35
 
28
36
  def parse_feature_element_description(source_lines)
37
+ CucumberAnalytics::Logging.logger.info('ParsedScenario#parse_feature_element_description')
38
+ CucumberAnalytics::Logging.logger.debug('source lines')
39
+ source_lines.each do |line|
40
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
41
+ end
42
+
29
43
  until source_lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* ))/ or
30
44
  source_lines.empty?
31
45
 
32
- @description << source_lines.first.strip
46
+ unless World.ignored_line?(source_lines.first)
47
+ @description << source_lines.first.strip
48
+ end
49
+
33
50
  source_lines.shift
34
51
  end
35
52
  end
@@ -8,6 +8,12 @@ module CucumberAnalytics
8
8
  # Creates a new ParsedScenarioOutline object and, if *source_lines* is
9
9
  # provided, populates the object.
10
10
  def initialize(source_lines = nil)
11
+ CucumberAnalytics::Logging.logger.info('ParsedScenarioOutline#initialize')
12
+ CucumberAnalytics::Logging.logger.debug('source lines')
13
+ source_lines.each do |line|
14
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
15
+ end
16
+
11
17
  super
12
18
 
13
19
  @tags = []
@@ -25,6 +31,8 @@ module CucumberAnalytics
25
31
 
26
32
 
27
33
  def parse_outline(source_lines)
34
+ CucumberAnalytics::Logging.logger.info('ParsedScenarioOutline#parse_outline')
35
+
28
36
  parse_feature_element_tags(source_lines)
29
37
  parse_feature_element(source_lines)
30
38
  parse_test_element_steps(source_lines)
@@ -32,32 +40,63 @@ module CucumberAnalytics
32
40
  end
33
41
 
34
42
  def parse_feature_element_description(source_lines)
43
+ CucumberAnalytics::Logging.logger.info('ParsedScenarioOutline#parse_feature_element_description')
44
+ CucumberAnalytics::Logging.logger.debug('source lines')
45
+ source_lines.each do |line|
46
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
47
+ end
48
+
35
49
  until source_lines.first =~ /^\s*(?:(?:Given )|(?:When )|(?:Then )|(?:And )|(?:\* )| (?:Examples: ))/ or
36
50
  source_lines.empty?
37
51
 
38
- @description << source_lines.first.strip
52
+ unless World.ignored_line?(source_lines.first)
53
+ @description << source_lines.first.strip
54
+ end
55
+
39
56
  source_lines.shift
40
57
  end
41
58
  end
42
59
 
43
60
  def parse_outline_examples(source_lines)
61
+ CucumberAnalytics::Logging.logger.info('ParsedScenarioOutline#parse_outline_examples')
62
+ CucumberAnalytics::Logging.logger.debug('source lines')
63
+ source_lines.each do |line|
64
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
65
+ end
66
+
67
+
44
68
  until source_lines.empty?
45
- current_example_line = source_lines.index { |line| line =~ /^\s*Examples/ }
69
+ example_lines = []
46
70
 
47
- example_lines = source_lines.slice!(0..current_example_line)
71
+ # collect the tag lines
72
+ until source_lines.first =~ /^\s*Examples:/
73
+ example_lines << source_lines.first
74
+ source_lines.shift
75
+ end
48
76
 
49
- next_example_line = source_lines.index { |line| line =~ /^\s*Examples:/ }
77
+ example_lines << source_lines.first
78
+ source_lines.shift
50
79
 
51
- if next_example_line.nil?
52
- example_lines.concat(source_lines.slice!(0..source_lines.count))
53
- else
54
- while source_lines[next_example_line - 1] =~ /^\s*@/
55
- next_example_line -= 1
56
- end
80
+ # collect the description lines
81
+ until (source_lines.first =~ /^\s*\|/) or source_lines.empty?
82
+ example_lines << source_lines.first
83
+ source_lines.shift
84
+ end
85
+
86
+ # collect everything else up to the next example
87
+ until (source_lines.first =~ /^\s*Examples:/) or source_lines.empty?
88
+ example_lines << source_lines.first
89
+ source_lines.shift
90
+ end
57
91
 
58
- example_lines.concat(source_lines.slice!(0...next_example_line))
92
+ # backtrack in order to not end up stealing the next test's tag lines
93
+ unless source_lines.empty?
94
+ while (example_lines.last =~ /^\s*@/) or World.ignored_line?(example_lines.last)
95
+ source_lines = [example_lines.pop].concat(source_lines)
96
+ end
59
97
  end
60
98
 
99
+ # use the collected lines to create an example
61
100
  @examples << OutlineExample.new(example_lines)
62
101
  end
63
102
  end
@@ -10,11 +10,23 @@ module CucumberAnalytics
10
10
  # Creates a new Step object based on the passed string. If the optional
11
11
  # string array is provided, it becomes the block for the step.
12
12
  def initialize(step, block = nil)
13
+ CucumberAnalytics::Logging.logger.info('Step#initialize')
14
+ CucumberAnalytics::Logging.logger.debug("step: #{step}")
15
+
13
16
  @base = step.sub(/#{World::STEP_KEYWORD_PATTERN}/, '')
14
17
  @block = block
15
18
  @keyword = step.slice(/#{World::STEP_KEYWORD_PATTERN}/).strip
16
19
  end
17
20
 
21
+ # Returns true if the two steps have the same text, minus any keywords
22
+ # and arguments, and false otherwise.
23
+ def ==(other_step)
24
+ left_step = step_text(with_keywords: false, with_arguments: false)
25
+ right_step = other_step.step_text(with_keywords: false, with_arguments: false)
26
+
27
+ left_step == right_step
28
+ end
29
+
18
30
  # Returns the text of the step. Options can be set to selectively exclude
19
31
  # certain portions of the text. *left_delimiter* and *right_delimiter* are
20
32
  # used to determine which parts of the step are arguments.
@@ -7,18 +7,17 @@ module CucumberAnalytics
7
7
 
8
8
  # Creates a new TestElement object.
9
9
  def initialize(source_lines = nil)
10
+ CucumberAnalytics::Logging.logger.info('TestElement#initialize')
11
+
10
12
  super
11
13
 
12
14
  @steps = []
13
15
  end
14
16
 
15
- # Return true if the two elements have the same steps, minus any keywords
17
+ # Returns true if the two elements have the same steps, minus any keywords
16
18
  # and arguments, and false otherwise.
17
19
  def ==(other_element)
18
- left_steps = steps.collect { |step| step.step_text(with_keywords: false, with_arguments: false) }.flatten
19
- right_steps = other_element.steps.collect { |step| step.step_text(with_keywords: false, with_arguments: false) }.flatten
20
-
21
- left_steps == right_steps
20
+ steps == other_element.steps
22
21
  end
23
22
 
24
23
 
@@ -26,6 +25,12 @@ module CucumberAnalytics
26
25
 
27
26
 
28
27
  def parse_test_element_steps(source_lines)
28
+ CucumberAnalytics::Logging.logger.info('TestElement#parse_test_element_steps')
29
+ CucumberAnalytics::Logging.logger.debug('source lines')
30
+ source_lines.each do |line|
31
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
32
+ end
33
+
29
34
  until source_lines.empty? or source_lines.first =~ /^\s*(?:@|Examples:)/
30
35
  line = source_lines.first
31
36
  block = nil
@@ -38,13 +43,22 @@ module CucumberAnalytics
38
43
  block = extract_table_block(source_lines)
39
44
  @steps[@steps.size - 1] = Step.new(@steps.last.keyword + ' ' + @steps.last.base, block)
40
45
  else
41
- @steps << Step.new(line.strip)
46
+ unless World.ignored_line?(line)
47
+ @steps << Step.new(line.strip)
48
+ end
49
+
42
50
  source_lines.shift
43
51
  end
44
52
  end
45
53
  end
46
54
 
47
55
  def extract_doc_block(source_lines)
56
+ CucumberAnalytics::Logging.logger.info('TestElement#extract_doc_block')
57
+ CucumberAnalytics::Logging.logger.debug('source lines')
58
+ source_lines.each do |line|
59
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
60
+ end
61
+
48
62
  step_block = []
49
63
 
50
64
  line = source_lines.first
@@ -72,6 +86,12 @@ module CucumberAnalytics
72
86
  end
73
87
 
74
88
  def extract_table_block(source_lines)
89
+ CucumberAnalytics::Logging.logger.info('TestElement#extract_table_block')
90
+ CucumberAnalytics::Logging.logger.debug('source lines')
91
+ source_lines.each do |line|
92
+ CucumberAnalytics::Logging.logger.debug(line.chomp)
93
+ end
94
+
75
95
  step_block = []
76
96
 
77
97
  line = source_lines.first
@@ -1,3 +1,3 @@
1
- module CucumberAnalytics
2
- VERSION = "0.0.2"
3
- end
1
+ module CucumberAnalytics
2
+ VERSION = "0.0.3"
3
+ end
@@ -3,7 +3,7 @@ module CucumberAnalytics
3
3
 
4
4
 
5
5
  SANITARY_STRING = '___!!!___'
6
- STEP_KEYWORD_PATTERN = '\s*(?:Given|When|Then|And|\*)\s*'
6
+ STEP_KEYWORD_PATTERN = '\s*(?:Given|When|Then|And|But|\*)\s*'
7
7
 
8
8
 
9
9
  # Returns the left delimiter, which is used to mark the beginning of a step
@@ -178,5 +178,11 @@ module CucumberAnalytics
178
178
  end
179
179
  end
180
180
 
181
+ # Returns true if the line is ignored when reading source code, false
182
+ # otherwise.
183
+ def self.ignored_line?(line)
184
+ line =~ /^\s*#/ or !(line =~ /\S/)
185
+ end
186
+
181
187
  end
182
188
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber_analytics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-01 00:00:00.000000000 Z
12
+ date: 2012-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: log4r
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
78
94
  description: Static analysis of Cucumber tests made easy.
79
95
  email:
80
96
  - morrow748@gmail.com
@@ -84,6 +100,7 @@ extra_rdoc_files: []
84
100
  files:
85
101
  - .gitignore
86
102
  - Gemfile
103
+ - History.rdoc
87
104
  - LICENSE
88
105
  - README.rdoc
89
106
  - Rakefile
@@ -112,6 +129,7 @@ files:
112
129
  - features/support/transforms.rb
113
130
  - lib/cucumber_analytics.rb
114
131
  - lib/cucumber_analytics/feature_element.rb
132
+ - lib/cucumber_analytics/logging.rb
115
133
  - lib/cucumber_analytics/outline_example.rb
116
134
  - lib/cucumber_analytics/parsed_background.rb
117
135
  - lib/cucumber_analytics/parsed_directory.rb