cucumber_analytics 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,16 @@
1
+ === Version 0.0.6 / 2013-01-07
2
+
3
+ * Improved support for example blocks in outlines.
4
+ * Modeling of empty feature files is now possible.
5
+ * Modeling of inherited tags has been added.
6
+
7
+
8
+ === Version 0.0.5 / 2012-12-16
9
+
10
+ * Bug fix: a missing 'require' statement that was causing loading erros has
11
+ been fixed.
12
+
13
+
1
14
  === Version 0.0.4 / 2012-12-13
2
15
 
3
16
  * Removed an unintentional gem dependency
@@ -0,0 +1,37 @@
1
+ Feature: Tests can be manipulated in various ways.
2
+
3
+
4
+ Acceptance criteria
5
+
6
+ Tests can be manipulated:
7
+ 1. outlines can have rows added and removed
8
+
9
+
10
+ Background: Test file setup.
11
+ Given the following feature file:
12
+ """
13
+ Feature: A feature containing our starting outline.
14
+
15
+ Scenario Outline:
16
+ Given this *parameterized* step takes a table:
17
+ | <param1> |
18
+ | <param2> |
19
+ Then I don't really need another step
20
+ Examples: Only one row to start with
21
+ | param1 | param2 |
22
+ | x | y |
23
+ """
24
+ And parameter delimiters of "*" and "*"
25
+ And the file is read
26
+
27
+ Scenario: Rows can be added to an outline
28
+ When the test example block has the following rows added to it:
29
+ | 1,2 |
30
+ Then the test example block rows are as follows:
31
+ | x,y |
32
+ | 1,2 |
33
+
34
+ Scenario: Rows can be removed from an outline
35
+ When the test example block has the following rows removed from it:
36
+ | x,y |
37
+ Then the test example block has no rows
@@ -0,0 +1,100 @@
1
+ Feature: Example elements can be modeled.
2
+
3
+
4
+ Acceptance criteria
5
+
6
+ All conceptual pieces of an Examples block can be modeled:
7
+ 1. the examples' name
8
+ 2. the examples' description
9
+ 3. the examples' parameters
10
+ 4. the examples' rows
11
+ 5. the examples' tags
12
+ 6. the examples's applied tags
13
+
14
+
15
+ Background: Test file setup.
16
+ Given the following feature file:
17
+ """
18
+ @a_feature_level_tag
19
+ Feature: The test feature name.
20
+
21
+ @outline_tag
22
+ Scenario Outline: The scenario outline's name.
23
+ Given this *parameterized* step takes a table:
24
+ | <param1> |
25
+ | <param2> |
26
+ Then I don't really need another step
27
+
28
+ Examples: text describing the significance of the examples
29
+ Anything besides the | that starts a row should be valid
30
+ description at this point in the test. YMMV
31
+ | param1 | param2 | extra param |
32
+ #A more random comment
33
+ | x | y | ? |
34
+ | 1 | 2 | 3 |
35
+ @example_tag @another_one
36
+ Examples: some examples with different significance and a tag
37
+
38
+ Words, words, words, words,
39
+
40
+ why so many words?
41
+ #
42
+
43
+ | param1 |
44
+ #
45
+
46
+ #
47
+ | a |
48
+ Examples:
49
+ """
50
+ And parameter delimiters of "*" and "*"
51
+ When the file is read
52
+
53
+
54
+ Scenario: The examples' name is modeled.
55
+ Then the test example block "1" is found to have the following properties:
56
+ | name | text describing the significance of the examples |
57
+ And the test example block "2" is found to have the following properties:
58
+ | name | some examples with different significance and a tag |
59
+ And the test example block "3" is found to have the following properties:
60
+ | name | |
61
+
62
+
63
+ Scenario: The examples' description is modeled.
64
+ Then the test example block "1" descriptive lines are as follows:
65
+ | Anything besides the \| that starts a row should be valid |
66
+ | description at this point in the test. YMMV |
67
+ And the test example block "2" descriptive lines are as follows:
68
+ | Words, words, words, words, |
69
+ | why so many words? |
70
+ And the test example block "3" has no descriptive lines
71
+
72
+ Scenario: The examples' tags are modeled.
73
+ Then the test example block "1" has no tags
74
+ And the test example block "2" is found to have the following tags:
75
+ | @example_tag |
76
+ | @another_one |
77
+ And the test example block "3" has no tags
78
+
79
+ Scenario: The examples' applied tags are modeled.
80
+ Then the test example block "2" is found to have the following applied tags:
81
+ | @a_feature_level_tag |
82
+ | @outline_tag |
83
+
84
+ Scenario: The examples' parameters are modeled.
85
+ Then the test example block "1" parameters are as follows:
86
+ | param1 |
87
+ | param2 |
88
+ | extra param |
89
+ And the test example block "2" parameters are as follows:
90
+ | param1 |
91
+ And the test example block "3" has no parameters
92
+
93
+
94
+ Scenario: The examples' rows are modeled.
95
+ Then the test example block "1" rows are as follows:
96
+ | x,y,? |
97
+ | 1,2,3 |
98
+ And the test example block "2" rows are as follows:
99
+ | a |
100
+ And the test example block "3" has no rows
@@ -6,7 +6,7 @@ Feature: Feature files can be modeled.
6
6
  All conceptual pieces of a .feature file can be modeled:
