tdc 0.2.4 → 0.3.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea6a4c15535d29f9f7ab47c6ec12f4c20cc59f588543b19869324f5901097c24
4
- data.tar.gz: c5d57e1578f9550a725f20f6ef396bd2bb3d5791773929afd9c6605d8686f2b3
3
+ metadata.gz: bf0ce48e5dd1a629ad0c5240f9c3d8c344b46cf368e01bb842eefb3454167b4e
4
+ data.tar.gz: a85d7fef856826f3a4a4112c4e4186c1e813f8a52de500466ba0b9acfe559fe5
5
5
  SHA512:
6
- metadata.gz: 7829e509a7c5ef3c7db2b947ee109af96a442c662ccb15e0f5ab50a04e70f91eef039944b65a4b6dfcf9eae232e249146062067c79a2ca955cff2027b0aee649
7
- data.tar.gz: 20eefb49010d15905073f5f823bdc171cc428e5c2ef1217d61ec17210d4426f4dd7de4312c56167cd4b67b37d43c2049b3cfc90b0a8b51f4577eb5c884b94841
6
+ metadata.gz: 250b3ebace2728d87756a51f7075c3f318637997e5473bb90c4cccd820326f77ebf00429e57e885467d837b969c166b43f5044d75b028022f0dcd1464f7967bd
7
+ data.tar.gz: 8082f7dbdcd16c0a7cacb94af1479d0df9e4a12a83ec57556f0e6a865e18d5a5d7fa4d14cc2e3e8c3886c2ae2373bf64733e138072f262b1efc27e89ea259798
@@ -10,6 +10,9 @@ AllCops:
10
10
  Layout/EmptyLinesAroundAttributeAccessor:
11
11
  Enabled: true
12
12
 
13
+ Metrics/LineLength:
14
+ Max: 120
15
+
13
16
  # Rubocop and I cannot agree.
14
17
  Layout/MultilineMethodCallBraceLayout:
15
18
  Enabled: false
@@ -17,6 +20,15 @@ Layout/MultilineMethodCallBraceLayout:
17
20
  Layout/SpaceAroundMethodCallOperator:
18
21
  Enabled: true
19
22
 
23
+ Lint/DeprecatedOpenSSLConstant:
24
+ Enabled: true
25
+
26
+ Lint/DuplicateElsifCondition:
27
+ Enabled: true
28
+
29
+ Lint/MixedRegexpCaptureTypes:
30
+ Enabled: true
31
+
20
32
  Lint/RaiseException:
21
33
  Enabled: true
22
34
 
@@ -35,9 +47,6 @@ RSpec/AnyInstance:
35
47
  RSpec/ExampleLength:
36
48
  Max: 15
37
49
 
38
- Metrics/LineLength:
39
- Max: 120
40
-
41
50
  RSpec/DescribeClass:
42
51
  Enabled: false
43
52
 
@@ -59,6 +68,15 @@ RSpec/MultipleExpectations:
59
68
  RSpec/SubjectStub:
60
69
  Enabled: false
61
70
 
71
+ Style/AccessorGrouping:
72
+ Enabled: true
73
+
74
+ Style/ArrayCoercion:
75
+ Enabled: true
76
+
77
+ Style/BisectedAttrAccessor:
78
+ Enabled: true
79
+
62
80
  Style/BlockDelimiters:
63
81
  Enabled: true
64
82
  EnforcedStyle: line_count_based
@@ -66,6 +84,9 @@ Style/BlockDelimiters:
66
84
  - 'let'
67
85
  - 'subject'
68
86
 
87
+ Style/CaseLikeIf:
88
+ Enabled: true
89
+
69
90
  Style/Documentation:
70
91
  Enabled: false
71
92
 
@@ -79,9 +100,15 @@ Style/ExponentialNotation:
79
100
  Style/FrozenStringLiteralComment:
80
101
  Enabled: false
81
102
 
