cucumber_analytics 0.0.9 → 1.0.0
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.
- checksums.yaml +15 -0
- data/History.rdoc +16 -0
- data/README.rdoc +5 -3
- data/Rakefile +7 -2
- data/cucumber_analytics.gemspec +7 -5
- data/features/analysis/step_collection.feature +44 -45
- data/features/modeling/background_modeling.feature +14 -144
- data/features/modeling/directory_modeling.feature +3 -2
- data/features/modeling/doc_string_modeling.feature +46 -0
- data/features/modeling/example_modeling.feature +13 -34
- data/features/modeling/feature_file_modeling.feature +3 -2
- data/features/modeling/feature_modeling.feature +18 -80
- data/features/modeling/outline_modeling.feature +25 -164
- data/features/modeling/scenario_modeling.feature +17 -144
- data/features/modeling/step_modeling.feature +68 -0
- data/features/modeling/table_modeling.feature +41 -0
- data/features/step_definitions/background_steps.rb +12 -11
- data/features/step_definitions/directory_steps.rb +6 -3
- data/features/step_definitions/doc_string_steps.rb +50 -0
- data/features/step_definitions/{file_steps.rb → feature_file_steps.rb} +8 -2
- data/features/step_definitions/feature_steps.rb +8 -4
- data/features/step_definitions/outline_steps.rb +12 -6
- data/features/step_definitions/setup_steps.rb +2 -2
- data/features/step_definitions/spec_steps.rb +6 -3
- data/features/step_definitions/step_steps.rb +91 -0
- data/features/step_definitions/table_steps.rb +10 -0
- data/features/step_definitions/test_steps.rb +6 -10
- data/features/step_definitions/world_steps.rb +28 -19
- data/features/support/env.rb +0 -2
- data/lib/cucumber_analytics/background.rb +16 -0
- data/lib/cucumber_analytics/containing.rb +18 -0
- data/lib/cucumber_analytics/directory.rb +83 -0
- data/lib/cucumber_analytics/doc_string.rb +55 -0
- data/lib/cucumber_analytics/example.rb +100 -0
- data/lib/cucumber_analytics/feature.rb +120 -0
- data/lib/cucumber_analytics/feature_element.rb +22 -40
- data/lib/cucumber_analytics/feature_file.rb +74 -0
- data/lib/cucumber_analytics/outline.rb +49 -0
- data/lib/cucumber_analytics/parsing.rb +30 -0
- data/lib/cucumber_analytics/scenario.rb +31 -0
- data/lib/cucumber_analytics/step.rb +142 -32
- data/lib/cucumber_analytics/table.rb +51 -0
- data/lib/cucumber_analytics/taggable.rb +35 -0
- data/lib/cucumber_analytics/test_element.rb +36 -91
- data/lib/cucumber_analytics/version.rb +1 -1
- data/lib/cucumber_analytics/world.rb +109 -153
- data/lib/cucumber_analytics.rb +12 -8
- data/spec/integration/background_integration_spec.rb +18 -0
- data/spec/integration/directory_integration_spec.rb +24 -0
- data/spec/{feature_spec.rb → integration/feature_file_integration_spec.rb} +5 -5
- data/spec/integration/feature_integration_spec.rb +86 -0
- data/spec/integration/outline_integration_spec.rb +22 -0
- data/spec/integration/scenario_integration_spec.rb +18 -0
- data/spec/integration/step_integration_spec.rb +116 -0
- data/spec/integration/world_integration_spec.rb +40 -0
- data/spec/spec_helper.rb +7 -3
- data/spec/unit/background_unit_spec.rb +22 -0
- data/spec/unit/bare_bones_unit_specs.rb +13 -0
- data/spec/unit/containing_element_unit_specs.rb +17 -0
- data/spec/unit/directory_unit_spec.rb +91 -0
- data/spec/unit/doc_string_unit_spec.rb +65 -0
- data/spec/unit/example_unit_spec.rb +171 -0
- data/spec/unit/feature_element_unit_spec.rb +19 -0
- data/spec/unit/feature_element_unit_specs.rb +39 -0
- data/spec/unit/feature_file_unit_spec.rb +82 -0
- data/spec/unit/feature_unit_spec.rb +81 -0
- data/spec/unit/nested_element_unit_specs.rb +24 -0
- data/spec/unit/outline_unit_spec.rb +56 -0
- data/spec/unit/parsing_unit_spec.rb +21 -0
- data/spec/unit/prepopulated_unit_specs.rb +13 -0
- data/spec/unit/scenario_unit_spec.rb +36 -0
- data/spec/unit/step_unit_spec.rb +231 -0
- data/spec/unit/table_unit_spec.rb +52 -0
- data/spec/unit/taggable_unit_spec.rb +63 -0
- data/spec/unit/tagged_element_unit_specs.rb +48 -0
- data/spec/unit/test_element_unit_spec.rb +40 -0
- data/spec/unit/test_element_unit_specs.rb +31 -0
- data/spec/unit/world_unit_spec.rb +167 -0
- metadata +106 -41
- data/lib/cucumber_analytics/logging.rb +0 -28
- data/lib/cucumber_analytics/outline_example.rb +0 -110
- data/lib/cucumber_analytics/parsed_background.rb +0 -45
- data/lib/cucumber_analytics/parsed_directory.rb +0 -78
- data/lib/cucumber_analytics/parsed_feature.rb +0 -97
- data/lib/cucumber_analytics/parsed_file.rb +0 -199
- data/lib/cucumber_analytics/parsed_scenario.rb +0 -67
- data/lib/cucumber_analytics/parsed_scenario_outline.rb +0 -122
- data/spec/background_spec.rb +0 -23
- data/spec/directory_spec.rb +0 -18
- data/spec/example_spec.rb +0 -37
- data/spec/file_spec.rb +0 -20
- data/spec/outline_spec.rb +0 -32
- data/spec/scenario_spec.rb +0 -33
- data/spec/step_spec.rb +0 -24
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling the Doc String of a Step.
|
|
4
|
+
|
|
5
|
+
class DocString
|
|
6
|
+
|
|
7
|
+
# The parent object that contains *self*
|
|
8
|
+
attr_accessor :parent_element
|
|
9
|
+
|
|
10
|
+
# The content type associated with the doc string
|
|
11
|
+
attr_accessor :content_type
|
|
12
|
+
|
|
13
|
+
# The contents of the doc string
|
|
14
|
+
attr_accessor :contents
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Creates a new DocString object and, if *source* is provided, populates
|
|
18
|
+
# the object.
|
|
19
|
+
def initialize(source = nil)
|
|
20
|
+
@contents = []
|
|
21
|
+
|
|
22
|
+
parsed_doc_string = process_source(source)
|
|
23
|
+
|
|
24
|
+
build_doc_string(parsed_doc_string) if parsed_doc_string
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def process_source(source)
|
|
32
|
+
case
|
|
33
|
+
when source.is_a?(String)
|
|
34
|
+
parse_doc_string(source)
|
|
35
|
+
else
|
|
36
|
+
source
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def parse_doc_string(source_text)
|
|
41
|
+
base_file_string = "Feature:\nScenario:\n* step\n"
|
|
42
|
+
source_text = base_file_string + source_text
|
|
43
|
+
|
|
44
|
+
parsed_file = Parsing::parse_text(source_text)
|
|
45
|
+
|
|
46
|
+
parsed_file.first['elements'].first['steps'].first['doc_string']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def build_doc_string(doc_string)
|
|
50
|
+
@content_type = doc_string['content_type'] == "" ? nil : doc_string['content_type']
|
|
51
|
+
@contents = doc_string['value'].split($/)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Examples table.
|
|
4
|
+
|
|
5
|
+
class Example < FeatureElement
|
|
6
|
+
|
|
7
|
+
include Taggable
|
|
8
|
+
|
|
9
|
+
# The argument rows in the example table
|
|
10
|
+
attr_accessor :rows
|
|
11
|
+
|
|
12
|
+
# The parameters for the example table
|
|
13
|
+
attr_accessor :parameters
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Creates a new Example object and, if *source* is provided,
|
|
17
|
+
# populates the object.
|
|
18
|
+
def initialize(source = nil)
|
|
19
|
+
parsed_example = process_source(source)
|
|
20
|
+
|
|
21
|
+
super(parsed_example)
|
|
22
|
+
|
|
23
|
+
@tags = []
|
|
24
|
+
@rows = []
|
|
25
|
+
@parameters = []
|
|
26
|
+
|
|
27
|
+
build_example(parsed_example) if parsed_example
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Adds a row to the example table. The row can be given as a Hash of
|
|
31
|
+
# parameters and their corresponding values or as an Array of values which
|
|
32
|
+
# will be assigned in order.
|
|
33
|
+
def add_row(row)
|
|
34
|
+
case
|
|
35
|
+
when row.is_a?(Array)
|
|
36
|
+
@rows << Hash[@parameters.zip(row.collect { |value| value.strip })]
|
|
37
|
+
when row.is_a?(Hash)
|
|
38
|
+
@rows << row.each_value { |value| value.strip! }
|
|
39
|
+
else
|
|
40
|
+
raise(ArgumentError, "Can only add row from a Hash or an Array but received #{row.class}")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Removes a row from the example table. The row can be given as a Hash of
|
|
45
|
+
# parameters and their corresponding values or as an Array of values
|
|
46
|
+
# which will be assigned in order.
|
|
47
|
+
def remove_row(row)
|
|
48
|
+
case
|
|
49
|
+
when row.is_a?(Array)
|
|
50
|
+
location = @rows.index { |row_hash| row_hash.values_at(*@parameters) == row.collect { |value| value.strip } }
|
|
51
|
+
when row.is_a?(Hash)
|
|
52
|
+
location = @rows.index { |row_hash| row_hash == row.each_value { |value| value.strip! } }
|
|
53
|
+
else
|
|
54
|
+
raise(ArgumentError, "Can only remove row from a Hash or an Array but received #{row.class}")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@rows.delete_at(location) if location
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def process_source(source)
|
|
65
|
+
case
|
|
66
|
+
when source.is_a?(String)
|
|
67
|
+
parse_example(source)
|
|
68
|
+
else
|
|
69
|
+
source
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def parse_example(source_text)
|
|
74
|
+
base_file_string = "Feature: Fake feature to parse\nScenario Outline:\n* fake step\n"
|
|
75
|
+
source_text = base_file_string + source_text
|
|
76
|
+
|
|
77
|
+
parsed_file = Parsing::parse_text(source_text)
|
|
78
|
+
|
|
79
|
+
parsed_file.first['elements'].first['examples'].first
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def build_example(parsed_example)
|
|
83
|
+
populate_element_tags(parsed_example)
|
|
84
|
+
populate_example_parameters(parsed_example)
|
|
85
|
+
populate_example_rows(parsed_example)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def populate_example_parameters(parsed_example)
|
|
89
|
+
@parameters = parsed_example['rows'].first['cells']
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def populate_example_rows(parsed_example)
|
|
93
|
+
parsed_example['rows'].shift
|
|
94
|
+
parsed_example['rows'].each do |row|
|
|
95
|
+
@rows << Hash[@parameters.zip(row['cells'])]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Feature.
|
|
4
|
+
|
|
5
|
+
class Feature < FeatureElement
|
|
6
|
+
|
|
7
|
+
include Taggable
|
|
8
|
+
include Containing
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# The Background object contained by the Feature
|
|
12
|
+
attr_accessor :background
|
|
13
|
+
|
|
14
|
+
# The TestElement objects contained by the Feature
|
|
15
|
+
attr_accessor :tests
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Creates a new Feature object and, if *source* is provided, populates the
|
|
19
|
+
# object.
|
|
20
|
+
def initialize(source = nil)
|
|
21
|
+
parsed_feature = process_source(source)
|
|
22
|
+
|
|
23
|
+
super(parsed_feature)
|
|
24
|
+
|
|
25
|
+
@tags = []
|
|
26
|
+
@tests = []
|
|
27
|
+
|
|
28
|
+
build_feature(parsed_feature) if parsed_feature
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns true if the feature contains a background, false otherwise.
|
|
32
|
+
def has_background?
|
|
33
|
+
!@background.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Returns the scenarios contained in the feature.
|
|
37
|
+
def scenarios
|
|
38
|
+
@tests.select { |test| test.is_a? Scenario }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns the outlines contained in the feature.
|
|
42
|
+
def outlines
|
|
43
|
+
@tests.select { |test| test.is_a? Outline }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns the number of scenarios contained in the feature.
|
|
47
|
+
def scenario_count
|
|
48
|
+
scenarios.count
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns the number of outlines contained in the feature.
|
|
52
|
+
def outline_count
|
|
53
|
+
outlines.count
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns the number of tests contained in the feature.
|
|
57
|
+
def test_count
|
|
58
|
+
@tests.count
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns the number of test cases contained in the feature.
|
|
62
|
+
def test_case_count
|
|
63
|
+
scenario_count + outlines.reduce(0) { |outline_sum, outline|
|
|
64
|
+
outline_sum += outline.examples.reduce(0) { |example_sum, example|
|
|
65
|
+
example_sum += example.rows.count
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns the immediate child elements of the feature (i.e. its Background,
|
|
71
|
+
# Scenario, and Outline objects.
|
|
72
|
+
def contains
|
|
73
|
+
[@background] + @tests
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def process_source(source)
|
|
81
|
+
case
|
|
82
|
+
when source.is_a?(String)
|
|
83
|
+
parse_feature(source)
|
|
84
|
+
else
|
|
85
|
+
source
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def parse_feature(source_text)
|
|
90
|
+
parsed_file = Parsing::parse_text(source_text)
|
|
91
|
+
|
|
92
|
+
parsed_file.first
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_feature(parsed_feature)
|
|
96
|
+
populate_element_tags(parsed_feature)
|
|
97
|
+
populate_feature_elements(parsed_feature)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def populate_feature_elements(parsed_feature)
|
|
101
|
+
elements = parsed_feature['elements']
|
|
102
|
+
|
|
103
|
+
if elements
|
|
104
|
+
elements.each do |element|
|
|
105
|
+
case element['keyword']
|
|
106
|
+
when 'Scenario'
|
|
107
|
+
@tests << build_child_element(Scenario, element)
|
|
108
|
+
when 'Scenario Outline'
|
|
109
|
+
@tests << build_child_element(Outline, element)
|
|
110
|
+
when 'Background'
|
|
111
|
+
@background = build_child_element(Background, element)
|
|
112
|
+
else
|
|
113
|
+
raise(ArgumentError, "Unknown keyword: #{element['keyword']}")
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -1,62 +1,44 @@
|
|
|
1
1
|
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling an basic element of a feature.
|
|
4
|
+
|
|
2
5
|
class FeatureElement
|
|
3
6
|
|
|
7
|
+
# The name of the FeatureElement
|
|
8
|
+
attr_accessor :name
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
attr_accessor :parent_element
|
|
10
|
+
# The description of the FeatureElement
|
|
11
|
+
attr_accessor :description
|
|
8
12
|
|
|
13
|
+
# The parent object that contains *self*
|
|
14
|
+
attr_accessor :parent_element
|
|
9
15
|
|
|
10
|
-
# Creates a new FeatureElement object.
|
|
11
|
-
def initialize(source_lines = nil)
|
|
12
|
-
CucumberAnalytics::Logging.logger.info('FeatureElement#initialize')
|
|
13
16
|
|
|
17
|
+
# Creates a new FeatureElement object and, if *parsed_element* is provided,
|
|
18
|
+
# populates the object.
|
|
19
|
+
def initialize(parsed_element = nil)
|
|
14
20
|
@name = ''
|
|
15
21
|
@description =[]
|
|
22
|
+
|
|
23
|
+
build_feature_element(parsed_element) if parsed_element
|
|
16
24
|
end
|
|
17
25
|
|
|
18
26
|
|
|
19
27
|
private
|
|
20
28
|
|
|
21
29
|
|
|
22
|
-
def
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
parse_feature_element_name(source_lines)
|
|
26
|
-
parse_feature_element_description(source_lines)
|
|
30
|
+
def build_feature_element(parsed_element)
|
|
31
|
+
populate_feature_element_name(parsed_element)
|
|
32
|
+
populate_feature_element_description(parsed_element)
|
|
27
33
|
end
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
CucumberAnalytics::Logging.logger.info('FeatureElement#parse_feature_element_tags')
|
|
32
|
-
CucumberAnalytics::Logging.logger.debug('source lines')
|
|
33
|
-
source_lines.each do |line|
|
|
34
|
-
CucumberAnalytics::Logging.logger.debug(line.chomp)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
source_lines.take_while { |line| line !~ /^\s*(?:[A-Z a-z])+:/ }.tap do |tag_lines|
|
|
38
|
-
tag_lines.delete_if { |line| World.ignored_line?(line)}
|
|
39
|
-
|
|
40
|
-
tag_lines.join(' ').delete(' ').split('@').each do |tag|
|
|
41
|
-
@tags << "@#{tag.strip}"
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
@tags.shift
|
|
45
|
-
|
|
46
|
-
while source_lines.first !~ /^\s*(?:[A-Z a-z])+:/
|
|
47
|
-
source_lines.shift
|
|
48
|
-
end
|
|
35
|
+
def populate_feature_element_name(parsed_element)
|
|
36
|
+
@name = parsed_element['name']
|
|
49
37
|
end
|
|
50
38
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
source_lines.each do |line|
|
|
55
|
-
CucumberAnalytics::Logging.logger.debug(line.chomp)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
@name.replace source_lines.first.match(/^\s*(?:[A-Z a-z])+:(.*)/)[1].strip
|
|
59
|
-
source_lines.shift
|
|
39
|
+
def populate_feature_element_description(parsed_element)
|
|
40
|
+
@description = parsed_element['description'].split("\n").collect { |line| line.strip }
|
|
41
|
+
@description.delete('')
|
|
60
42
|
end
|
|
61
43
|
|
|
62
44
|
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber .feature file.
|
|
4
|
+
|
|
5
|
+
class FeatureFile
|
|
6
|
+
|
|
7
|
+
include Containing
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# The Feature objects contained by the FeatureFile
|
|
11
|
+
attr_accessor :features
|
|
12
|
+
|
|
13
|
+
# The parent object that contains *self*
|
|
14
|
+
attr_accessor :parent_element
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Creates a new FeatureFile object and, if *file_parsed* is provided,
|
|
18
|
+
# populates the object.
|
|
19
|
+
def initialize(file = nil)
|
|
20
|
+
@file = file
|
|
21
|
+
@features = []
|
|
22
|
+
|
|
23
|
+
if file
|
|
24
|
+
raise(ArgumentError, "Unknown file: #{file.inspect}") unless File.exists?(file)
|
|
25
|
+
|
|
26
|
+
parsed_file = parse_file(file)
|
|
27
|
+
|
|
28
|
+
build_file(parsed_file)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Returns the name of the file.
|
|
33
|
+
def name
|
|
34
|
+
File.basename(@file.gsub('\\', '/'))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns the path of the file.
|
|
38
|
+
def path
|
|
39
|
+
@file
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns the immediate child elements of the file(i.e. its Feature object).
|
|
43
|
+
def contains
|
|
44
|
+
@features
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Returns the number of features contained in the file.
|
|
48
|
+
def feature_count
|
|
49
|
+
@features.count
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns the Feature object contained by the FeatureFile.
|
|
53
|
+
def feature
|
|
54
|
+
@features.first
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def parse_file(file_to_parse)
|
|
62
|
+
source_text = IO.read(file_to_parse)
|
|
63
|
+
|
|
64
|
+
Parsing::parse_text(source_text)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def build_file(parsed_file)
|
|
68
|
+
unless parsed_file.empty?
|
|
69
|
+
@features << build_child_element(Feature, parsed_file.first)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Scenario Outline.
|
|
4
|
+
|
|
5
|
+
class Outline < TestElement
|
|
6
|
+
|
|
7
|
+
include Taggable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# The Example objects contained by the Outline
|
|
11
|
+
attr_accessor :examples
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Creates a new Outline object and, if *source* is provided, populates the
|
|
15
|
+
# object.
|
|
16
|
+
def initialize(source = nil)
|
|
17
|
+
parsed_outline = process_source(source)
|
|
18
|
+
|
|
19
|
+
super(parsed_outline)
|
|
20
|
+
|
|
21
|
+
@tags = []
|
|
22
|
+
@examples = []
|
|
23
|
+
|
|
24
|
+
build_outline(parsed_outline) if parsed_outline
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns the immediate child elements of the outline (i.e. its Example
|
|
28
|
+
# objects.
|
|
29
|
+
def contains
|
|
30
|
+
@examples + @steps
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def build_outline(parsed_outline)
|
|
38
|
+
populate_element_tags(parsed_outline)
|
|
39
|
+
populate_outline_examples(parsed_outline['examples']) if parsed_outline['examples']
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def populate_outline_examples(parsed_examples)
|
|
43
|
+
parsed_examples.each do |example|
|
|
44
|
+
@examples << build_child_element(Example, example)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'stringio'
|
|
2
|
+
require 'gherkin/formatter/json_formatter'
|
|
3
|
+
require 'gherkin'
|
|
4
|
+
|
|
5
|
+
module CucumberAnalytics
|
|
6
|
+
|
|
7
|
+
# A module providing source text parsing functionality.
|
|
8
|
+
|
|
9
|
+
module Parsing
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
|
|
13
|
+
# Parses the Cucumber feature given in *source_text* and returns an array
|
|
14
|
+
# containing the hash representation of its logical structure.
|
|
15
|
+
def parse_text(source_text)
|
|
16
|
+
raise(ArgumentError, "Cannot parse #{source_text.class} objects. Strings only.") unless source_text.is_a?(String)
|
|
17
|
+
|
|
18
|
+
io = StringIO.new
|
|
19
|
+
formatter = Gherkin::Formatter::JSONFormatter.new(io)
|
|
20
|
+
parser = Gherkin::Parser::Parser.new(formatter)
|
|
21
|
+
parser.parse(source_text, 'fake_file.txt', 0)
|
|
22
|
+
formatter.done
|
|
23
|
+
|
|
24
|
+
JSON.parse(io.string)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module CucumberAnalytics
|
|
2
|
+
|
|
3
|
+
# A class modeling a Cucumber Scenario.
|
|
4
|
+
|
|
5
|
+
class Scenario < TestElement
|
|
6
|
+
|
|
7
|
+
include Taggable
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Creates a new Scenario object and, if *source* is provided, populates the
|
|
11
|
+
# object.
|
|
12
|
+
def initialize(source = nil)
|
|
13
|
+
parsed_scenario = process_source(source)
|
|
14
|
+
|
|
15
|
+
super(parsed_scenario)
|
|
16
|
+
|
|
17
|
+
@tags = []
|
|
18
|
+
|
|
19
|
+
build_scenario(parsed_scenario) if parsed_scenario
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def build_scenario(scenario)
|
|
27
|
+
populate_element_tags(scenario)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|