7
7
  1. the files's name
8
8
  2. the file's full path
9
- 3. the file's features (only one per file)
9
+ 3. the file's features (one or zero per file)
10
10
 
11
11
 
12
12
  Background: Test file setup.
@@ -20,18 +20,29 @@ Feature: Feature files can be modeled.
20
20
  Feature: The second test feature
21
21
  Just a dummy feature.
22
22
  """
23
+ And the following feature file "why_would_you_make_an_empty_file.feature":
24
+ """
25
+ """
23
26
  When the file "test_file_1.feature" is read
24
27
  And the file "test_file_2.feature" is read
28
+ And the file "why_would_you_make_an_empty_file.feature" is read
25
29
 
26
30
 
27
31
  Scenario: The file's feature is modeled.
28
32
  Then file "1" is found to have the following properties:
29
33
  | name | test_file_1.feature |
30
34
  | path | path_to/test_file_1.feature |
35
+ | feature_count | 1 |
31
36
  And file "1" features are as follows:
32
37
  | The first test feature |
33
38
  Then file "2" is found to have the following properties:
34
39
  | name | test_file_2.feature |
35
40
  | path | path_to/test_file_2.feature |
41
+ | feature_count | 1 |
36
42
  And file "2" features are as follows:
37
43
  | The second test feature |
44
+ Then file "3" is found to have the following properties:
45
+ | name | why_would_you_make_an_empty_file.feature |
46
+ | path | path_to/why_would_you_make_an_empty_file.feature |
47
+ | feature_count | 0 |
48
+ And file "3" has no features
@@ -8,7 +8,8 @@ Feature: Scenario Outline elements can be modeled.
8
8
  2. the outline's description
9
9
  3. the outline's steps
10
10
  4. the outline's tags
11
- 5. the outline's example rows
11
+ 5. the outline's applied tags
12
+ 6. the outline's example blocks
12
13
 
13
14
 
14
15
  Background: Test file setup.
@@ -196,18 +197,11 @@ Feature: Scenario Outline elements can be modeled.
196
197
  Then the test is found to have the following tags:
197
198
  | @outline_tag |
198
199
 
199
- Scenario Outline: The outline examples are modeled.
200
- Then "<outline>" example "<set>" has a "<name>"
201
- And "<outline>" example "<set>" descriptive lines are as follows:
202
- | <description1> |
203
- | <description2> |
204
- And "<outline>" example "<set>" tags are as follows:
205
- | <tag1> |
206
- | <tag2> |
207
- And "<outline>" example "<set>" rows are as follows:
208
- | <row1> |
209
- | <row2> |
210
- Examples:
211
- | outline | set | name | description1 | description2 | tag1 | tag2 | row1 | row2 |
212
- | 1 | 1 | text describing the significance of the examples | Anything besides the \| that starts a row should be valid | description at this point in the test. YMMV | | | \| param1 \| param2 \| | \| x \| y \| |
213
- | 1 | 2 | some examples with different significance and a tag | Words, words, words, words, | why so many words? | @example_tag | @another_one | \| param1 \| param2 \| | \| a \| b \| |
200
+ Scenario: The outline applied tags are modeled.
201
+ Then the test is found to have the following applied tags:
202
+ | @a_feature_level_tag |
203
+
204
+ Scenario: The outline example blocks are modeled.
205
+ And the test example blocks are as follows:
206
+ | text describing the significance of the examples |
207
+ | some examples with different significance and a tag |
@@ -8,6 +8,7 @@ Feature: Scenario elements can be modeled.
8
8
  2. the scenario's description
9
9
  3. the scenario's steps
10
10
  4. the scenario's tags
11
+ 5. the scenario's applied tags
11
12
 
12
13
 
13
14
  Background: Test file setup.
@@ -177,3 +178,7 @@ Feature: Scenario elements can be modeled.
177
178
  | @a_tag |
178
179
  | @another_tag |
179
180
  | @yet_another_tag |
181
+
182
+ Scenario: The scenario applied tags are modeled.
183
+ Then the test is found to have the following applied tags:
184
+ | @a_feature_level_tag |
@@ -3,7 +3,10 @@ Then /^(?:the )?feature(?: "([^"]*)")? is found to have the following properties
3
3
  properties = properties.rows_hash
4
4
 
5
5
  properties.each do |property, expected_value|
6
- assert expected_value == @parsed_files[file - 1].feature.send(property.to_sym).to_s
6
+ expected = expected_value
7
+ actual = @parsed_files[file - 1].feature.send(property.to_sym).to_s
8
+
9
+ assert(actual == expected, "Expected: #{expected}\n but was: #{actual}")
7
10
  end
8
11
  end
9
12
 
@@ -16,3 +16,9 @@ When /^(?:the )?file(?: "([^"]*)")? features are as follows:$/ do |file, feature
16
16
 
17
17
  assert @parsed_files[file - 1].feature.name == feature.raw.flatten.first
18
18
  end
19
+
20
+ When /^(?:the )?file(?: "([^"]*)")? has no features$/ do |file|
21
+ file ||= 1
22
+
23
+ assert @parsed_files[file - 1].feature.nil?
24
+ end
@@ -1,26 +1,141 @@
1
- Then /^(?:feature "([^"]*)" )?"([^"]*)" example "([^"]*)" has a "([^"]*)"$/ do |file, test, example, name|
1
+ When /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example blocks are as follows:$/ do |file, test, names|
2
2
  file ||= 1
3
+ test ||= 1
3
4
 
4
- assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].name == name
5
+ names = names.raw.flatten
6
+
7
+ assert @parsed_files[file - 1].feature.tests[test - 1].examples.collect { |example| example.name } == names
5
8
  end
6
9
 
7
- When /^(?:feature "([^"]*)" )?"([^"]*)" example "([^"]*)" descriptive lines are as follows:$/ do |file, test, example, lines|
10
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? is found to have the following properties:$/ do |file, test, example, properties|
8
11
  file ||= 1
9
- lines = lines.raw.flatten.delete_if { |line| line == '' }
12
+ test ||= 1
13
+ example ||= 1
14
+
15
+ properties = properties.rows_hash
16
+
17
+ properties.each do |property, value|
18
+ assert value == @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].send(property.to_sym).to_s
19
+ end
20
+ end
21
+
22
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? descriptive lines are as follows:$/ do |file, test, example, lines|
23
+ file ||= 1
24
+ test ||= 1
25
+ example ||= 1
26
+
27
+ lines = lines.raw.flatten
10
28
 
11
29
  assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].description == lines
12
30
  end
13
31
 
14
- When /^(?:feature "([^"]*)" )?"([^"]*)" example "([^"]*)" tags are as follows:$/ do |file, test, example, tags|
32
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? is found to have the following tags:$/ do |file, test, example, tags|
15
33
  file ||= 1
16
- tags = tags.raw.flatten.delete_if { |line| line == '' }
34
+ test ||= 1
35
+ example ||= 1
36
+
37
+ tags = tags.raw.flatten
17
38
 
18
39
  assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].tags == tags
19
40
  end
20
41
 
21
- When /^(?:feature "([^"]*)" )?"([^"]*)" example "([^"]*)" rows are as follows:$/ do |file, test, example, rows|
42
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? is found to have the following applied tags:$/ do |file, test, example, tags|
43
+ file ||= 1
44
+ test ||= 1
45
+ example ||= 1
46
+
47
+ tags = tags.raw.flatten
48
+
49
+ expected = tags.sort
50
+ actual = @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].applied_tags.sort
51
+
52
+ assert(actual == expected, "Expected: #{expected}\n but was: #{actual}")
53
+ end
54
+
55
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? has no tags$/ do |file, test, example|
22
56
  file ||= 1
57
+ test ||= 1
58
+ example ||= 1
59
+
60
+ assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].tags == []
61
+ end
62
+
63
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? rows are as follows:$/ do |file, test, example, rows|
64
+ file ||= 1
65
+ test ||= 1
66
+ example ||= 1
67
+
68
+ rows = rows.raw.flatten
69
+ examples = @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1]
70
+
71
+ expected = rows.collect { |row| row.split(',') }.collect { |row| Hash[examples.parameters.zip(row)] }
72
+ actual = examples.rows
73
+
74
+ assert(actual == expected, "Expected: #{expected}\n but was: #{actual}")
75
+ end
76
+
77
+ When /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? has the following rows added to it:$/ do |file, test, example, rows|
78
+ file ||= 1
79
+ test ||= 1
80
+ example ||= 1
81
+
23
82
  rows = rows.raw.flatten
24
83
 
25
- assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].rows == rows
84
+ rows.each do |row|
85
+ row = row.split(',')
86
+ @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].add_row(row)
87
+ end
88
+ end
89
+
90
+ When /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? has the following rows removed from it:$/ do |file, test, example, rows|
91
+ file ||= 1
92
+ test ||= 1
93
+ example ||= 1
94
+
95
+ rows = rows.raw.flatten
96
+
97
+ rows.each do |row|
98
+ row = row.split(',')
99
+ @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].remove_row(row)
100
+ end
101
+ end
102
+
103
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? parameters are as follows:$/ do |file, test, example, parameters|
104
+ file ||= 1
105
+ test ||= 1
106
+ example ||= 1
107
+
108
+ parameters = parameters.raw.flatten
109
+
110
+ expected = parameters
111
+ actual =@parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].parameters
112
+
113
+ assert(actual == expected, "Expected: #{expected}\n but was: #{actual}")
114
+ end
115
+
116
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? has no descriptive lines$/ do |file, test, example|
117
+ file ||= 1
118
+ test ||= 1
119
+ example ||= 1
120
+
121
+ assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].description == []
122
+ end
123
+
124
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? has no parameters$/ do |file, test, example|
125
+ file ||= 1
126
+ test ||= 1
127
+ example ||= 1
128
+
129
+ assert @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].parameters == []
130
+ end
131
+
132
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? example block(?: "([^"]*)")? has no rows$/ do |file, test, example|
133
+ file ||= 1
134
+ test ||= 1
135
+ example ||= 1
136
+
137
+ expected = []
138
+ actual = @parsed_files[file - 1].feature.tests[test - 1].examples[example - 1].rows
139
+
140
+ assert(actual == expected, "Expected: #{expected}\n but was: #{actual}")
26
141
  end
@@ -52,6 +52,16 @@ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? is found to have the
52
52
  assert @parsed_files[file - 1].feature.tests[test - 1].tags == tags.raw.flatten
53
53
  end
54
54
 
55
+ Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? is found to have the following applied tags:$/ do |file, test, tags|
56
+ file ||= 1
57
+ test ||= 1
58
+
59
+ expected = tags.raw.flatten
60
+ actual = @parsed_files[file - 1].feature.tests[test - 1].applied_tags
61
+
62
+ assert(actual == expected, "Expected: #{expected}\n but was: #{actual}")
63
+ end
64
+
55
65
  Then /^(?:the )?(?:feature "([^"]*)" )?test(?: "([^"]*)")? step "([^"]*)" has the following block:$/ do |file, test, step, block|
56
66
  file ||= 1
57
67
  test ||= 1
@@ -4,6 +4,8 @@ module CucumberAnalytics
4
4
 
5
5
  attr_accessor :tags
6
6
  attr_accessor :rows
7
+ attr_accessor :parameters
8
+ attr_accessor :parent_element
7
9
 
8
10
 
9
11
  # Creates a new OutlineExample object and, if *source_lines* is provided,
@@ -19,10 +21,43 @@ module CucumberAnalytics
19
21
 
20
22
  @tags = []
21
23
  @rows = []
24
+ @parameters = []
22
25
 
23
26
  parse_example(source_lines) if source_lines
24
27
  end
25
28
 
29
+ # Adds a row to the example block. The row can be given as a Hash of column
30
+ # headers and their corresponding values or as an Array of values which
31
+ # will be assigned in order.
32
+ def add_row(row)
33
+ if row.is_a?(Array)
34
+ @rows << Hash[@parameters.zip(row.collect { |value| value.strip })]
35
+ else
36
+ @rows << row
37
+ end
38
+ end
39
+
40
+ # Removes a row from the example block. The row can be given as a Hash of
41
+ # column headers and their corresponding values or as an Array of values
42
+ # which will be assigned in order.
43
+ def remove_row(row)
44
+ if row.is_a?(Array)
45
+ location = @rows.index { |row_hash| row_hash.values_at(*@parameters) == row }
46
+ else
47
+ location = @rows.index { |row_hash| row_hash == row }
48
+ end
49
+ @rows.delete_at(location) if location
50
+ end
51
+
52
+ # Returns tags which are applicable to the example block which have been
53
+ # inherited from the outline level.
54
+ def applied_tags
55
+ additional_tags = @parent_element.tags
56
+ additional_tags.concat(@parent_element.applied_tags) if @parent_element.respond_to?(:applied_tags)
57
+
58
+ additional_tags
59
+ end
60
+
26
61
 
27
62
  private
28
63
 
@@ -33,8 +68,24 @@ module CucumberAnalytics
33
68
  parse_feature_element_tags(source_lines)
34
69
  parse_feature_element(source_lines)
35
70
 
36
- source_lines.delete_if { |line| World.ignored_line?(line)}
37
- rows.concat source_lines.collect { |line| line.strip }
71
+ source_lines.delete_if { |line| World.ignored_line?(line) }
72
+
73
+ unless source_lines.empty?
74
+ @parameters = source_lines.shift.split('|')
75
+ @parameters.shift
76
+ @parameters.pop
77
+
78
+ @parameters.collect! { |param| param.strip }
79
+ end
80
+
81
+ unless source_lines.empty?
82
+ @rows = source_lines.collect { |row| row.split('|') }.collect do |row|
83
+ row.shift
84
+ row.collect { |value| value.strip }
85
+ end
86
+
87
+ @rows.collect! { |row| Hash[@parameters.zip(row)] }
88
+ end
38
89
  end
39
90
 
40
91
  def parse_feature_element_description(source_lines)
@@ -34,6 +34,8 @@ module CucumberAnalytics
34
34
  @feature_files.count
35
35
  end
36
36
 
37
+ # Returns the immediate child elements of the directory (i.e. its .feature
38
+ # files and .feature file containing sub-directories).
37
39
  def contains
38
40
  @feature_files + @feature_directories
39
41
  end
@@ -54,11 +54,13 @@ module CucumberAnalytics
54
54
  def test_case_count
55
55
  scenario_count + outlines.reduce(0) { |outline_sum, outline|
56
56
  outline_sum += outline.examples.reduce(0) { |example_sum, example|
57
- example_sum += example.rows.count - 1
57
+ example_sum += example.rows.count
58
58
  }
59
59
  }
60
60
  end
61
61
 
62
+ # Returns the immediate child elements of the feature (i.e. its background
63
+ # and tests).
62
64
  def contains
63
65
  [@background] + @tests
64
66
  end
@@ -81,7 +83,7 @@ module CucumberAnalytics
81
83
  CucumberAnalytics::Logging.logger.debug(line.chomp)
82
84
  end
83
85
 
84
- source_lines.delete_if { |line| World.ignored_line?(line)}
86
+ source_lines.delete_if { |line| World.ignored_line?(line) }
85
87
 
86
88
  until source_lines.first =~ /^\s*(?:(?:Scenario: )|(?:Scenario Outline: )|(?:Background: )|(?:@ ))/ or
87
89
  source_lines.empty?
@@ -23,16 +23,24 @@ module CucumberAnalytics
23
23
  @file
24
24
  end
25
25
 
26
+ # Returns the immediate child elements of the feature file(i.e. its
27
+ # feature).
26
28
  def contains
27
29
  [@feature]
28
30
  end
29
31
 
32
+ # Returns the number of features contained in the file.
33
+ def feature_count
34
+ @feature.nil? ? 0 : 1
35
+ end
36
+
30
37
 
31
38
  private
32
39
 
33
40
 
34
41
  def parse_file(file_parsed)
35
42
  CucumberAnalytics::Logging.logger.info('ParsedFile#parse_file')
43
+ CucumberAnalytics::Logging.logger.debug("Parsing file: #{file_parsed}")
36
44
 
37
45
  @file = file_parsed
38
46
 
@@ -43,7 +51,9 @@ module CucumberAnalytics
43
51
  File.open(@file, 'r') { |file| file_lines = file.readlines }
44
52
 
45
53
  # collect feature tag lines
46
- until file_lines.first =~ /^s*Feature:/
54
+ until file_lines.first =~ /^s*Feature:/ or
55
+ file_lines.empty?
56
+
47
57
  feature_lines << file_lines.first
48
58
  file_lines.shift
49
59
  end
@@ -57,7 +67,7 @@ module CucumberAnalytics
57
67
  end
58
68
 
59
69
  # create a new feature bases on the collected lines
60
- @feature = ParsedFeature.new(feature_lines)
70
+ @feature = feature_lines.empty? ? nil : ParsedFeature.new(feature_lines)
61
71
 
62
72
  if file_lines.first =~ /^\s*Background:/
63
73
 
@@ -71,7 +81,7 @@ module CucumberAnalytics
71
81
 
72
82
  # collect everything else up to the first test
73
83
  until file_lines.first =~ /^\s*(?:@|Scenario:|(?:Scenario Outline:))/ or
74
- file_lines.empty?
84
+ file_lines.empty?
75
85
 
76
86
  if file_lines.first =~ /^\s*"""/
