tdc 0.2.0 → 0.3.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 +4 -4
- data/.editorconfig +16 -0
- data/.rspec +1 -1
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +20 -0
- data/README.md +3 -1
- data/images/Tdc.png +0 -0
- data/lib/tdc.rb +23 -4
- data/lib/tdc/data_definition.rb +1 -1
- data/lib/tdc/definition_resolvers.rb +7 -0
- data/lib/tdc/definition_resolvers/definition_resolver.rb +18 -0
- data/lib/tdc/definition_resolvers/tag_resolver.rb +38 -0
- data/lib/tdc/generators.rb +1 -1
- data/lib/tdc/generators/{instance_definition_configurable.rb → configurable_generator.rb} +15 -18
- data/lib/tdc/generators/definition_resolvable.rb +33 -35
- data/lib/tdc/generators/definition_sourcable.rb +2 -2
- data/lib/tdc/generators/generator_base.rb +2 -2
- data/lib/tdc/generators/singular_generator.rb +7 -11
- data/lib/tdc/generators/standard_generator.rb +1 -3
- data/lib/tdc/missing_override_error.rb +1 -5
- data/lib/tdc/version.rb +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d7775cd9909b7d1aef1f59def823777cc24d6bbfc50ddfd41eda202f5f5f387
|
4
|
+
data.tar.gz: 11b7ddadec9d97e1953f34efdee8b66d6f0cb08213dd8d9a9e9d4ae8372687fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f396da321ee096251062cd35ff6add1d19292591dc8fa019509fe432f2fd7faea74844ee4583fbb30bc03e9f8106fbeabdb403732ec5098d70c40b69e2c216c
|
7
|
+
data.tar.gz: 69cfdaa1a302ae2d458f6775db22134953db4f6f584ba9af36970f4865d308de9a44d9c5c6ec10e7db0a4ec5c05d340254a4458dfc843d6676225459e2542660
|
data/.editorconfig
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
root = true
|
2
|
+
|
3
|
+
[*]
|
4
|
+
|
5
|
+
# Change these settings to your own preference
|
6
|
+
indent_style = space
|
7
|
+
indent_size = 2
|
8
|
+
|
9
|
+
# We recommend you to keep these unchanged
|
10
|
+
end_of_line = lf
|
11
|
+
charset = utf-8
|
12
|
+
trim_trailing_whitespace = true
|
13
|
+
insert_final_newline = true
|
14
|
+
|
15
|
+
[*.md]
|
16
|
+
trim_trailing_whitespace = false
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -64,10 +64,14 @@ Style/BlockDelimiters:
|
|
64
64
|
EnforcedStyle: line_count_based
|
65
65
|
BracesRequiredMethods:
|
66
66
|
- 'let'
|
67
|
+
- 'subject'
|
67
68
|
|
68
69
|
Style/Documentation:
|
69
70
|
Enabled: false
|
70
71
|
|
72
|
+
Style/EmptyMethod:
|
73
|
+
EnforcedStyle: expanded
|
74
|
+
|
71
75
|
Style/ExponentialNotation:
|
72
76
|
Enabled: true
|
73
77
|
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.3.0] - 2020-07-19
|
10
|
+
|
11
|
+
- Introduce the DefinitionResolver abstraction
|
12
|
+
|
13
|
+
## [0.2.4] - 2020-07-19
|
14
|
+
|
15
|
+
- Improve Tdc::MissingOverrideError diagnostics
|
16
|
+
|
17
|
+
## [0.2.3] - 2020-05-21
|
18
|
+
|
19
|
+
- Update the diagram in the README
|
20
|
+
|
21
|
+
## [0.2.2] - 2020-05-20
|
22
|
+
|
23
|
+
- Adding specs
|
24
|
+
|
25
|
+
## [0.2.1] - 2020-05-19
|
26
|
+
|
27
|
+
- Adding specs
|
28
|
+
|
9
29
|
## [0.2.0] - 2020-05-19
|
10
30
|
|
11
31
|
#### Breaking Changes
|
data/README.md
CHANGED
@@ -4,7 +4,9 @@
|
|
4
4
|
|
5
5
|
**Extension Points**
|
6
6
|
|
7
|
-
Define your own test data generators by inheriting from ```StandardGenerator``` or ```
|
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
|
+
|
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.
|
8
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
|
|
data/images/Tdc.png
CHANGED
Binary file
|
data/lib/tdc.rb
CHANGED
@@ -1,24 +1,43 @@
|
|
1
1
|
require "ostruct"
|
2
|
+
require "yaml"
|
2
3
|
|
4
|
+
require "active_support"
|
3
5
|
require "active_support/concern"
|
4
|
-
require "active_support/core_ext
|
6
|
+
require "active_support/core_ext"
|
5
7
|
|
8
|
+
require "tdc/version"
|
9
|
+
|
10
|
+
# Errors
|
11
|
+
require "tdc/fatal_error"
|
12
|
+
require "tdc/missing_override_error"
|
13
|
+
|
14
|
+
# Data Definition Hierarchy
|
6
15
|
require "tdc/data_definition"
|
7
16
|
require "tdc/data_definition_file_reader"
|
8
|
-
require "tdc/fatal_error"
|
9
17
|
require "tdc/in_memory_data_definition"
|
10
|
-
require "tdc/version"
|
11
18
|
require "tdc/with_indifferent_access_decorator"
|
12
19
|
|
20
|
+
# Generators
|
13
21
|
require "tdc/generators"
|
22
|
+
|
23
|
+
# Current Catalog
|
14
24
|
require "tdc/generators/catalog_entries"
|
25
|
+
|
26
|
+
# Concerns
|
15
27
|
require "tdc/generators/definition_resolvable"
|
16
28
|
require "tdc/generators/definition_sourcable"
|
29
|
+
|
30
|
+
# Generator Hierarchy
|
17
31
|
require "tdc/generators/generator_base"
|
18
|
-
require "tdc/generators/
|
32
|
+
require "tdc/generators/configurable_generator"
|
19
33
|
require "tdc/generators/singular_generator"
|
20
34
|
require "tdc/generators/standard_generator"
|
21
35
|
|
36
|
+
# Definition Resolvers
|
37
|
+
require "tdc/definition_resolvers"
|
38
|
+
require "tdc/definition_resolvers/definition_resolver"
|
39
|
+
require "tdc/definition_resolvers/tag_resolver"
|
40
|
+
|
22
41
|
#
|
23
42
|
# A framework for building a Test Data Catalog
|
24
43
|
#
|
data/lib/tdc/data_definition.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
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
|
+
end
|
12
|
+
|
13
|
+
def resolve(_instance_definition)
|
14
|
+
raise Tdc::MissingOverrideError, "Implement the 'resolve' method"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
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
|
data/lib/tdc/generators.rb
CHANGED
@@ -5,27 +5,16 @@ module Tdc
|
|
5
5
|
#
|
6
6
|
# Shared implementation between the StandardGenerator and the SingularGenerator abstract classes.
|
7
7
|
#
|
8
|
-
|
9
|
-
|
8
|
+
class ConfigurableGenerator < Tdc::Generators::GeneratorBase
|
9
|
+
include Tdc::Generators::DefinitionSourcable
|
10
10
|
|
11
|
-
|
12
|
-
include Tdc::Generators::DefinitionSourcable
|
11
|
+
attr_reader :instance_definition
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
source_definition_from :instance_definition
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def configure_instance_definition(instance_definition)
|
22
|
-
@instance_definition = instance_definition
|
23
|
-
configure_definition_source(instance_definition)
|
24
|
-
end
|
13
|
+
source_definition_from :instance_definition
|
25
14
|
|
26
15
|
def run_resolvers_and_generate_instance
|
27
16
|
run_atx_resolvers(instance_definition)
|
28
|
-
|
17
|
+
run_definition_resolvers(instance_definition)
|
29
18
|
|
30
19
|
generate_instance
|
31
20
|
end
|
@@ -34,16 +23,24 @@ module Tdc
|
|
34
23
|
# Hook method: subclasses are expected to define how to generate a model instance.
|
35
24
|
#
|
36
25
|
def generate_instance
|
37
|
-
raise Tdc::MissingOverrideError
|
26
|
+
raise Tdc::MissingOverrideError, "Implement the 'generate_instance' method"
|
38
27
|
end
|
39
28
|
|
40
29
|
#
|
41
30
|
# Hook method: subclasses may include the DefinitionResolvable concern to override.
|
42
31
|
#
|
43
|
-
def
|
32
|
+
def run_definition_resolvers(_instance_definition)
|
44
33
|
# Do nothing
|
45
34
|
end
|
46
35
|
|
36
|
+
private
|
37
|
+
|
38
|
+
def configure_instance_definition(instance_definition)
|
39
|
+
@instance_definition = instance_definition
|
40
|
+
|
41
|
+
configure_definition_source(instance_definition)
|
42
|
+
end
|
43
|
+
|
47
44
|
def run_atx_resolvers(instance_definition)
|
48
45
|
atx_definitions = instance_definition.select { |k, _v| /_atx$/ =~ k }
|
49
46
|
|
@@ -1,61 +1,59 @@
|
|
1
1
|
module Tdc
|
2
2
|
module Generators
|
3
3
|
#
|
4
|
-
# Knows how to resolve
|
5
|
-
#
|
4
|
+
# Knows how to resolve attribute values in an instance definition. The attribute value will be replaced
|
5
|
+
# by the result of invoking the specified 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
|
-
#
|
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 resolve_definition class macro is provided for generators to define definition resolution. The test data
|
18
|
+
# definition YAML file has attribute values than contain an arbitrary value that will typically be replaced by
|
19
|
+
# an instance of an object returned by the specified resolver.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
#
|
23
|
+
# Suppose a particular instance definition contained { pallet_number: P0001 } then a generator could resolve
|
24
|
+
# the pallet_number to a pallet instance by defining:
|
25
|
+
#
|
26
|
+
# resolve_definition :pallet_number, to: :pallet_id, resolver: "TestDataCatalog::Resolvers::PalletNumberResolver"
|
27
|
+
#
|
28
|
+
# The PalletNumberResolver class inherits from Tdc::DefinitionResolvers::DefinitionResolver.
|
29
|
+
#
|
16
30
|
module DefinitionResolvable
|
17
31
|
extend ActiveSupport::Concern
|
18
32
|
|
19
33
|
included do
|
20
|
-
class_attribute :
|
21
|
-
|
34
|
+
class_attribute :_definition_resolvers, instance_writer: false
|
35
|
+
|
36
|
+
self._definition_resolvers = []
|
22
37
|
end
|
23
38
|
|
24
39
|
class_methods do
|
25
|
-
def
|
26
|
-
|
40
|
+
def resolve_definition(key:, to: nil, resolver:)
|
41
|
+
resolver_instance = resolver.constantize.new(key: key, to: to || key)
|
42
|
+
|
43
|
+
_definition_resolvers << resolver_instance
|
27
44
|
end
|
28
|
-
end
|
29
45
|
|
30
|
-
|
31
|
-
|
46
|
+
def resolve_tag(key:, source:)
|
47
|
+
_definition_resolvers << Tdc::DefinitionResolvers::TagResolver.new(key: key, source: source)
|
48
|
+
end
|
32
49
|
end
|
33
50
|
|
34
|
-
|
35
|
-
|
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__)
|
51
|
+
def run_definition_resolvers(instance_definition)
|
52
|
+
_definition_resolvers.each do |definition_resolver|
|
53
|
+
definition_resolver.configure_current_catalog(current_catalog)
|
44
54
|
|
45
|
-
|
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
|
55
|
+
definition_resolver.resolve(instance_definition)
|
55
56
|
end
|
56
|
-
|
57
|
-
# Replace the tag value with the sourced object.
|
58
|
-
instance_definition[key] = sourced_object
|
59
57
|
end
|
60
58
|
end
|
61
59
|
end
|
@@ -35,13 +35,13 @@ module Tdc
|
|
35
35
|
def method_missing(method, *args)
|
36
36
|
key = transform_method_to_definition_source_key(method)
|
37
37
|
|
38
|
-
definition_source
|
38
|
+
definition_source&.key?(key) ? definition_source.fetch(key) : super
|
39
39
|
end
|
40
40
|
|
41
41
|
def respond_to_missing?(method, include_all = false)
|
42
42
|
key = transform_method_to_definition_source_key(method)
|
43
43
|
|
44
|
-
definition_source
|
44
|
+
definition_source&.key?(key) ? true : super
|
45
45
|
end
|
46
46
|
|
47
47
|
def transform_method_to_definition_source_key(method)
|
@@ -12,11 +12,11 @@ module Tdc
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def generate
|
15
|
-
raise Tdc::MissingOverrideError
|
15
|
+
raise Tdc::MissingOverrideError, "Implement the 'generate' method"
|
16
16
|
end
|
17
17
|
|
18
18
|
def instance_definitions
|
19
|
-
raise Tdc::MissingOverrideError
|
19
|
+
raise Tdc::MissingOverrideError, "Implement the 'instance_definitions' method"
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -5,15 +5,7 @@ module Tdc
|
|
5
5
|
#
|
6
6
|
# See also StandardGenerator.
|
7
7
|
#
|
8
|
-
class SingularGenerator < Tdc::Generators::
|
9
|
-
include Tdc::Generators::InstanceDefinitionConfigurable
|
10
|
-
|
11
|
-
def initialize(data_definition, current_catalog)
|
12
|
-
super
|
13
|
-
|
14
|
-
@additional_definitions = {}
|
15
|
-
end
|
16
|
-
|
8
|
+
class SingularGenerator < Tdc::Generators::ConfigurableGenerator
|
17
9
|
def with_definition(additional_definitions)
|
18
10
|
@additional_definitions = additional_definitions.stringify_keys.reject { |_, v| v == :missing_definition }
|
19
11
|
|
@@ -21,18 +13,22 @@ module Tdc
|
|
21
13
|
end
|
22
14
|
|
23
15
|
def generate
|
24
|
-
configure_instance_definition(singular_instance_definition.merge(
|
16
|
+
configure_instance_definition(singular_instance_definition.merge(additional_definitions))
|
25
17
|
|
26
18
|
run_resolvers_and_generate_instance
|
27
19
|
end
|
28
20
|
|
29
21
|
private
|
30
22
|
|
23
|
+
def additional_definitions
|
24
|
+
@additional_definitions || {}
|
25
|
+
end
|
26
|
+
|
31
27
|
def singular_instance_definition
|
32
28
|
all_instance_definitions = instance_definitions
|
33
29
|
|
34
30
|
if all_instance_definitions.many?
|
35
|
-
raise Tdc::FatalError, "
|
31
|
+
raise Tdc::FatalError, "A singular generator only generates a single model instance"
|
36
32
|
end
|
37
33
|
|
38
34
|
# Delete the tag so that the models do not need to filter it out.
|
@@ -5,9 +5,7 @@ module Tdc
|
|
5
5
|
#
|
6
6
|
# See also SingularGenerator.
|
7
7
|
#
|
8
|
-
class StandardGenerator < Tdc::Generators::
|
9
|
-
include Tdc::Generators::InstanceDefinitionConfigurable
|
10
|
-
|
8
|
+
class StandardGenerator < Tdc::Generators::ConfigurableGenerator
|
11
9
|
def generate
|
12
10
|
CatalogEntries.new.tap do |catalog_entries|
|
13
11
|
instance_definitions.each do |instance_definition|
|
data/lib/tdc/version.rb
CHANGED
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.
|
4
|
+
version: 0.3.0
|
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-
|
11
|
+
date: 2020-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -113,6 +113,7 @@ executables: []
|
|
113
113
|
extensions: []
|
114
114
|
extra_rdoc_files: []
|
115
115
|
files:
|
116
|
+
- ".editorconfig"
|
116
117
|
- ".gitignore"
|
117
118
|
- ".rspec"
|
118
119
|
- ".rubocop.yml"
|
@@ -127,13 +128,16 @@ files:
|
|
127
128
|
- lib/tdc.rb
|
128
129
|
- lib/tdc/data_definition.rb
|
129
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
|
130
134
|
- lib/tdc/fatal_error.rb
|
131
135
|
- lib/tdc/generators.rb
|
132
136
|
- lib/tdc/generators/catalog_entries.rb
|
137
|
+
- lib/tdc/generators/configurable_generator.rb
|
133
138
|
- lib/tdc/generators/definition_resolvable.rb
|
134
139
|
- lib/tdc/generators/definition_sourcable.rb
|
135
140
|
- lib/tdc/generators/generator_base.rb
|
136
|
-
- lib/tdc/generators/instance_definition_configurable.rb
|
137
141
|
- lib/tdc/generators/singular_generator.rb
|
138
142
|
- lib/tdc/generators/standard_generator.rb
|
139
143
|
- lib/tdc/in_memory_data_definition.rb
|
@@ -163,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
167
|
- !ruby/object:Gem::Version
|
164
168
|
version: '0'
|
165
169
|
requirements: []
|
166
|
-
rubygems_version: 3.1.
|
170
|
+
rubygems_version: 3.1.4
|
167
171
|
signing_key:
|
168
172
|
specification_version: 4
|
169
173
|
summary: A simple framework for creating a Test Data Catalog
|