cql 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cql.rb +18 -11
  3. data/lib/cql/dsl.rb +14 -2
  4. data/lib/cql/filters.rb +12 -6
  5. data/lib/cql/map_reduce.rb +29 -11
  6. data/lib/cql/model_dsl.rb +18 -0
  7. data/lib/cql/queriable.rb +14 -0
  8. data/lib/cql/sso_filters.rb +3 -2
  9. data/lib/cql/version.rb +1 -1
  10. data/testing/cql_test_model.rb +42 -0
  11. data/testing/cucumber/features/clauses/as_clause.feature +136 -0
  12. data/testing/cucumber/features/clauses/from_clause.feature +126 -0
  13. data/testing/cucumber/features/clauses/select_clause.feature +117 -0
  14. data/testing/cucumber/features/clauses/transform_clause.feature +153 -0
  15. data/testing/cucumber/features/clauses/with_clause.feature +363 -0
  16. data/testing/cucumber/features/dsl.feature +77 -0
  17. data/testing/cucumber/features/model_querying.feature +18 -0
  18. data/testing/cucumber/features/repository.feature +23 -0
  19. data/testing/cucumber/step_definitions/query_steps.rb +7 -0
  20. data/testing/cucumber/step_definitions/setup_steps.rb +25 -0
  21. data/testing/cucumber/step_definitions/verification_steps.rb +78 -0
  22. data/testing/cucumber/support/env.rb +24 -0
  23. data/testing/cucumber/support/transforms.rb +3 -0
  24. data/testing/fixtures/features/combined/a/f1_4_scenarios_5_so.feature +59 -0
  25. data/testing/fixtures/features/combined/a/f2_7_scenarios_2_so.feature +43 -0
  26. data/testing/fixtures/features/combined/a/f3_2_scenarios_3_so.feature +30 -0
  27. data/testing/fixtures/features/combined/b/f1_1_tag.feature +6 -0
  28. data/testing/fixtures/features/combined/b/f2_2_tags.feature +6 -0
  29. data/testing/fixtures/features/combined/b/f3_3_tags.feature +6 -0
  30. data/testing/fixtures/features/examples/basic/test_with_scenarios.feature +15 -0
  31. data/testing/fixtures/features/examples/filters/tag_count/simple.feature +21 -0
  32. data/testing/fixtures/features/examples/filters/tag_count/simple2.feature +21 -0
  33. data/testing/fixtures/features/examples/filters/tags/simple.feature +34 -0
  34. data/testing/fixtures/features/examples/filters/tags2/simple.feature +34 -0
  35. data/testing/fixtures/features/examples/filters/tags2/simple2.feature +34 -0
  36. data/testing/fixtures/features/examples/multiple_examples/test_with_scenarios.feature +43 -0
  37. data/testing/fixtures/features/examples/name_filter/name.feature +19 -0
  38. data/testing/fixtures/features/got/Lannisters.feature +24 -0
  39. data/testing/fixtures/features/got/Starks.feature +18 -0
  40. data/testing/fixtures/features/scen_outlines/basic/test_with_scenarios.feature +15 -0
  41. data/testing/fixtures/features/scen_outlines/filters/tag_count/simple.feature +21 -0
  42. data/testing/fixtures/features/scen_outlines/filters/tag_count/simple2.feature +21 -0
  43. data/testing/fixtures/features/scen_outlines/filters/tags/simple.feature +34 -0
  44. data/testing/fixtures/features/scen_outlines/filters/tags2/simple.feature +34 -0
  45. data/testing/fixtures/features/scen_outlines/filters/tags2/simple2.feature +34 -0
  46. data/testing/fixtures/features/scen_outlines/line_count/simple.feature +12 -0
  47. data/testing/fixtures/features/scen_outlines/line_count/simple2.feature +16 -0
  48. data/testing/fixtures/features/scen_outlines/line_filter/ll.feature +13 -0
  49. data/testing/fixtures/features/scen_outlines/multiple_examples/test_with_scenarios.feature +43 -0
  50. data/testing/fixtures/features/scen_outlines/name_filter/name.feature +19 -0
  51. data/testing/fixtures/features/scenario/line_count/simple.feature +9 -0
  52. data/testing/fixtures/features/scenario/line_count/simple2.feature +12 -0
  53. data/testing/fixtures/features/scenario/line_filter/ll.feature +9 -0
  54. data/testing/fixtures/features/scenario/name_filter/name.feature +13 -0
  55. data/testing/fixtures/features/scenario/simple/simple.feature +8 -0
  56. data/testing/fixtures/features/scenario/simple/test.feature +9 -0
  57. data/testing/fixtures/features/scenario/simple/test2.feature +5 -0
  58. data/testing/fixtures/features/scenario/simple/test_full.feature +22 -0
  59. data/testing/fixtures/features/scenario/simple2/test_full.feature +23 -0
  60. data/testing/fixtures/features/scenario/table/simple.feature +11 -0
  61. data/testing/fixtures/features/scenario/tag_count/simple.feature +17 -0
  62. data/testing/fixtures/features/scenario/tag_count/simple2.feature +17 -0
  63. data/testing/fixtures/features/scenario/tagged_features/simple.feature +8 -0
  64. data/testing/fixtures/features/scenario/tagged_features/test.feature +10 -0
  65. data/testing/fixtures/features/scenario/tagged_features/test2.feature +6 -0
  66. data/testing/fixtures/features/scenario/tagged_features/test_full.feature +22 -0
  67. data/testing/fixtures/features/scenario/tags/simple.feature +24 -0
  68. data/testing/fixtures/features/scenario/tags2/simple.feature +24 -0
  69. data/testing/fixtures/features/scenario/tags2/simple2.feature +24 -0
  70. data/testing/fixtures/features/scenario/tags3/simple.feature +21 -0
  71. data/testing/gemfiles/cuke_modeler0.gemfile +30 -0
  72. data/testing/gemfiles/cuke_modeler1.gemfile +30 -0
  73. data/testing/rspec/spec/dsl_spec.rb +600 -0
  74. data/testing/rspec/spec/filter_example_spec.rb +65 -0
  75. data/testing/rspec/spec/filter_feature_dsl_spec.rb +286 -0
  76. data/testing/rspec/spec/filter_sso_spec.rb +202 -0
  77. data/testing/rspec/spec/line_count_filterable_specs.rb +74 -0
  78. data/testing/rspec/spec/line_filterable_specs.rb +52 -0
  79. data/testing/rspec/spec/map_reduce_spec.rb +135 -0
  80. data/testing/rspec/spec/model_query_spec.rb +49 -0
  81. data/testing/rspec/spec/multiple_queries_spec.rb +24 -0
  82. data/testing/rspec/spec/name_filterable_specs.rb +52 -0
  83. data/testing/rspec/spec/queriable_specs.rb +45 -0
  84. data/testing/rspec/spec/repository_spec.rb +82 -0
  85. data/testing/rspec/spec/select_feature_dsl_spec.rb +114 -0
  86. data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +234 -0
  87. data/testing/rspec/spec/select_scenario_dsl_spec.rb +132 -0
  88. data/testing/rspec/spec/spec_helper.rb +42 -0
  89. data/testing/rspec/spec/tag_filterable_specs.rb +107 -0
  90. metadata +170 -5