77
87
  background_lines.concat(extract_doc_string!(file_lines))
@@ -145,6 +155,7 @@ module CucumberAnalytics
145
155
  next_test = ParsedScenario.new(test_lines)
146
156
  end
147
157
 
158
+ next_test.parent_element = @feature
148
159
  @feature.tests << next_test
149
160
  end
150
161
  end
@@ -3,6 +3,7 @@ module CucumberAnalytics
3
3
 
4
4
 
5
5
  attr_accessor :tags
6
+ attr_accessor :parent_element
6
7
 
7
8
 
8
9
  # Creates a new ParsedScenario object and, if *source_lines* is provided,
@@ -21,6 +22,15 @@ module CucumberAnalytics
21
22
  parse_scenario(source_lines) if source_lines
22
23
  end
23
24
 
25
+ # Returns tags which are applicable to the scenario which have been
26
+ # inherited from the feature level.
27
+ def applied_tags
28
+ additional_tags = @parent_element.tags
29
+ additional_tags.concat(@parent_element.applied_tags) if @parent_element.respond_to?(:applied_tags)
30
+
31
+ additional_tags
32
+ end
33
+
24
34
 
25
35
  private
26
36
 
@@ -4,6 +4,8 @@ module CucumberAnalytics
4
4
 
5
5
  attr_accessor :tags
