cuke_modeler 0.0.1

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.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.simplecov +8 -0
  4. data/Gemfile +4 -0
  5. data/History.rdoc +3 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +73 -0
  8. data/Rakefile +38 -0
  9. data/cuke_modeler.gemspec +29 -0
  10. data/features/analysis/test_comparison.feature +123 -0
  11. data/features/analysis/test_manipulation.feature +37 -0
  12. data/features/modeling/background_modeling.feature +75 -0
  13. data/features/modeling/background_output.feature +130 -0
  14. data/features/modeling/directory_modeling.feature +120 -0
  15. data/features/modeling/directory_output.feature +13 -0
  16. data/features/modeling/doc_string_modeling.feature +63 -0
  17. data/features/modeling/doc_string_output.feature +71 -0
  18. data/features/modeling/example_modeling.feature +111 -0
  19. data/features/modeling/example_output.feature +192 -0
  20. data/features/modeling/feature_file_modeling.feature +64 -0
  21. data/features/modeling/feature_file_output.feature +13 -0
  22. data/features/modeling/feature_modeling.feature +164 -0
  23. data/features/modeling/feature_output.feature +244 -0
  24. data/features/modeling/outline_modeling.feature +100 -0
  25. data/features/modeling/outline_output.feature +197 -0
  26. data/features/modeling/row_modeling.feature +77 -0
  27. data/features/modeling/row_output.feature +27 -0
  28. data/features/modeling/scenario_modeling.feature +89 -0
  29. data/features/modeling/scenario_output.feature +147 -0
  30. data/features/modeling/step_modeling.feature +85 -0
  31. data/features/modeling/step_output.feature +52 -0
  32. data/features/modeling/table_modeling.feature +52 -0
  33. data/features/modeling/table_output.feature +42 -0
  34. data/features/modeling/table_row_modeling.feature +67 -0
  35. data/features/modeling/table_row_output.feature +27 -0
  36. data/features/modeling/tag_modeling.feature +58 -0
  37. data/features/modeling/tag_output.feature +16 -0
  38. data/features/step_definitions/action_steps.rb +3 -0
  39. data/features/step_definitions/background_steps.rb +81 -0
  40. data/features/step_definitions/directory_steps.rb +52 -0
  41. data/features/step_definitions/doc_string_steps.rb +63 -0
  42. data/features/step_definitions/feature_file_steps.rb +41 -0
  43. data/features/step_definitions/feature_steps.rb +96 -0
  44. data/features/step_definitions/outline_steps.rb +252 -0
  45. data/features/step_definitions/setup_steps.rb +50 -0
  46. data/features/step_definitions/spec_steps.rb +18 -0
  47. data/features/step_definitions/step_steps.rb +159 -0
  48. data/features/step_definitions/table_steps.rb +54 -0
  49. data/features/step_definitions/tag_steps.rb +61 -0
  50. data/features/step_definitions/test_steps.rb +114 -0
  51. data/features/step_definitions/verification_steps.rb +9 -0
  52. data/features/support/env.rb +27 -0
  53. data/features/support/transforms.rb +3 -0
  54. data/lib/cuke_modeler.rb +29 -0
  55. data/lib/cuke_modeler/background.rb +38 -0
  56. data/lib/cuke_modeler/containing.rb +18 -0
  57. data/lib/cuke_modeler/directory.rb +86 -0
  58. data/lib/cuke_modeler/doc_string.rb +87 -0
  59. data/lib/cuke_modeler/example.rb +184 -0
  60. data/lib/cuke_modeler/feature.rb +147 -0
  61. data/lib/cuke_modeler/feature_element.rb +73 -0
  62. data/lib/cuke_modeler/feature_file.rb +77 -0
  63. data/lib/cuke_modeler/nested.rb +34 -0
  64. data/lib/cuke_modeler/outline.rb +68 -0
  65. data/lib/cuke_modeler/parsing.rb +32 -0
  66. data/lib/cuke_modeler/raw.rb +20 -0
  67. data/lib/cuke_modeler/row.rb +64 -0
  68. data/lib/cuke_modeler/scenario.rb +45 -0
  69. data/lib/cuke_modeler/sourceable.rb +20 -0
  70. data/lib/cuke_modeler/step.rb +214 -0
  71. data/lib/cuke_modeler/table.rb +90 -0
  72. data/lib/cuke_modeler/table_row.rb +64 -0
  73. data/lib/cuke_modeler/tag.rb +62 -0
  74. data/lib/cuke_modeler/taggable.rb +54 -0
  75. data/lib/cuke_modeler/test_element.rb +77 -0
  76. data/lib/cuke_modeler/version.rb +3 -0
  77. data/lib/cuke_modeler/world.rb +113 -0
  78. data/spec/integration/background_integration_spec.rb +72 -0
  79. data/spec/integration/directory_integration_spec.rb +48 -0
  80. data/spec/integration/doc_string_integration_spec.rb +66 -0
  81. data/spec/integration/example_integration_spec.rb +94 -0
  82. data/spec/integration/feature_file_integration_spec.rb +44 -0
  83. data/spec/integration/feature_integration_spec.rb +152 -0
  84. data/spec/integration/outline_integration_spec.rb +92 -0
  85. data/spec/integration/scenario_integration_spec.rb +80 -0
  86. data/spec/integration/step_integration_spec.rb +184 -0
  87. data/spec/integration/table_integration_spec.rb +86 -0
  88. data/spec/integration/table_row_integration_spec.rb +68 -0
  89. data/spec/integration/tag_integration_spec.rb +67 -0
  90. data/spec/integration/world_integration_spec.rb +13 -0
  91. data/spec/spec_helper.rb +30 -0
  92. data/spec/unit/background_unit_spec.rb +55 -0
  93. data/spec/unit/bare_bones_unit_specs.rb +13 -0
  94. data/spec/unit/containing_element_unit_specs.rb +17 -0
  95. data/spec/unit/directory_unit_spec.rb +103 -0
  96. data/spec/unit/doc_string_unit_spec.rb +109 -0
  97. data/spec/unit/example_unit_spec.rb +251 -0
  98. data/spec/unit/feature_element_unit_spec.rb +19 -0
  99. data/spec/unit/feature_element_unit_specs.rb +46 -0
  100. data/spec/unit/feature_file_unit_spec.rb +94 -0
  101. data/spec/unit/feature_unit_spec.rb +135 -0
  102. data/spec/unit/nested_element_unit_specs.rb +36 -0
  103. data/spec/unit/nested_unit_spec.rb +37 -0
  104. data/spec/unit/outline_unit_spec.rb +91 -0
  105. data/spec/unit/parsing_unit_spec.rb +21 -0
  106. data/spec/unit/prepopulated_unit_specs.rb +13 -0
  107. data/spec/unit/raw_element_unit_specs.rb +24 -0
  108. data/spec/unit/raw_unit_spec.rb +25 -0
  109. data/spec/unit/row_unit_spec.rb +55 -0
  110. data/spec/unit/scenario_unit_spec.rb +71 -0
  111. data/spec/unit/sourceable_unit_spec.rb +17 -0
  112. data/spec/unit/sourced_element_unit_specs.rb +18 -0
  113. data/spec/unit/step_unit_spec.rb +259 -0
  114. data/spec/unit/table_row_unit_spec.rb +55 -0
  115. data/spec/unit/table_unit_spec.rb +96 -0
  116. data/spec/unit/tag_unit_spec.rb +51 -0
  117. data/spec/unit/taggable_unit_spec.rb +78 -0
  118. data/spec/unit/tagged_element_unit_specs.rb +63 -0
  119. data/spec/unit/test_element_unit_spec.rb +40 -0
  120. data/spec/unit/test_element_unit_specs.rb +31 -0
  121. data/spec/unit/world_unit_spec.rb +130 -0
  122. metadata +364 -0