@@ -0,0 +1,77 @@
1
+ Feature: DSL
2
+
3
+ The cql gem uses a DSL to specify queries on a repository object that holds the models which represent a Cucumber test suite. The DSL can query for any attribute that is available on the underlying models.
4
+
5
+ Sample usage:
6
+ cql_repo.query do
7
+ select name, source_line
8
+ from features
9
+ end
10
+
11
+ Query results are returned as a list of attribute mappings for all of the models found in the repository. The sample query above might return:
12
+
13
+ [{'name' => 'Feature 1', 'source_line' => 1},
14
+ {'name' => 'Feature 2', 'source_line' => 3},
15
+ {'name' => 'Feature 3', 'source_line' => 10}]
16
+
17
+
18
+ Background: A sample Cucumber suite
19
+ Given a directory "test_directory"
20
+ And a file "test_directory/test_file_1.feature":
21
+ """
22
+ Feature: A test feature
23
+
24
+ Scenario: Test 1
25
+ * some steps
26
+
27
+ @special_tag
28
+ Scenario: Test 2
29
+ * some other steps
30
+
31
+ Scenario Outline: Test 3
32
+ * some steps
33
+ Examples: First examples
34
+ | param |
35
+ | value |
36
+ Examples: Second examples
37
+ | param |
38
+ | value |
39
+ """
40
+ And a repository is made from "test_directory"
41
+
42
+ Scenario: Automatic string conversion
43
+
44
+ Although most times it is unnecessary, using full strings in a query can remove syntactical ambiguity.
45
+
46
+ When the following query is executed:
47
+ """
48
+ select name
49
+ from scenarios
50
+ """
51
+ Then the result is the same as the result of the following query:
52
+ """
53
+ select 'name'
54
+ from 'scenarios'
55
+ """
56
+
57
+
58
+ # Commented out so that they aren't picked up by Relish
59
+ #
60
+ # @wip
61
+ # Scenario: Use 'order_by' to sort the results
62
+ #
63
+ # # 'and' is a keyword. Some other kind of repeater word would be needed
64
+ # @wip
65
+ # Scenario: 'And' can be used instead of repeating the previous keyword
66
+ # When the following query is executed:
67
+ # """
68
+ # select 'name'
69
+ # and 'source_line'
70
+ # from CukeModeler::Scenario
71
+ # and CukeModeler::Outline
72
+ # """
73
+ # Then the following values are returned:
74
+ # | name | source_line |
75
+ # | Test 1 | 3 |
76
+ # | Test 2 | 6 |
77
+ # | Test 3 | 9 |
@@ -0,0 +1,18 @@
1
+ Feature: Models can be queried directly
2
+
3
+ Note: This feature is only available with newer versions of the 'cuke_modeler' library.
4
+
5
+ @cuke_modeler_1x
6
+ Scenario: Querying a model
7
+ Given the models provided by CukeModeler
8
+ Then all of them can be queried
9
+ """
10
+ model = <model_class>.new
11
+
12
+ model.query do
13
+
14
+ select
15
+ from :all
16
+
17
+ end
18
+ """
@@ -0,0 +1,23 @@
1
+ Feature: Repository
2
+
3
+ All queries are performed against a repository object. A repository is simply a collection of models that represent a Cucumber test suite. Commonly, a repository is created based on a file path that is the location of such a test suite. However, repositories can also be created using any model as their starting point.
4
+
5
+
6
+ Scenario: Using a file path to create a repository
7
+ Given a directory "path/to/test_directory"
8
+ Then the following code executes without error:
9
+ """
10
+ CQL::Repository.new("path/to/test_directory")
11
+ """
12
+
13
+ Scenario: Using a model to create a repository
14
+
15
+ Note: Non-directory models can also be used
16
+
17
+ Given a directory "path/to/test_directory"
18
+ Then the following code executes without error:
19
+ """
20
+ directory_model = CukeModeler::Directory.new("path/to/test_directory")
21
+
22
+ CQL::Repository.new(directory_model)
23
+ """
@@ -0,0 +1,7 @@
1
+ When(/^the following query is executed:$/) do |query_text|
2
+ command = "@repository.query do
3
+ #{query_text}
4
+ end"
5
+
6
+ @query_results = eval(command)
7
+ end
@@ -0,0 +1,25 @@
1
+ Given(/^a directory "([^"]*)"$/) do |partial_directory_path|
2
+ directory_path = partial_directory_path.include?('path/to') ? process_path(partial_directory_path) : "#{@default_file_directory}/#{partial_directory_path}"
3
+
4
+ FileUtils.mkpath(directory_path) unless File.exists?(directory_path)
5
+ end
6
+
7
+ And(/^a file "([^"]*)":$/) do |partial_file_path, file_text|
8
+ File.open("#{@default_file_directory}/#{partial_file_path}", 'w') { |file| file.write file_text }
9
+ end
10
+
11
+ And(/^a repository is made from "([^"]*)"$/) do |partial_path|
12
+ repo_path = "#{@default_file_directory}/#{partial_path}"
13
+
14
+ @repository = CQL::Repository.new(repo_path)
15
+ end
16
+
17
+ Given(/^the models provided by CukeModeler$/) do
18
+ @available_model_classes = Array.new.tap do |classes|
19
+ CukeModeler.constants.each do |constant|
20
+ if CukeModeler.const_get(constant).is_a?(Class)
21
+ classes << CukeModeler.const_get(constant) if CukeModeler.const_get(constant).ancestors.include?(CukeModeler::Model)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,78 @@
1
+ Then(/^the following values are returned:$/) do |values|
2
+ expected_results = values.hashes
3
+ expected_results.each { |result| result['source_line'] = result['source_line'].to_i if result['source_line'] }
4
+ expected_results.each { |result| result['scenario_line'] = result['scenario_line'].to_i if result['scenario_line'] }
5
+ expected_results.each { |result| result['tags'] = eval(result['tags']) if result['tags'] }
6
+ expected_results.each { |result| result['scenario_tags'] = eval(result['scenario_tags']) if result['scenario_tags'] }
7
+
8
+ expected_results.each do |result|
9
+ result.each_pair { |key, value| result[key] = value.sub('path/to', @default_file_directory) if value =~ /path\/to/ }
10
+ end
11
+
12
+ expect(@query_results).to match_array(expected_results)
13
+ end
14
+
15
+ # Then(/^all of them can be queried for additional information$/) do
16
+ #
17
+ # expect(@cm_models).to_not be_empty
18
+ #
19
+ # @cm_models.each do |model|
20
+ # raise("Expected #{model} to define :query") unless model.method_defined?(:query)
21
+ # end
22
+ #
23
+ # end
24
+
25
+ Then(/^the models for the following items are returned:$/) do |item_names|
26
+ expected_results = item_names.raw.flatten
27
+
28
+ expect(@query_results.collect { |result| result[:self].name }).to match_array(expected_results)
29
+ end
30
+
31
+ Then(/^the result is the same as the result of the following query:$/) do |query_text|
32
+ command = "@repository.query do
33
+ #{query_text}
34
+ end"
35
+
36
+ baseline_results = eval(command)
37
+
38
+ expect(@query_results).to eq(baseline_results)
39
+ end
40
+
41
+ Then(/^the following code executes without error:$/) do |code_text|
42
+ code_text = process_path(code_text)
43
+
44
+ expect { eval(code_text) }.to_not raise_error
45
+ end
46
+
47
+ Then(/^all of them can be queried$/) do |code_text|
48
+ @available_model_classes.each do |clazz|
49
+ code_text.gsub!('<model_class>', clazz.to_s)
50
+
51
+ expect(clazz.new).to respond_to(:query)
52
+
53
+ # Make sure that the example code is valid
54
+ expect { eval(code_text) }.to_not raise_error
55
+ end
56
+ end
57
+
58
+ Then(/^all models are queried from$/) do
59
+ # Just making sure that multiple model results are returned
60
+ expect(@query_results.count).to be > 1
61
+
62
+ @query_results.each do |result|
63
+ class_name = result[:model].class.name.split('::').last
64
+
65
+ expect(CukeModeler.const_defined?(class_name)).to be true
66
+ end
67
+ end
68
+
69
+ And(/^equivalent results are returned for the following query:$/) do |query_text|
70
+ command = "@repository.query do
71
+ #{query_text}
72
+ end"
73
+
74
+ alternate_results = eval(command)
75
+
76
+ # Only checking the values of the results because they will have different :model/:self keys
77
+ expect(alternate_results.collect { |result| result.values }).to eq(@query_results.collect { |result| result.values })
78
+ end
@@ -0,0 +1,24 @@
1
+ unless RUBY_VERSION.to_s < '1.9.0'
2
+ require 'simplecov'
3
+ SimpleCov.command_name('cql-cucumber')
4
+ end
5
+
6
+
7
+ require 'cql'
8
+ require 'cql/model_dsl'
9
+
10
+
11
+ Before do
12
+ @default_file_directory = "#{File.dirname(__FILE__)}/../temp_files"
13
+
14
+ FileUtils.mkdir(@default_file_directory)
15
+ end
16
+
17
+ After do
18
+ FileUtils.remove_dir(@default_file_directory, true)
19
+ end
20
+
21
+
22
+ def process_path(path)
23
+ path.sub('path/to', @default_file_directory)
24
+ end
@@ -0,0 +1,3 @@
1
+ Transform /^(-?\d+)$/ do |number|
2
+ number.to_i
3
+ end
@@ -0,0 +1,59 @@
1
+ Feature: f1_4_scenarios_5_so
2
+ (4 scenarios, 5 scenario outlines)
3
+
4
+ Scenario: A cat in a hat
5
+ Given A cat in a hat
6
+ And walked across the road
7
+ Then he was on the other side
8
+
9
+ Scenario: The lonely giant
10
+ Given he was very big
11
+ And he was an orphan
12
+ And no one wanted to play with him
13
+ And he couldn't fit into normal sized building
14
+ Then he was all alone
15
+
16
+ Scenario: The king of kings
17
+ Given king "George"
18
+ And king "Bruce"
19
+ Then George is the king of kings
20
+
21
+ Scenario: A deer
22
+ * A deer
23
+ * A female deer
24
+ * Ray, a drop of golden sun
25
+
26
+ Scenario Outline: f1_so1
27
+ Given blah <e>
28
+
29
+ Examples:
30
+ | e |
31
+ | r |
32
+
33
+ Scenario Outline: f1_so2
34
+ Given blah <e>
35
+
36
+ Examples:
37
+ | e |
38
+ | r |
39
+
40
+ Scenario Outline: f1_so3
41
+ Given blah <e>
42
+
43
+ Examples:
44
+ | e |
45
+ | r |
46
+
47
+ Scenario Outline: f1_so4
48
+ Given blah <e>
49
+
50
+ Examples:
51
+ | e |
52
+ | r |
53
+
54
+ Scenario Outline: f1_so5
55
+ Given blah <e>
56
+
57
+ Examples:
58
+ | e |
59
+ | r |
@@ -0,0 +1,43 @@
1
+ Feature: f2_7_scenarios_2_so
2
+
3
+ Scenario: f2_scen1
4
+ Given Something
5
+ Then something else
6
+
7
+ Scenario: f2_scen2
8
+ Given Something
9
+ Then something else
10
+
11
+ Scenario: f2_scen3
12
+ Given Something
13
+ Then something else
14
+
15
+ Scenario: f2_scen4
16
+ Given Something
17
+ Then something else
18
+
19
+ Scenario: f2_scen5
20
+ Given Something
21
+ Then something else
22
+
23
+ Scenario: f2_scen6
24
+ Given Something
25
+ Then something else
26
+
27
+ Scenario: f2_scen7
28
+ Given Something
29
+ Then something else
30
+
31
+ Scenario Outline: f2_so1
32
+ Given blah <e>
33
+
34
+ Examples:
35
+ | e |
36
+ | r |
37
+
38
+ Scenario Outline: f2_so2
39
+ Given blah <e>
40
+
41
+ Examples:
42
+ | e |
43
+ | r |
@@ -0,0 +1,30 @@
1
+ Feature: f3_2_scenarios_3_so
2
+
3
+ Scenario: f3_scen1
4
+ Given Something
5
+ Then something else
6
+
7
+ Scenario: f3_scen2
8
+ Given Something
9
+ Then something else
10
+
11
+ Scenario Outline: f3_so1
12
+ Given blah <e>
13
+
14
+ Examples:
15
+ | e |
16
+ | r |
17
+
18
+ Scenario Outline: f3_so2
19
+ Given blah <e>
20
+
21
+ Examples:
22
+ | e |
23
+ | r |
24
+
25
+ Scenario Outline: f3_so3
26
+ Given blah <e>
27
+
28
+ Examples:
29
+ | e |
30
+ | r |
@@ -0,0 +1,6 @@
1
+ @one
2
+ Feature: f1_1_tag
3
+
4
+ Scenario: f1_scen1
5
+ Given Something
6
+ Then something else
@@ -0,0 +1,6 @@
1
+ @one @two
2
+ Feature: f2_2_tags
3
+
4
+ Scenario: f2_scen1
5
+ Given Something
6
+ Then something else
@@ -0,0 +1,6 @@
1
+ @one @two @three
2
+ Feature: f3_3_tags
3
+
4
+ Scenario: f3_scen1
5
+ Given Something
6
+ Then something else
@@ -0,0 +1,15 @@
1
+ Feature: Test Feature
2
+
3
+ Scenario Outline: An Outline
4
+ Given something happend
5
+ Then I expect something else
6
+ Examples:
7
+ | var_a | var_b |
8
+ | 1 | a |
9
+ | 2 | b |
10
+ | 3 | c |
11
+ | 4 | d |
12
+
13
+ Scenario: A Scenario
14
+ Given something happend
15
+ Then I expect something else
@@ -0,0 +1,21 @@
1
+ Feature: Simple
2
+
3
+ Scenario Outline:
4
+ Given Something
5
+ | a | a |
6
+ | s | a |
7
+ | s | s |
8
+ Then something else
9
+ @one
10
+ Examples: 1 tag
11
+ | param |
12
+
13
+ Scenario Outline:
14
+ Given Something
15
+ | a | a |
16
+ | s | a |
17
+ | s | s |
18
+ Then something else
19
+ @one @two
20
+ Examples: 2 tags
21
+ | param |