103
+ Style/HashAsLastArrayItem:
104
+ Enabled: true
105
+
82
106
  Style/HashEachMethods:
83
107
  Enabled: true
84
108
 
109
+ Style/HashLikeCase:
110
+ Enabled: true
111
+
85
112
  Style/HashTransformKeys:
86
113
  Enabled: true
87
114
 
@@ -93,6 +120,21 @@ Style/HashSyntax:
93
120
  Exclude:
94
121
  - 'Rakefile'
95
122
 
123
+ Style/RedundantAssignment:
124
+ Enabled: true
125
+
126
+ Style/RedundantFetchBlock:
127
+ Enabled: true
128
+
129
+ Style/RedundantFileExtensionInRequire:
130
+ Enabled: true
131
+
132
+ Style/RedundantRegexpCharacterClass:
133
+ Enabled: true
134
+
135
+ Style/RedundantRegexpEscape:
136
+ Enabled: true
137
+
96
138
  # No need to mention StandardError.
97
139
  Style/RescueStandardError:
98
140
  EnforcedStyle: implicit
@@ -6,6 +6,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.4] - 2020-08-05
10
+
11
+ #### Breaking Changes
12
+
13
+ - Introduce the `GenerationContext` abstraction
14
+ - All generators are initialized with an instance of `Tdc::GenerationContext`
15
+
16
+ ## [0.3.3] - 2020-08-04
17
+
18
+ - Add the `empty?` method to `CatalogEntries`
19
+ - Evaluate `_atx` attribute values against a `Time.zone` instance
20
+
21
+ ## [0.3.2] - 2020-07-27
22
+
23
+ - Return `self` from `DefinitionResolver#configure_current_catalog` to make it chainable
24
+
25
+ ## [0.3.1] - 2020-07-25
26
+
27
+ - Support DefinitionResolver instance registration
28
+
29
+ ## [0.3.0] - 2020-07-19
30
+
31
+ - Introduce the DefinitionResolver abstraction
32
+
9
33
  ## [0.2.4] - 2020-07-19
10
34
 
11
35
  - Improve Tdc::MissingOverrideError diagnostics
@@ -38,5 +62,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
38
62
  #### New Features
39
63
 
40
64
  - Avoid all PackManager dependencies
41
-
42
-
data/README.md CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  Define your own test data generators by inheriting from ```StandardGenerator``` or ```SingularGenerator```. Best practice is to define an ```ApplicationStandardGenerator``` and an ```ApplicationSingularGenerator``` and have all other generators inherit from them.
8
8
 
9
+ Define your own definition resolvers by inheriting from ```DefinitionResolver```. Best practice is to define an ```ApplicationDefinitionResolver``` and all other definition resolvers inherit from it.
10
+
9
11
  During generation the test data catalog will be represented by ```CatalogEntries``` that are populated by reading from ```YAML``` files with a ```DataDefinitionReader``` or provided directly by an ```InMemoryDataDefinition```.
10
12
 
11
13
  **Data Definition DSL**
Binary file
data/lib/tdc.rb CHANGED
@@ -19,6 +19,7 @@ require "tdc/with_indifferent_access_decorator"
19
19
 
20
20
  # Generators
21
21
  require "tdc/generators"
22
+ require "tdc/generators/generation_context"
22
23
 
23
24
  # Current Catalog
24
25
  require "tdc/generators/catalog_entries"
@@ -33,6 +34,11 @@ require "tdc/generators/configurable_generator"
33
34
  require "tdc/generators/singular_generator"
34
35
  require "tdc/generators/standard_generator"
35
36
 
37
+ # Definition Resolvers
38
+ require "tdc/definition_resolvers"
39
+ require "tdc/definition_resolvers/definition_resolver"
40
+ require "tdc/definition_resolvers/tag_resolver"
41
+
36
42
  #
37
43
  # A framework for building a Test Data Catalog
38
44
  #