6
6
  attr_accessor :examples
7
+ attr_accessor :parent_element
8
+
7
9
 
8
10
  # Creates a new ParsedScenarioOutline object and, if *source_lines* is
9
11
  # provided, populates the object.
@@ -22,10 +24,21 @@ module CucumberAnalytics
22
24
  parse_outline(source_lines) if source_lines
23
25
  end
24
26
 
27
+ # Returns the immediate child elements of the outline (i.e. its example
28
+ # blocks).
25
29
  def contains
26
30
  @examples
27
31
  end
28
32
 
33
+ # Returns tags which are applicable to the outline which have been
34
+ # inherited from the feature level.
35
+ def applied_tags
36
+ additional_tags = @parent_element.tags
37
+ additional_tags.concat(@parent_element.applied_tags) if @parent_element.respond_to?(:applied_tags)
38
+
39
+ additional_tags
40
+ end
41
+
29
42
 
30
43
  private
31
44
 
@@ -97,7 +110,10 @@ module CucumberAnalytics
97
110
  end
98
111
 
99
112
  # use the collected lines to create an example
100
- @examples << OutlineExample.new(example_lines)
113
+ example = OutlineExample.new(example_lines)
114
+ example.parent_element = self
115
+
116
+ @examples << example
101
117
  end
102
118
  end
