cql 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cql.rb +18 -11
- data/lib/cql/dsl.rb +14 -2
- data/lib/cql/filters.rb +12 -6
- data/lib/cql/map_reduce.rb +29 -11
- data/lib/cql/model_dsl.rb +18 -0
- data/lib/cql/queriable.rb +14 -0
- data/lib/cql/sso_filters.rb +3 -2
- data/lib/cql/version.rb +1 -1
- data/testing/cql_test_model.rb +42 -0
- data/testing/cucumber/features/clauses/as_clause.feature +136 -0
- data/testing/cucumber/features/clauses/from_clause.feature +126 -0
- data/testing/cucumber/features/clauses/select_clause.feature +117 -0
- data/testing/cucumber/features/clauses/transform_clause.feature +153 -0
- data/testing/cucumber/features/clauses/with_clause.feature +363 -0
- data/testing/cucumber/features/dsl.feature +77 -0
- data/testing/cucumber/features/model_querying.feature +18 -0
- data/testing/cucumber/features/repository.feature +23 -0
- data/testing/cucumber/step_definitions/query_steps.rb +7 -0
- data/testing/cucumber/step_definitions/setup_steps.rb +25 -0
- data/testing/cucumber/step_definitions/verification_steps.rb +78 -0
- data/testing/cucumber/support/env.rb +24 -0
- data/testing/cucumber/support/transforms.rb +3 -0
- data/testing/fixtures/features/combined/a/f1_4_scenarios_5_so.feature +59 -0
- data/testing/fixtures/features/combined/a/f2_7_scenarios_2_so.feature +43 -0
- data/testing/fixtures/features/combined/a/f3_2_scenarios_3_so.feature +30 -0
- data/testing/fixtures/features/combined/b/f1_1_tag.feature +6 -0
- data/testing/fixtures/features/combined/b/f2_2_tags.feature +6 -0
- data/testing/fixtures/features/combined/b/f3_3_tags.feature +6 -0
- data/testing/fixtures/features/examples/basic/test_with_scenarios.feature +15 -0
- data/testing/fixtures/features/examples/filters/tag_count/simple.feature +21 -0
- data/testing/fixtures/features/examples/filters/tag_count/simple2.feature +21 -0
- data/testing/fixtures/features/examples/filters/tags/simple.feature +34 -0
- data/testing/fixtures/features/examples/filters/tags2/simple.feature +34 -0
- data/testing/fixtures/features/examples/filters/tags2/simple2.feature +34 -0
- data/testing/fixtures/features/examples/multiple_examples/test_with_scenarios.feature +43 -0
- data/testing/fixtures/features/examples/name_filter/name.feature +19 -0
- data/testing/fixtures/features/got/Lannisters.feature +24 -0
- data/testing/fixtures/features/got/Starks.feature +18 -0
- data/testing/fixtures/features/scen_outlines/basic/test_with_scenarios.feature +15 -0
- data/testing/fixtures/features/scen_outlines/filters/tag_count/simple.feature +21 -0
- data/testing/fixtures/features/scen_outlines/filters/tag_count/simple2.feature +21 -0
- data/testing/fixtures/features/scen_outlines/filters/tags/simple.feature +34 -0
- data/testing/fixtures/features/scen_outlines/filters/tags2/simple.feature +34 -0
- data/testing/fixtures/features/scen_outlines/filters/tags2/simple2.feature +34 -0
- data/testing/fixtures/features/scen_outlines/line_count/simple.feature +12 -0
- data/testing/fixtures/features/scen_outlines/line_count/simple2.feature +16 -0
- data/testing/fixtures/features/scen_outlines/line_filter/ll.feature +13 -0
- data/testing/fixtures/features/scen_outlines/multiple_examples/test_with_scenarios.feature +43 -0
- data/testing/fixtures/features/scen_outlines/name_filter/name.feature +19 -0
- data/testing/fixtures/features/scenario/line_count/simple.feature +9 -0
- data/testing/fixtures/features/scenario/line_count/simple2.feature +12 -0
- data/testing/fixtures/features/scenario/line_filter/ll.feature +9 -0
- data/testing/fixtures/features/scenario/name_filter/name.feature +13 -0
- data/testing/fixtures/features/scenario/simple/simple.feature +8 -0
- data/testing/fixtures/features/scenario/simple/test.feature +9 -0
- data/testing/fixtures/features/scenario/simple/test2.feature +5 -0
- data/testing/fixtures/features/scenario/simple/test_full.feature +22 -0
- data/testing/fixtures/features/scenario/simple2/test_full.feature +23 -0
- data/testing/fixtures/features/scenario/table/simple.feature +11 -0
- data/testing/fixtures/features/scenario/tag_count/simple.feature +17 -0
- data/testing/fixtures/features/scenario/tag_count/simple2.feature +17 -0
- data/testing/fixtures/features/scenario/tagged_features/simple.feature +8 -0
- data/testing/fixtures/features/scenario/tagged_features/test.feature +10 -0
- data/testing/fixtures/features/scenario/tagged_features/test2.feature +6 -0
- data/testing/fixtures/features/scenario/tagged_features/test_full.feature +22 -0
- data/testing/fixtures/features/scenario/tags/simple.feature +24 -0
- data/testing/fixtures/features/scenario/tags2/simple.feature +24 -0
- data/testing/fixtures/features/scenario/tags2/simple2.feature +24 -0
- data/testing/fixtures/features/scenario/tags3/simple.feature +21 -0
- data/testing/gemfiles/cuke_modeler0.gemfile +30 -0
- data/testing/gemfiles/cuke_modeler1.gemfile +30 -0
- data/testing/rspec/spec/dsl_spec.rb +600 -0
- data/testing/rspec/spec/filter_example_spec.rb +65 -0
- data/testing/rspec/spec/filter_feature_dsl_spec.rb +286 -0
- data/testing/rspec/spec/filter_sso_spec.rb +202 -0
- data/testing/rspec/spec/line_count_filterable_specs.rb +74 -0
- data/testing/rspec/spec/line_filterable_specs.rb +52 -0
- data/testing/rspec/spec/map_reduce_spec.rb +135 -0
- data/testing/rspec/spec/model_query_spec.rb +49 -0
- data/testing/rspec/spec/multiple_queries_spec.rb +24 -0
- data/testing/rspec/spec/name_filterable_specs.rb +52 -0
- data/testing/rspec/spec/queriable_specs.rb +45 -0
- data/testing/rspec/spec/repository_spec.rb +82 -0
- data/testing/rspec/spec/select_feature_dsl_spec.rb +114 -0
- data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +234 -0
- data/testing/rspec/spec/select_scenario_dsl_spec.rb +132 -0
- data/testing/rspec/spec/spec_helper.rb +42 -0
- data/testing/rspec/spec/tag_filterable_specs.rb +107 -0
- 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,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,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,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 |
|