cql 1.4.0 → 1.6.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 +5 -5
- data/lib/cql.rb +4 -169
- data/lib/cql/dsl.rb +39 -5
- data/lib/cql/feature_filters.rb +2 -0
- data/lib/cql/filters.rb +25 -1
- data/lib/cql/map_reduce.rb +3 -0
- data/lib/cql/model_dsl.rb +7 -1
- data/lib/cql/queriable.rb +6 -1
- data/lib/cql/query.rb +157 -0
- data/lib/cql/repository.rb +25 -0
- data/lib/cql/sso_filters.rb +4 -0
- data/lib/cql/version.rb +2 -1
- data/testing/cucumber/features/clauses/as_clause.feature +10 -9
- data/testing/cucumber/features/clauses/from_clause.feature +15 -20
- data/testing/cucumber/features/clauses/predefined_with_filters.feature +392 -0
- data/testing/cucumber/features/clauses/select_clause.feature +11 -14
- data/testing/cucumber/features/clauses/transform_clause.feature +10 -9
- data/testing/cucumber/features/clauses/with_clause.feature +10 -170
- data/testing/cucumber/features/dsl.feature +15 -34
- data/testing/cucumber/step_definitions/setup_steps.rb +1 -13
- data/testing/cucumber/step_definitions/verification_steps.rb +6 -7
- data/testing/cucumber/support/env.rb +9 -9
- data/testing/gemfiles/cuke_modeler0.gemfile +10 -7
- data/testing/gemfiles/cuke_modeler1.gemfile +6 -7
- data/testing/gemfiles/cuke_modeler2.gemfile +33 -0
- data/testing/gemfiles/cuke_modeler3.gemfile +10 -0
- data/testing/helper_methods.rb +13 -0
- data/testing/model_helper.rb +28 -0
- data/testing/rspec/spec/clauses/as_clause_spec.rb +1 -0
- data/testing/rspec/spec/clauses/from_clause_spec.rb +146 -0
- data/testing/rspec/spec/clauses/select_clause_spec.rb +184 -0
- data/testing/rspec/spec/clauses/transform_clause_spec.rb +35 -0
- data/testing/rspec/spec/clauses/with_clause_spec.rb +84 -0
- data/testing/rspec/spec/clauses/without_clause_spec.rb +171 -0
- data/testing/rspec/spec/cql_spec.rb +25 -0
- data/testing/rspec/spec/dsl_spec.rb +3 -575
- data/testing/rspec/spec/filter_example_spec.rb +1 -1
- data/testing/rspec/spec/filter_feature_dsl_spec.rb +13 -13
- data/testing/rspec/spec/filter_sso_spec.rb +2 -2
- data/testing/rspec/spec/line_filterable_specs.rb +1 -1
- data/testing/rspec/spec/map_reduce_spec.rb +1 -1
- data/testing/rspec/spec/model_query_spec.rb +1 -1
- data/testing/rspec/spec/multiple_queries_spec.rb +1 -1
- data/testing/rspec/spec/name_filterable_specs.rb +1 -1
- data/testing/rspec/spec/predefined_filters_spec.rb +284 -0
- data/testing/rspec/spec/repository_spec.rb +3 -3
- data/testing/rspec/spec/select_feature_dsl_spec.rb +8 -8
- data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +14 -14
- data/testing/rspec/spec/select_scenario_dsl_spec.rb +9 -9
- data/testing/rspec/spec/spec_helper.rb +7 -17
- metadata +52 -23
- data/testing/cucumber/support/transforms.rb +0 -3
@@ -2,18 +2,20 @@ Feature: 'select' clause
|
|
2
2
|
|
3
3
|
The *select* clause specifies what attributes will be retrieved from the models specified by the *from* clause. Multiple values can be given and they are delimited by a comma. The *select* clause can take any method to which the objects specified by *from* know how to respond. The clause can also be given a special identifier in order to return the underlying models themselves instead of their attributes. If no attributes are specified then the underlying model will be returned instead, just as if the special identifier had been used (it is simply an alternate syntax and may look nicer in some queries).
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
Sample usage:
|
6
|
+
````
|
7
|
+
cql_repo.query do
|
8
|
+
select name, tags, description_text
|
9
|
+
from features
|
10
|
+
end
|
11
|
+
````
|
10
12
|
|
11
13
|
This clause can be repeated multiple times. The arguments for successive clauses are simply added to the previous arguments.
|
12
14
|
|
13
15
|
|
14
|
-
Background:
|
15
|
-
Given a
|
16
|
-
And
|
16
|
+
Background: Repository with models
|
17
|
+
Given a repository to query
|
18
|
+
And the following feature has been modeled in the repository:
|
17
19
|
"""
|
18
20
|
Feature: A test feature
|
19
21
|
|
@@ -33,7 +35,6 @@ Feature: 'select' clause
|
|
33
35
|
| param |
|
34
36
|
| value |
|
35
37
|
"""
|
36
|
-
And a repository is made from "test_directory"
|
37
38
|
|
38
39
|
|
39
40
|
Scenario: Using 'select' to specify which attributes of an object to return
|
@@ -91,7 +92,7 @@ Feature: 'select' clause
|
|
91
92
|
from scenarios
|
92
93
|
"""
|
93
94
|
|
94
|
-
Scenario:
|
95
|
+
Scenario: Using the 'select' clause multiple times
|
95
96
|
When the following query is executed:
|
96
97
|
"""
|
97
98
|
select name
|
@@ -115,7 +116,3 @@ Feature: 'select' clause
|
|
115
116
|
select :self
|
116
117
|
from scenarios
|
117
118
|
"""
|
118
|
-
|
119
|
-
# Commented out so that they aren't picked up by Relish
|
120
|
-
# @wip
|
121
|
-
# Scenario: Can select from all types of model
|
@@ -2,20 +2,22 @@ Feature: 'transform' clause
|
|
2
2
|
|
3
3
|
The *transform* clause allows you to change the values of the attributes specified by the *select* clause after they are gathered. Value transforming can be done as a list of transformation blocks that are applied in order or as a mapping of specific keys and their transformations.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
Sample usage:
|
6
|
+
````
|
7
|
+
cql_repo.query do
|
8
|
+
select name
|
9
|
+
transform { |name| name.upcase }
|
10
|
+
from features
|
11
|
+
end
|
12
|
+
````
|
11
13
|
|
12
14
|
This will return a list of all of the feature names but with all of their names upcased.
|
13
15
|
|
14
16
|
This clause can be repeated multiple times. When using lists of transforms, the arguments for successive clauses are simply added to the previous arguments. When using mapped transforms, the mappings are likewise combined. If the same key is mapped more than once, the mappings are tracked separately such that they can be applied to different instances of attribute retrieval (see examples below).
|
15
17
|
|
16
18
|
Background: A sample Cucumber suite
|
17
|
-
Given a
|
18
|
-
And
|
19
|
+
Given a repository to query
|
20
|
+
And the following feature has been modeled in the repository:
|
19
21
|
"""
|
20
22
|
Feature: A test feature
|
21
23
|
|
@@ -35,7 +37,6 @@ Feature: 'transform' clause
|
|
35
37
|
| param |
|
36
38
|
| value |
|
37
39
|
"""
|
38
|
-
And a repository is made from "test_directory"
|
39
40
|
|
40
41
|
|
41
42
|
Scenario: Using 'transform' to change values after they are gathered
|
@@ -1,47 +1,20 @@
|
|
1
1
|
# todo - Rewrite the scenarios such that they use their own test specific feature files instead of setting up a large suite in the background
|
2
2
|
Feature: 'with' clause
|
3
3
|
|
4
|
-
The *with* clause specifies filter conditions that will reduce the number of things targeted by the *from* clause. The *with* clause can take one or more blocks that will filter out any object for which the block does not evaluate to true (using 'without' instead of 'with' will have the opposite effect). Alternatively, mappings of specific *from* targets to their respective filtering blocks can be provided. The *with* clause can also take predefined filters (
|
4
|
+
The *with* clause specifies filter conditions that will reduce the number of things targeted by the *from* clause. The *with* clause can take one or more blocks that will filter out any object for which the block does not evaluate to true (using 'without' instead of 'with' will have the opposite effect). Alternatively, mappings of specific *from* targets to their respective filtering blocks can be provided. The *with* clause can also take predefined filters (see corresponding documentation).
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
Sample usage:
|
7
|
+
````
|
8
|
+
cql_repo.query do
|
9
|
+
select name, tags, description_text
|
10
|
+
from features
|
11
|
+
with { |feature| feature.name =~ /foo/ }
|
12
|
+
end
|
13
|
+
````
|
13
14
|
|
14
15
|
This clause can be repeated multiple times. The arguments for successive clauses are simply added to the previous arguments.
|
15
16
|
|
16
17
|
|
17
|
-
The following filters are supported for models that have tags:
|
18
|
-
|
19
|
-
* tags - Filters out models that do not have the exact set of tags provided.
|
20
|
-
* tc - (tag count) Filters out models based on the number of tags that they have.
|
21
|
-
|
22
|
-
The following filters are supported for models that have names:
|
23
|
-
|
24
|
-
* name - Filters out models whose name does not match the name provided. Can be a string or regular expression.
|
25
|
-
|
26
|
-
The following filters are supported for models that have steps:
|
27
|
-
|
28
|
-
* line - Filters out models whose steps do not include the provided step (keywords and blocks are ignored). Can be a string or regular expression.
|
29
|
-
* lc - (line count) Filters out models based on the number of steps that they have.
|
30
|
-
|
31
|
-
The following filters are supported for feature models:
|
32
|
-
|
33
|
-
* sc - (scenario count) Filters out models based on the number of scenarios that they have.
|
34
|
-
* soc - (scenario outline count) Filters out models based on the number of outlines that they have.
|
35
|
-
* ssoc - (scenario and scenario outline count) Filters out models based on the total number of scenarios and outlines that they have.
|
36
|
-
|
37
|
-
For count based filters, the following operators are available:
|
38
|
-
|
39
|
-
* lt (Less than)
|
40
|
-
* lte (Less than or equals)
|
41
|
-
* gt (Greater than)
|
42
|
-
* gte (Greater than or equals)
|
43
|
-
|
44
|
-
|
45
18
|
Background: A sample Cucumber suite
|
46
19
|
Given a repository to query
|
47
20
|
And the following feature has been modeled in the repository:
|
@@ -159,7 +132,7 @@ Feature: 'with' clause
|
|
159
132
|
"""
|
160
133
|
select name
|
161
134
|
from features, scenarios
|
162
|
-
with scenarios =>
|
135
|
+
with scenarios => lambda { |element| element.name == 'Test 1' }
|
163
136
|
"""
|
164
137
|
Then the following values are returned:
|
165
138
|
| name |
|
@@ -214,127 +187,6 @@ Feature: 'with' clause
|
|
214
187
|
| A feature with lots of scenarios |
|
215
188
|
| A feature with lots of outlines |
|
216
189
|
|
217
|
-
# todo - break out the predefined filters into another feature file?
|
218
|
-
Scenario: Filtering by tags
|
219
|
-
When the following query is executed:
|
220
|
-
"""
|
221
|
-
select name
|
222
|
-
from scenarios
|
223
|
-
with tags '@tag_1', '@tag_2'
|
224
|
-
"""
|
225
|
-
Then the following values are returned:
|
226
|
-
| name |
|
227
|
-
| Test 1 |
|
228
|
-
|
229
|
-
Scenario: Filtering by tag count
|
230
|
-
When the following query is executed:
|
231
|
-
"""
|
232
|
-
select name
|
233
|
-
from scenarios, outlines
|
234
|
-
with tc gt 2
|
235
|
-
"""
|
236
|
-
Then the following values are returned:
|
237
|
-
| name |
|
238
|
-
| Test 3 |
|
239
|
-
|
240
|
-
Scenario: Filtering by name
|
241
|
-
When the following query is executed:
|
242
|
-
"""
|
243
|
-
select name
|
244
|
-
from scenarios, outlines
|
245
|
-
with name 'Test 3'
|
246
|
-
"""
|
247
|
-
Then the following values are returned:
|
248
|
-
| name |
|
249
|
-
| Test 3 |
|
250
|
-
When the following query is executed:
|
251
|
-
"""
|
252
|
-
select name
|
253
|
-
from scenarios, outlines
|
254
|
-
with name /Test [12]/
|
255
|
-
"""
|
256
|
-
Then the following values are returned:
|
257
|
-
| name |
|
258
|
-
| Test 1 |
|
259
|
-
| Test 2 |
|
260
|
-
|
261
|
-
Scenario: Filtering by line
|
262
|
-
When the following query is executed:
|
263
|
-
"""
|
264
|
-
select name
|
265
|
-
from scenarios, outlines
|
266
|
-
with line 'some steps'
|
267
|
-
"""
|
268
|
-
Then the following values are returned:
|
269
|
-
| name |
|
270
|
-
| Test 1 |
|
271
|
-
| Test 3 |
|
272
|
-
When the following query is executed:
|
273
|
-
"""
|
274
|
-
select name
|
275
|
-
from scenarios, outlines
|
276
|
-
with line /other/
|
277
|
-
"""
|
278
|
-
Then the following values are returned:
|
279
|
-
| name |
|
280
|
-
| Test 2 |
|
281
|
-
|
282
|
-
Scenario: Filtering by line count
|
283
|
-
When the following query is executed:
|
284
|
-
"""
|
285
|
-
select name
|
286
|
-
from scenarios, outlines
|
287
|
-
with lc gt 1
|
288
|
-
"""
|
289
|
-
Then the following values are returned:
|
290
|
-
| name |
|
291
|
-
| Test 3 |
|
292
|
-
|
293
|
-
Scenario: Filtering by scenario count
|
294
|
-
When the following query is executed:
|
295
|
-
"""
|
296
|
-
select name
|
297
|
-
from features
|
298
|
-
with sc gt 2
|
299
|
-
"""
|
300
|
-
Then the following values are returned:
|
301
|
-
| name |
|
302
|
-
| A feature with lots of scenarios |
|
303
|
-
|
304
|
-
Scenario: Filtering by outline count
|
305
|
-
When the following query is executed:
|
306
|
-
"""
|
307
|
-
select name
|
308
|
-
from features
|
309
|
-
with soc gt 2
|
310
|
-
"""
|
311
|
-
Then the following values are returned:
|
312
|
-
| name |
|
313
|
-
| A feature with lots of outlines |
|
314
|
-
|
315
|
-
Scenario: Filtering by combined test count
|
316
|
-
When the following query is executed:
|
317
|
-
"""
|
318
|
-
select name
|
319
|
-
from features
|
320
|
-
with ssoc lt 3
|
321
|
-
"""
|
322
|
-
Then the following values are returned:
|
323
|
-
| name |
|
324
|
-
| A feature with a mix of tests |
|
325
|
-
|
326
|
-
@wip
|
327
|
-
Scenario: Using the 'lt' count filter
|
328
|
-
|
329
|
-
@wip
|
330
|
-
Scenario: Using the 'lte' count filter
|
331
|
-
|
332
|
-
@wip
|
333
|
-
Scenario: Using the 'gt' count filter
|
334
|
-
|
335
|
-
@wip
|
336
|
-
Scenario: Using the 'gte' count filter
|
337
|
-
|
338
190
|
Scenario: Using 'without' for negation
|
339
191
|
When the following query is executed:
|
340
192
|
"""
|
@@ -348,15 +200,3 @@ Feature: 'with' clause
|
|
348
200
|
from scenarios
|
349
201
|
with { |scenario| !(scenario.source_line == 8) }
|
350
202
|
"""
|
351
|
-
When the following query is executed:
|
352
|
-
"""
|
353
|
-
select name
|
354
|
-
from features
|
355
|
-
without ssoc lt 3
|
356
|
-
"""
|
357
|
-
Then the result is the same as the result of the following query:
|
358
|
-
"""
|
359
|
-
select name
|
360
|
-
from features
|
361
|
-
with ssoc gt 2
|
362
|
-
"""
|
@@ -2,22 +2,25 @@ Feature: DSL
|
|
2
2
|
|
3
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
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
Sample usage:
|
6
|
+
````
|
7
|
+
cql_repo.query do
|
8
|
+
select name, source_line
|
9
|
+
from features
|
10
|
+
end
|
11
|
+
````
|
10
12
|
|
11
13
|
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
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
````
|
16
|
+
[{'name' => 'Feature 1', 'source_line' => 1},
|
17
|
+
{'name' => 'Feature 2', 'source_line' => 3},
|
18
|
+
{'name' => 'Feature 3', 'source_line' => 10}]
|
19
|
+
````
|
17
20
|
|
18
21
|
Background: A sample Cucumber suite
|
19
|
-
Given a
|
20
|
-
And
|
22
|
+
Given a repository to query
|
23
|
+
And the following feature has been modeled in the repository:
|
21
24
|
"""
|
22
25
|
Feature: A test feature
|
23
26
|
|
@@ -37,7 +40,7 @@ Feature: DSL
|
|
37
40
|
| param |
|
38
41
|
| value |
|
39
42
|
"""
|
40
|
-
|
43
|
+
|
41
44
|
|
42
45
|
Scenario: Automatic string conversion
|
43
46
|
|
@@ -53,25 +56,3 @@ Feature: DSL
|
|
53
56
|
select 'name'
|
54
57
|
from 'scenarios'
|
55
58
|
"""
|
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 |
|
@@ -1,17 +1,5 @@
|
|
1
1
|
Given(/^a directory "([^"]*)"$/) do |partial_directory_path|
|
2
|
-
|
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)
|
2
|
+
create_path(partial_directory_path)
|
15
3
|
end
|
16
4
|
|
17
5
|
Given(/^the models provided by CukeModeler$/) do
|
@@ -2,16 +2,15 @@ Then(/^the following values are returned:$/) do |values|
|
|
2
2
|
expected_keys = values.raw.first
|
3
3
|
expected_results = values.hashes
|
4
4
|
|
5
|
+
# Protecting against false positives
|
6
|
+
# Key order doesn't matter and Ruby 1.8.7 does not retain hash key ordering, so sorting them for consistency
|
7
|
+
raise('Invalid result set. Attribute names cannot be repeated.') unless expected_keys.sort == expected_results.first.keys.sort
|
8
|
+
|
5
9
|
expected_results.each do |result|
|
6
10
|
result.each_pair { |key, value| result[key] = value.to_i if value =~ /^\d+$/ }
|
7
11
|
end
|
8
12
|
|
9
|
-
|
10
|
-
@query_results.each_with_index do |result, index|
|
11
|
-
# Key order doesn't matter and Ruby 1.8.7 does not retain hash key ordering, so sorting them for consistency
|
12
|
-
expect(result.keys.sort).to eq(expected_keys.sort)
|
13
|
-
expect(result).to eq(expected_results[index])
|
14
|
-
end
|
13
|
+
expect(@query_results).to match_array(expected_results)
|
15
14
|
end
|
16
15
|
|
17
16
|
# Then(/^all of them can be queried for additional information$/) do
|
@@ -41,7 +40,7 @@ Then(/^the result is the same as the result of the following query:$/) do |query
|
|
41
40
|
end
|
42
41
|
|
43
42
|
Then(/^the following code executes without error:$/) do |code_text|
|
44
|
-
code_text
|
43
|
+
code_text.sub!('path/to', @temp_dir)
|
45
44
|
|
46
45
|
expect { eval(code_text) }.to_not raise_error
|
47
46
|
end
|
@@ -3,22 +3,22 @@ unless RUBY_VERSION.to_s < '1.9.0'
|
|
3
3
|
SimpleCov.command_name('cql-cucumber')
|
4
4
|
end
|
5
5
|
|
6
|
+
require 'tmpdir'
|
6
7
|
|
7
8
|
require 'cql'
|
8
9
|
require 'cql/model_dsl'
|
9
10
|
|
10
11
|
|
11
|
-
Before do
|
12
|
-
@default_file_directory = "#{File.dirname(__FILE__)}/../temp_files"
|
13
|
-
|
14
|
-
FileUtils.mkdir(@default_file_directory)
|
15
|
-
end
|
16
|
-
|
17
12
|
After do
|
18
|
-
FileUtils.remove_dir(@
|
13
|
+
FileUtils.remove_dir(@temp_dir, true) if @temp_dir
|
19
14
|
end
|
20
15
|
|
21
16
|
|
22
|
-
def
|
23
|
-
|
17
|
+
def create_path(path)
|
18
|
+
@temp_dir ||= Dir.mktmpdir
|
19
|
+
path = path.sub('path/to/', "#{@temp_dir}/")
|
20
|
+
|
21
|
+
Dir.mkdir(path)
|
22
|
+
|
23
|
+
path
|
24
24
|
end
|