@@ -0,0 +1,7 @@
1
+ module Tdc
2
+ #
3
+ # Namespace to host definition resolvers.
4
+ #
5
+ module DefinitionResolvers
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ module Tdc
2
+ module DefinitionResolvers
3
+ #
4
+ # Base class for any definition resolver.
5
+ #
6
+ class DefinitionResolver
7
+ attr_reader :current_catalog
8
+
9
+ def configure_current_catalog(current_catalog)
10
+ @current_catalog = current_catalog
11
+
12
+ self
13
+ end
14
+
15
+ def resolve(_instance_definition)
16
+ raise Tdc::MissingOverrideError, "Implement the 'resolve' method"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ module Tdc
2
+ module DefinitionResolvers
3
+ #
4
+ # Knows how to resolve the tag value for the specified instance_definition key by replacing it
5
+ # with an object sourced from the current catalog.
6
+ #
7
+ class TagResolver < Tdc::DefinitionResolvers::DefinitionResolver
8
+ attr_reader :key, :source
9
+
10
+ def initialize(key:, source:)
11
+ @key = key
12
+ @source = source
13
+ end
14
+
15
+ def resolve(instance_definition)
16
+ return unless instance_definition.key?(key)
17
+
18
+ # Lookup the source catalog entry in the current_catalog.
19
+ catalog_entry = instance_eval("current_catalog.#{source}", __FILE__, __LINE__)
20
+
21
+ # Before resolution the instance definition value is a tag.
22
+ tag = instance_definition[key]
23
+
24
+ # Use the tag to source an object from the current catalog.
25
+ sourced_object = catalog_entry.send(tag)
26
+
27
+ unless sourced_object
28
+ message = "Could not find a tag reference for '#{key}' in the catalog entries provided."
29
+
30
+ raise Tdc::FatalError, message
31
+ end
32
+
33
+ # Replace the tag value with the sourced object.
34
+ instance_definition[key] = sourced_object
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,6 +1,6 @@
1
1
  module Tdc
2
2
  #
3
- # Namespace to host generators
3
+ # Namespace to host generators.
4
4
  #
5
5
  module Generators
6
6
  end
@@ -8,6 +8,10 @@ module Tdc
8
8
  def add_catalog_entry(tag, entry)
9
9
  send("#{tag}=", entry)
10
10
  end
11
+
12
+ def empty?
13
+ to_h.empty?
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -14,7 +14,7 @@ module Tdc
14
14
 
15
15
  def run_resolvers_and_generate_instance
16
16
  run_atx_resolvers(instance_definition)
17
- run_tag_resolvers(instance_definition)
17
+ run_definition_resolvers(instance_definition)
18
18
 
19
19
  generate_instance
20
20
  end
@@ -29,7 +29,7 @@ module Tdc
29
29
  #
30
30
  # Hook method: subclasses may include the DefinitionResolvable concern to override.
31
31
  #
32
- def run_tag_resolvers(_instance_definition)
32
+ def run_definition_resolvers(_instance_definition)
33
33
  # Do nothing
34
34
  end
35
35
 
@@ -44,12 +44,15 @@ module Tdc
44
44
  def run_atx_resolvers(instance_definition)
45
45
  atx_definitions = instance_definition.select { |k, _v| /_atx$/ =~ k }
46
46
 
47
+ # ARM (2020-08-04): Move all the way out so that all generators use the same atx_context.
48
+ atx_context = Time.zone
49
+
47
50
  atx_definitions.each do |k, v|
48
51
  # Remove the original _atx attribute.
49
52
  instance_definition.delete(k)
50
53
 
51
54
  # Add a standard _at attribute.
52
- instance_definition[k.delete_suffix("x")] = eval(v) # rubocop:disable Security/Eval
55
+ instance_definition[k.delete_suffix("x")] = atx_context.instance_eval(v)
53
56
  end
54
57
  end
55
58
  end
@@ -1,61 +1,48 @@
1
1
  module Tdc
2
2
  module Generators
3
3
  #