@@ -0,0 +1,90 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling the table of a Step.
4
+
5
+ class Table
6
+
7
+ include Containing
8
+ include Raw
9
+ include Nested
10
+
11
+
12
+ # The contents of the table
13
+ #
14
+ # Deprecated
15
+ attr_accessor :contents
16
+
17
+ # The row elements that make up the table
18
+ attr_accessor :row_elements
19
+
20
+
21
+ # Creates a new Table object and, if *source* is provided, populates
22
+ # the object.
23
+ def initialize(source = nil)
24
+ @contents = []
25
+ @row_elements = []
26
+
27
+ parsed_table = process_source(source)
28
+
29
+ build_table(parsed_table) if parsed_table
30
+ end
31
+
32
+ # Returns a gherkin representation of the table.
33
+ def to_s
34
+ row_elements.empty? ? '' : row_elements.collect { |row| row_output_string(row) }.join("\n")
35
+ end
36
+
37
+
38
+ private
39
+
40
+
41
+ def process_source(source)
42
+ case
43
+ when source.is_a?(String)
44
+ parse_table(source)
45
+ else
46
+ source
47
+ end
48
+ end
49
+
50
+ def parse_table(source_text)
51
+ base_file_string = "Feature:\nScenario:\n* step\n"
52
+ source_text = base_file_string + source_text
53
+
54
+ parsed_file = Parsing::parse_text(source_text)
55
+
56
+ parsed_file.first['elements'].first['steps'].first['rows']
57
+ end
58
+
59
+ def build_table(table)
60
+ populate_contents(table)
61
+ populate_row_elements(table)
62
+ populate_raw_element(table)
63
+ end
64
+
65
+ def populate_contents(table)
66
+ @contents = table.collect { |row| row['cells'] }
67
+ end
68
+
69
+ def populate_row_elements(table)
70
+ table.each do |row|
71
+ @row_elements << build_child_element(TableRow, row)
72
+ end
73
+ end
74
+
75
+ def row_output_string(row)
76
+ row_text = '|'
77
+
78
+ row.cells.count.times do |count|
79
+ row_text << " #{row.cells[count].ljust(determine_buffer_size(count))} |"
80
+ end
81
+
82
+ row_text
83
+ end
84
+
85
+ def determine_buffer_size(index)
86
+ row_elements.collect { |row| row.cells[index].length }.max || 0
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,64 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a step table row.
4
+
5
+ class TableRow
6
+
7
+ include Sourceable
8
+ include Raw
9
+ include Nested
10
+
11
+
12
+ # The cells that make up the row
13
+ attr_accessor :cells
14
+
15
+
16
+ # Creates a new TableRow object and, if *source* is provided, populates
17
+ # the object.
18
+ def initialize(source = nil)
19
+ parsed_row = process_source(source)
20
+
21
+ @cells = []
22
+
23
+ build_row(parsed_row) if parsed_row
24
+ end
25
+
26
+ # Returns a gherkin representation of the table row.
27
+ def to_s
28
+ "| #{cells.join(' | ')} |"
29
+ end
30
+
31
+
32
+ private
33
+
34
+
35
+ def process_source(source)
36
+ case
37
+ when source.is_a?(String)
38
+ parse_row(source)
39
+ else
40
+ source
41
+ end
42
+ end
43
+
44
+ def parse_row(source_text)
45
+ base_file_string = "Feature: Fake feature to parse\nScenario:\n* fake step\n"
46
+ source_text = base_file_string + source_text
47
+
48
+ parsed_file = Parsing::parse_text(source_text)
49
+
50
+ parsed_file.first['elements'].first['steps'].first['rows'].first
51
+ end
52
+
53
+ def build_row(parsed_row)
54
+ populate_element_source_line(parsed_row)
55
+ populate_row_cells(parsed_row)
56
+ populate_raw_element(parsed_row)
57
+ end
58
+
59
+ def populate_row_cells(parsed_row)
60
+ @cells = parsed_row['cells']
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,62 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling a Tag.
4
+
5
+ class Tag
6
+
7
+ include Raw
8
+ include Sourceable
9
+ include Nested
10
+
11
+
12
+ # The name of the Tag
13
+ attr_accessor :name
14
+
15
+
16
+ # Creates a new Tag object and, if *source* is provided, populates the
17
+ # object.
18
+ def initialize(source = nil)
19
+ parsed_tag = process_source(source)
20
+
21
+ build_tag(parsed_tag) if parsed_tag
22
+ end
23
+
24
+ # Returns gherkin representation of the tag.
25
+ def to_s
26
+ name || ''
27
+ end
28
+
29
+
30
+ private
31
+
32
+
33
+ def process_source(source)
34
+ case
35
+ when source.is_a?(String)
36
+ parse_tag(source)
37
+ else
38
+ source
39
+ end
40
+ end
41
+
42
+ def parse_tag(source_text)
43
+ base_file_string = "\nFeature: Fake feature to parse"
44
+ source_text = source_text + base_file_string
45
+
46
+ parsed_file = Parsing::parse_text(source_text)
47
+
48
+ parsed_file.first['tags'].first
49
+ end
50
+
51
+ def build_tag(parsed_tag)
52
+ populate_name(parsed_tag)
53
+ populate_raw_element(parsed_tag)
54
+ populate_element_source_line(parsed_tag)
55
+ end
56
+
57
+ def populate_name(parsed_tag)
58
+ @name = parsed_tag['name']
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,54 @@
1
+ module CukeModeler
2
+
3
+ # A mix-in module containing methods used by elements that can be tagged.
4
+
5
+ module Taggable
6
+
7
+ # The tags which are directly assigned to the element
8
+ attr_accessor :tags
9
+
10
+ # The tag elements belonging to the element
11
+ attr_accessor :tag_elements
12
+
13
+
14
+ # Returns the tags which are indirectly assigned to the element (i.e. they
15
+ # have been inherited from a parent element).
16
+ def applied_tags
17
+ @parent_element.respond_to?(:all_tags) ? @parent_element.all_tags : []
18
+ end
19
+
20
+ # Returns the tags elements which are indirectly assigned to the element
21
+ # (i.e. they have been inherited from a parent element).
22
+ def applied_tag_elements
23
+ @parent_element.respond_to?(:all_tag_elements) ? @parent_element.all_tag_elements : []
24
+ end
25
+
26
+ # Returns all of the tags which are applicable to the element.
27
+ def all_tags
28
+ applied_tags + @tags
29
+ end
30
+
31
+ # Returns all of the tag elements which are applicable to the element.
32
+ def all_tag_elements
33
+ applied_tag_elements + @tag_elements
34
+ end
35
+
36
+
37
+ private
38
+
39
+
40
+ def populate_element_tags(parsed_element)
41
+ if parsed_element['tags']
42
+ parsed_element['tags'].each do |tag|
43
+ @tags << tag['name']
44
+ @tag_elements << build_child_element(Tag, tag)
45
+ end
46
+ end
47
+ end
48
+
49
+ def tag_output_string
50
+ tag_elements.collect { |tag| tag.name }.join(' ')
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,77 @@
1
+ module CukeModeler
2
+
3
+ # A class modeling an element that contains steps.
4
+
5
+ class TestElement < FeatureElement
6
+
7
+ include Containing
8
+
9
+
10
+ # The steps contained by the TestElement
11
+ attr_accessor :steps
12
+
13
+
14
+ # Creates a new TestElement object and, if *parsed_test_element* is provided,
15
+ # populates the object.
16
+ def initialize(parsed_test_element = nil)
17
+ super
18
+
19
+ @steps = []
20
+
21
+ build_test_element(parsed_test_element) if parsed_test_element
22
+ end
23
+
24
+ # Returns true if the two elements have equivalent steps and false otherwise.
25
+ def ==(other_element)
26
+ steps == other_element.steps
27
+ end
28
+
29
+ # Returns the immediate child elements of the element.
30
+ def contains
31
+ @steps
32
+ end
33
+
34
+
35
+ private
36
+
37
+
38
+ def process_source(source)
39
+ case
40
+ when source.is_a?(String)
41
+ parse_test_element(source)
42
+ else
43
+ source
44
+ end
45
+ end
46
+
47
+ def parse_test_element(source_text)
48
+ base_file_string = "Feature: Fake feature to parse\n"
49
+ source_text = base_file_string + source_text
50
+
51
+ parsed_file = Parsing::parse_text(source_text)
52
+
53
+ parsed_file.first['elements'].first
54
+ end
55
+
56
+ def build_test_element(parsed_test_element)
57
+ populate_test_element_steps(parsed_test_element)
58
+ end
59
+
60
+ def populate_test_element_steps(parsed_test_element)
61
+ if parsed_test_element['steps']
62
+ parsed_test_element['steps'].each do |step|
63
+ @steps << build_child_element(Step, step)
64
+ end
65
+ end
66
+ end
67
+
68
+ def steps_output_string
69
+ steps.collect { |step| indented_step_text(step) }.join("\n")
70
+ end
71
+
72
+ def indented_step_text(step)
73
+ step.to_s.split("\n").collect { |line| " #{line}" }.join("\n")
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module CukeModeler
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,113 @@
1
+ module CukeModeler
2
+
3
+ # A module providing suite level analysis functionality.
4
+
5
+ module World
6
+
7
+ # A placeholder string used to mark 'dirty' portions of input strings
8
+ SANITARY_STRING = '___SANITIZED_BY_CUCUMBER_ANALYTICS___'
9
+
10
+ # A pattern that matches a Cucumber step keyword
11
+ STEP_DEF_KEYWORD_PATTERN = '(?:Given|When|Then|And|But)'
12
+
13
+ # A pattern that matches a 'clean' regular expression
14
+ REGEX_PATTERN_STRING = '\/[^\/]*\/'
15
+
16
+ # A pattern that matches a step definition declaration line
17
+ STEP_DEF_LINE_PATTERN = /^\s*#{World::STEP_DEF_KEYWORD_PATTERN}\s*\(?\s*#{REGEX_PATTERN_STRING}\s*\)?/
18
+
19
+ # A pattern that captures the regular expression portion of a step definition declaration line
20
+ STEP_DEF_PATTERN_CAPTURE_PATTERN = /^\s*#{World::STEP_DEF_KEYWORD_PATTERN}\s*\(?\s*(#{REGEX_PATTERN_STRING})\s*\)?/
21
+
22
+
23
+ class << self
24
+
25
+ # Returns the left delimiter, which is used to mark the beginning of a step
26
+ # argument.
27
+ def left_delimiter
28
+ @left_delimiter
29
+ end
30
+
31
+ # Sets the left delimiter that will be used by default when determining
32
+ # step arguments.
33
+ def left_delimiter=(new_delimiter)
34
+ @left_delimiter = new_delimiter
35
+ end
36
+
37
+ # Returns the right delimiter, which is used to mark the end of a step
38
+ # argument.
39
+ def right_delimiter
40
+ @right_delimiter
41
+ end
42
+
43
+ # Sets the right delimiter that will be used by default when determining
44
+ # step arguments.
45
+ def right_delimiter=(new_delimiter)
46
+ @right_delimiter = new_delimiter
47
+ end
48
+
49
+ # Sets the delimiter that will be used by default when determining the
50
+ # boundaries of step arguments.
51
+ def delimiter=(new_delimiter)
52
+ self.left_delimiter = new_delimiter
53
+ self.right_delimiter = new_delimiter
54
+ end
55
+
56
+ # Loads the step patterns contained in the given file into the World.
57
+ def load_step_file(file_path)
58
+ File.open(file_path, 'r') do |file|
59
+ file.readlines.each do |line|
60
+ if step_def_line?(line)
61
+ the_reg_ex = extract_regular_expression(line)
62
+ loaded_step_patterns << the_reg_ex
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ # Loads the step pattern into the World.
69
+ def load_step_pattern(pattern)
70
+ loaded_step_patterns << pattern
71
+ end
72
+
73
+ # Returns the step patterns that have been loaded into the World.
74
+ def loaded_step_patterns
75
+ @defined_expressions ||= []
76
+ end
77
+
78
+ # Clears the step patterns that have been loaded into the World.
79
+ def clear_step_patterns
80
+ @defined_expressions = []
81
+ end
82
+
83
+
84
+ private
85
+
86
+
87
+ # Make life easier by ensuring that the only forward slashes in the
88
+ # regular expression are the important ones.
89
+ def sanitize_line(line)
90
+ line.gsub('\/', SANITARY_STRING)
91
+ end
92
+
93
+ # And be sure to restore the line to its original state.
94
+ def desanitize_line(line)
95
+ line.gsub(SANITARY_STRING, '\/')
96
+ end
97
+
98
+ # Returns whether or not the passed line is a step pattern.
99
+ def step_def_line?(line)
100
+ !!(sanitize_line(line) =~ STEP_DEF_LINE_PATTERN)
101
+ end
102
+
103
+ # Returns the regular expression portion of a step pattern line.
104
+ def extract_regular_expression(line)
105
+ line = desanitize_line(sanitize_line(line).match(STEP_DEF_PATTERN_CAPTURE_PATTERN)[1])
106
+ line = line.slice(1..(line.length - 2))
107
+
108
+ Regexp.new(line)
109
+ end
110
+
111
+ end
112
+ end
113
+ end