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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/lib/cql.rb +4 -169
  3. data/lib/cql/dsl.rb +39 -5
  4. data/lib/cql/feature_filters.rb +2 -0
  5. data/lib/cql/filters.rb +25 -1
  6. data/lib/cql/map_reduce.rb +3 -0
  7. data/lib/cql/model_dsl.rb +7 -1
  8. data/lib/cql/queriable.rb +6 -1
  9. data/lib/cql/query.rb +157 -0
  10. data/lib/cql/repository.rb +25 -0
  11. data/lib/cql/sso_filters.rb +4 -0
  12. data/lib/cql/version.rb +2 -1
  13. data/testing/cucumber/features/clauses/as_clause.feature +10 -9
  14. data/testing/cucumber/features/clauses/from_clause.feature +15 -20
  15. data/testing/cucumber/features/clauses/predefined_with_filters.feature +392 -0
  16. data/testing/cucumber/features/clauses/select_clause.feature +11 -14
  17. data/testing/cucumber/features/clauses/transform_clause.feature +10 -9
  18. data/testing/cucumber/features/clauses/with_clause.feature +10 -170
  19. data/testing/cucumber/features/dsl.feature +15 -34
  20. data/testing/cucumber/step_definitions/setup_steps.rb +1 -13
  21. data/testing/cucumber/step_definitions/verification_steps.rb +6 -7
  22. data/testing/cucumber/support/env.rb +9 -9
  23. data/testing/gemfiles/cuke_modeler0.gemfile +10 -7
  24. data/testing/gemfiles/cuke_modeler1.gemfile +6 -7
  25. data/testing/gemfiles/cuke_modeler2.gemfile +33 -0
  26. data/testing/gemfiles/cuke_modeler3.gemfile +10 -0
  27. data/testing/helper_methods.rb +13 -0
  28. data/testing/model_helper.rb +28 -0
  29. data/testing/rspec/spec/clauses/as_clause_spec.rb +1 -0
  30. data/testing/rspec/spec/clauses/from_clause_spec.rb +146 -0
  31. data/testing/rspec/spec/clauses/select_clause_spec.rb +184 -0
  32. data/testing/rspec/spec/clauses/transform_clause_spec.rb +35 -0
  33. data/testing/rspec/spec/clauses/with_clause_spec.rb +84 -0
  34. data/testing/rspec/spec/clauses/without_clause_spec.rb +171 -0
  35. data/testing/rspec/spec/cql_spec.rb +25 -0
  36. data/testing/rspec/spec/dsl_spec.rb +3 -575
  37. data/testing/rspec/spec/filter_example_spec.rb +1 -1
  38. data/testing/rspec/spec/filter_feature_dsl_spec.rb +13 -13
  39. data/testing/rspec/spec/filter_sso_spec.rb +2 -2
  40. data/testing/rspec/spec/line_filterable_specs.rb +1 -1
  41. data/testing/rspec/spec/map_reduce_spec.rb +1 -1
  42. data/testing/rspec/spec/model_query_spec.rb +1 -1
  43. data/testing/rspec/spec/multiple_queries_spec.rb +1 -1
  44. data/testing/rspec/spec/name_filterable_specs.rb +1 -1
  45. data/testing/rspec/spec/predefined_filters_spec.rb +284 -0
  46. data/testing/rspec/spec/repository_spec.rb +3 -3
  47. data/testing/rspec/spec/select_feature_dsl_spec.rb +8 -8
  48. data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +14 -14
  49. data/testing/rspec/spec/select_scenario_dsl_spec.rb +9 -9
  50. data/testing/rspec/spec/spec_helper.rb +7 -17
  51. metadata +52 -23
  52. 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
- Sample usage:
6
- cql_repo.query do
7
- select name, tags, description_text
8
- from features
9
- end
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: A sample Cucumber suite
15
- Given a directory "test_directory"
16
- And a file "test_directory/test_file_1.feature":
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: Repetitive selection
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
- Sample usage:
6
- cql_repo.query do
7
- select name
8
- transform { |name| name.upcase }
9
- from features
10
- end
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 directory "test_directory"
18
- And a file "test_directory/test_file_1.feature":
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 (detailed below).
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
- Sample usage:
7
- cql_repo.query do
8
- select name, tags, description_text
9
- from features
10
- with { |feature| feature.name =~ /foo/ }
11
- with tc lt 3
12
- end
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 => tags('@tag_1','@tag_2')
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
- Sample usage:
6
- cql_repo.query do
7
- select name, source_line
8
- from features
9
- end
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
- [{'name' => 'Feature 1', 'source_line' => 1},
14
- {'name' => 'Feature 2', 'source_line' => 3},
15
- {'name' => 'Feature 3', 'source_line' => 10}]
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 directory "test_directory"
20
- And a file "test_directory/test_file_1.feature":
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
- And a repository is made from "test_directory"
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
- 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)
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 = process_path(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(@default_file_directory, true)
13
+ FileUtils.remove_dir(@temp_dir, true) if @temp_dir
19
14
  end
20
15
 
21
16
 
22
- def process_path(path)
23
- path.sub('path/to', @default_file_directory)
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