4
- # Knows how to resolve tag values in an instance definition. The tag value will be replaced
5
- # with a model instance from the current catalog.
4
+ # Knows how to resolve attribute values in an instance definition. The attribute value will be replaced
5
+ # by the result of invoking the registered resolver.
6
6
  #
7
- # The resolve_tag class macro is provided for generators to define tag resolution.
7
+ # The resolve_tag class macro is provided for generators to define tag resolution. The test data definition
8
+ # YAML file has attribute values than contain a catalog entry tag.
8
9
  #
9
10
  # Example:
10
11
  #
11
- # Suppose a particular instance definition contained { subcomponent: sc_snackers_minis }
12
- # then a generator could resolve the subcomponent by defining:
12
+ # Suppose a particular instance definition contained { subcomponent: sc_snackers_minis } then a generator
13
+ # could resolve the subcomponent tag to the current catalog by defining:
13
14
  #
14
15
  # resolve_tag key: :subcomponent, source: "item_master.items"
15
16
  #
17
+ # The register_definition_resolver class macro is provided for generators to define and register their own
18
+ # definition resolvers. The test data definition YAML file has attribute values than contain an arbitrary
19
+ # value that will typically be replaced by an instance of an object returned by the specified resolver.
20
+ #
16
21
  module DefinitionResolvable
17
22
  extend ActiveSupport::Concern
18
23
 
19
24
  included do
20
- class_attribute :_tag_resolvers, instance_writer: false
21
- self._tag_resolvers = []
25
+ class_attribute :_definition_resolvers, instance_writer: false
26
+
27
+ self._definition_resolvers = []
22
28
  end
23
29
 
24
30
  class_methods do
25
- def resolve_tag(key:, source:)
26
- _tag_resolvers << [key, source]
31
+ def register_definition_resolver(resolver_instance)
32
+ _definition_resolvers << resolver_instance
27
33
  end
28
- end
29
34
 
30
- def run_tag_resolvers(instance_definition)
31
- _tag_resolvers.each { |key, source| _resolve_tag_reference(instance_definition, key, source) }
35
+ def resolve_tag(key:, source:)
36
+ register_definition_resolver(Tdc::DefinitionResolvers::TagResolver.new(key: key, source: source))
37
+ end
32
38
  end
33
39
 
34
- private
40
+ def run_definition_resolvers(instance_definition)
41
+ _definition_resolvers.each do |definition_resolver|
42
+ definition_resolver.configure_current_catalog(current_catalog)
35
43
 
36
- #
37
- # Replace the tag value for the specified instance_definition key with an object sourced from the current catalog.
38
- #
39
- def _resolve_tag_reference(instance_definition, key, source)
40
- return unless instance_definition.key?(key)
41
-
42
- # Lookup the source catalog entry in the current_catalog.
43
- catalog_entry = instance_eval("current_catalog.#{source}", __FILE__, __LINE__)
44
-
45
- # Before resolution the instance definition value is a tag.
46
- tag = instance_definition[key]
47
-
48
- # Use the tag to source an object from the current catalog.
49
- sourced_object = catalog_entry.send(tag)
50
-
51
- unless sourced_object
52
- message = "Could not find a tag reference for '#{key}' in the catalog entries provided."
53
-
54
- raise Tdc::FatalError, message
44
+ definition_resolver.resolve(instance_definition)
55
45
  end
56
-
57
- # Replace the tag value with the sourced object.
58
- instance_definition[key] = sourced_object
59
46
  end
60
47
  end
61
48
  end
@@ -0,0 +1,15 @@
1
+ module Tdc
2
+ module Generators
3
+ #
4
+ # Knows all the parameters that define the context for generation.
5
+ #
6
+ class GenerationContext
7
+ attr_reader :current_catalog, :data_definition
8
+
9
+ def initialize(current_catalog:, data_definition:)
10
+ @current_catalog = current_catalog
11
+ @data_definition = data_definition
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,11 +4,13 @@ module Tdc
4
4
  # Abstract base class for all Test Data Catalog generators.