103
119
 
@@ -1,3 +1,3 @@
1
1
  module CucumberAnalytics
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  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.5
4
+ version: 0.0.6
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-12-16 00:00:00.000000000 Z
12
+ date: 2013-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -79,8 +79,10 @@ files:
79
79
  - features/analysis/tag_collection.feature
80
80
  - features/analysis/test_collection.feature
81
81
  - features/analysis/test_comparison.feature
82
+ - features/analysis/test_manipulation.feature
82
83
  - features/modeling/background_modeling.feature
83
84
  - features/modeling/directory_modeling.feature
85
+ - features/modeling/example_modeling.feature
84
86
  - features/modeling/feature_file_modeling.feature
85
87
  - features/modeling/feature_modeling.feature
86
88
  - features/modeling/outline_modeling.feature
@@ -141,8 +143,10 @@ test_files:
141
143
  - features/analysis/tag_collection.feature
142
144
  - features/analysis/test_collection.feature
143
145
  - features/analysis/test_comparison.feature
146
+ - features/analysis/test_manipulation.feature
144
147
  - features/modeling/background_modeling.feature
145
148
  - features/modeling/directory_modeling.feature
149
+ - features/modeling/example_modeling.feature
146
150
  - features/modeling/feature_file_modeling.feature
147
151
  - features/modeling/feature_modeling.feature
148
152
  - features/modeling/outline_modeling.feature