5
5
  #
6
6
  class GeneratorBase
7
- attr_reader :data_definition, :current_catalog
7
+ attr_reader :generation_context
8
8
 
9
- def initialize(data_definition, current_catalog)
10
- @data_definition = data_definition
11
- @current_catalog = current_catalog
9
+ # ARM (2020-08-05): For backwards compatibility. Consider removing.
10
+ delegate :current_catalog, :data_definition, to: :generation_context
11
+
12
+ def initialize(generation_context)
13
+ @generation_context = generation_context
12
14
  end
13
15
 
14
16
  def generate
@@ -1,3 +1,3 @@
1
1
  module Tdc
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.4"
3
3
  end
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.summary = "A simple framework for creating a Test Data Catalog"
10
10
  spec.homepage = "https://github.com/nulogy/tdc"
11
+ spec.license = "MIT"
11
12
 
12
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
13
14
 
@@ -31,7 +32,7 @@ Gem::Specification.new do |spec|
31
32
 
32
33
  spec.add_development_dependency "rake", ">= 12.1", "< 13.1"
33
34
  spec.add_development_dependency "rspec", ">= 3.9", "< 4.0"
34
- spec.add_development_dependency "rubocop", "~> 0.82"
35
- spec.add_development_dependency "rubocop-rspec", "~> 1.38"
35
+ spec.add_development_dependency "rubocop", "~> 0.88"
36
+ spec.add_development_dependency "rubocop-rspec", "~> 1.42"
36
37
  spec.add_development_dependency "simplecov", "~> 0.17"
37
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tdc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alistair McKinnell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-19 00:00:00.000000000 Z
11
+ date: 2020-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -70,28 +70,28 @@ dependencies:
70
70
  requirements:
71
71
  - - "~>"
72
72
  - !ruby/object:Gem::Version
73
- version: '0.82'
73
+ version: '0.88'
74
74
  type: :development
75
75
  prerelease: false
76
76
  version_requirements: !ruby/object:Gem::Requirement
77
77
  requirements:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
- version: '0.82'
80
+ version: '0.88'
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rubocop-rspec
83
83
  requirement: !ruby/object:Gem::Requirement
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: '1.38'
87
+ version: '1.42'
88
88
  type: :development
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: '1.38'
94
+ version: '1.42'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: simplecov
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -128,12 +128,16 @@ files:
128
128
  - lib/tdc.rb
129
129
  - lib/tdc/data_definition.rb
130
130
  - lib/tdc/data_definition_file_reader.rb
131
+ - lib/tdc/definition_resolvers.rb
132
+ - lib/tdc/definition_resolvers/definition_resolver.rb
133
+ - lib/tdc/definition_resolvers/tag_resolver.rb
131
134
  - lib/tdc/fatal_error.rb
132
135
  - lib/tdc/generators.rb
133
136
  - lib/tdc/generators/catalog_entries.rb
134
137
  - lib/tdc/generators/configurable_generator.rb
135
138
  - lib/tdc/generators/definition_resolvable.rb
136
139
  - lib/tdc/generators/definition_sourcable.rb
140
+ - lib/tdc/generators/generation_context.rb
137
141
  - lib/tdc/generators/generator_base.rb
138
142
  - lib/tdc/generators/singular_generator.rb
139
143
  - lib/tdc/generators/standard_generator.rb
@@ -143,7 +147,8 @@ files:
143
147
  - lib/tdc/with_indifferent_access_decorator.rb
144
148
  - tdc.gemspec
145
149
  homepage: https://github.com/nulogy/tdc
146
- licenses: []
150
+ licenses:
151
+ - MIT
147
152
  metadata:
148
153
  homepage_uri: https://github.com/nulogy/tdc
149
154
  changelog_uri: https://github.com/nulogy/tdc/blob/master/CHANGELOG.md