tdc 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +109 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +7 -0
- data/README.md +2 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/tdc.rb +32 -0
- data/lib/tdc/decorator_error.rb +3 -0
- data/lib/tdc/generators.rb +7 -0
- data/lib/tdc/generators/catalog_entries.rb +13 -0
- data/lib/tdc/generators/definition_resolvable.rb +62 -0
- data/lib/tdc/generators/definition_sourcable.rb +52 -0
- data/lib/tdc/generators/generator_base.rb +23 -0
- data/lib/tdc/generators/instance_definition_configurable.rb +60 -0
- data/lib/tdc/generators/singular_generator.rb +43 -0
- data/lib/tdc/generators/standard_generator.rb +28 -0
- data/lib/tdc/in_memory_data_definition.rb +24 -0
- data/lib/tdc/missing_hook_override_error.rb +7 -0
- data/lib/tdc/missing_path_elements_error.rb +3 -0
- data/lib/tdc/missing_test_data_definition_error.rb +3 -0
- data/lib/tdc/non_singular_instance_error.rb +3 -0
- data/lib/tdc/test_data_definition_reader.rb +57 -0
- data/lib/tdc/unresolvable_tag_error.rb +3 -0
- data/lib/tdc/version.rb +3 -0
- data/lib/tdc/with_indifferent_access_decorator.rb +17 -0
- data/lib/tdc/yaml_load_error.rb +3 -0
- data/tdc.gemspec +37 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 523892b0a0a870a9b4c5a6abe2b7e0cac37b8dfb51249e50da32fcac29c3e6f6
|
4
|
+
data.tar.gz: 616521e4890e99edf594c8b6778b2f4ee7680e713077ba4cf08811b91d4adf26
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e6c1bf80620c67f96f89234a7b578c3a97d42b64a732c1048d489902206f9caa859c998c684f10ac38b87ac67a1cfe11340438708aa391c524381470737265a3
|
7
|
+
data.tar.gz: d1df65063610d080e53cc57f61b64bca1f48111fb99240702547f609c5f8b446b698de6d816b0f4d4e64d7c9813daad466567ee47df759e9fda497f97a8aa6a4
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
TargetRubyVersion: 2.5
|
6
|
+
|
7
|
+
Exclude:
|
8
|
+
- 'bin/**/*'
|
9
|
+
|
10
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
11
|
+
Enabled: true
|
12
|
+
|
13
|
+
# Rubocop and I cannot agree.
|
14
|
+
Layout/MultilineMethodCallBraceLayout:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Layout/SpaceAroundMethodCallOperator:
|
18
|
+
Enabled: true
|
19
|
+
|
20
|
+
Lint/RaiseException:
|
21
|
+
Enabled: true
|
22
|
+
|
23
|
+
Lint/StructNewOverride:
|
24
|
+
Enabled: true
|
25
|
+
|
26
|
+
Metrics/BlockLength:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Naming/MemoizedInstanceVariableName:
|
30
|
+
EnforcedStyleForLeadingUnderscores: required
|
31
|
+
|
32
|
+
RSpec/AnyInstance:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
RSpec/ExampleLength:
|
36
|
+
Max: 15
|
37
|
+
|
38
|
+
Metrics/LineLength:
|
39
|
+
Max: 120
|
40
|
+
|
41
|
+
RSpec/DescribeClass:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
RSpec/DescribedClass:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
RSpec/NotToNot:
|
48
|
+
EnforcedStyle: to_not
|
49
|
+
|
50
|
+
RSpec/LeadingSubject:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
RSpec/MessageSpies:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
RSpec/MultipleExpectations:
|
57
|
+
Max: 3
|
58
|
+
|
59
|
+
RSpec/SubjectStub:
|
60
|
+
Enabled: false
|
61
|
+
|
62
|
+
Style/BlockDelimiters:
|
63
|
+
Enabled: true
|
64
|
+
EnforcedStyle: line_count_based
|
65
|
+
BracesRequiredMethods:
|
66
|
+
- 'let'
|
67
|
+
|
68
|
+
Style/Documentation:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
Style/ExponentialNotation:
|
72
|
+
Enabled: true
|
73
|
+
|
74
|
+
# We can ignore this small performance improvement.
|
75
|
+
Style/FrozenStringLiteralComment:
|
76
|
+
Enabled: false
|
77
|
+
|
78
|
+
Style/HashEachMethods:
|
79
|
+
Enabled: true
|
80
|
+
|
81
|
+
Style/HashTransformKeys:
|
82
|
+
Enabled: true
|
83
|
+
|
84
|
+
Style/HashTransformValues:
|
85
|
+
Enabled: true
|
86
|
+
|
87
|
+
# We like to use the hash rocket in rake files.
|
88
|
+
Style/HashSyntax:
|
89
|
+
Exclude:
|
90
|
+
- 'Rakefile'
|
91
|
+
|
92
|
+
# No need to mention StandardError.
|
93
|
+
Style/RescueStandardError:
|
94
|
+
EnforcedStyle: implicit
|
95
|
+
|
96
|
+
Style/SlicingWithRange:
|
97
|
+
Enabled: false
|
98
|
+
|
99
|
+
# We'll just use double quotes everywhere.
|
100
|
+
Style/StringLiterals:
|
101
|
+
EnforcedStyle: double_quotes
|
102
|
+
|
103
|
+
# I prefer not to use %i or %I for an array of symbols.
|
104
|
+
Style/SymbolArray:
|
105
|
+
Enabled: false
|
106
|
+
|
107
|
+
# We are not going to optimize by freezing strings.
|
108
|
+
Style/MutableConstant:
|
109
|
+
Enabled: false
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.6
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [Unreleased]
|
8
|
+
|
9
|
+
## [0.1.2] - 2020-05-18
|
10
|
+
|
11
|
+
- Complete the extraction from PackManager
|
12
|
+
|
13
|
+
## [0.1.1] - 2020-05-18
|
14
|
+
|
15
|
+
#### New Features
|
16
|
+
|
17
|
+
- Avoid all PackManager dependencies
|
18
|
+
|
19
|
+
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "tdc"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/tdc.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
require "active_support/core_ext/hash/indifferent_access"
|
5
|
+
|
6
|
+
require "tdc/in_memory_data_definition"
|
7
|
+
require "tdc/test_data_definition_reader"
|
8
|
+
require "tdc/version"
|
9
|
+
require "tdc/with_indifferent_access_decorator"
|
10
|
+
|
11
|
+
require "tdc/generators"
|
12
|
+
require "tdc/generators/catalog_entries"
|
13
|
+
require "tdc/generators/definition_resolvable"
|
14
|
+
require "tdc/generators/definition_sourcable"
|
15
|
+
require "tdc/generators/generator_base"
|
16
|
+
require "tdc/generators/instance_definition_configurable"
|
17
|
+
require "tdc/generators/singular_generator"
|
18
|
+
require "tdc/generators/standard_generator"
|
19
|
+
|
20
|
+
require "tdc/decorator_error"
|
21
|
+
require "tdc/missing_hook_override_error"
|
22
|
+
require "tdc/missing_path_elements_error"
|
23
|
+
require "tdc/missing_test_data_definition_error"
|
24
|
+
require "tdc/non_singular_instance_error"
|
25
|
+
require "tdc/unresolvable_tag_error"
|
26
|
+
require "tdc/yaml_load_error"
|
27
|
+
|
28
|
+
#
|
29
|
+
# A framework for building a Test Data Catalog
|
30
|
+
#
|
31
|
+
module Tdc
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
3
|
+
#
|
4
|
+
# Knows how to contain arbitrary collections of model objects. As model instances are created
|
5
|
+
# by generators, the model instances are added to the current catalog as catalog entries.
|
6
|
+
#
|
7
|
+
class CatalogEntries < OpenStruct
|
8
|
+
def add_catalog_entry(tag, entry)
|
9
|
+
send("#{tag}=", entry)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
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.
|
6
|
+
#
|
7
|
+
# The resolve_tag class macro is provided for generators to define tag resolution.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# Suppose a particular instance definition contained { subcomponent: sc_snackers_minis }
|
12
|
+
# then a generator could resolve the subcomponent by defining:
|
13
|
+
#
|
14
|
+
# resolve_tag key: :subcomponent, source: "item_master.items"
|
15
|
+
#
|
16
|
+
module DefinitionResolvable
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
included do
|
20
|
+
class_attribute :_tag_resolvers, instance_writer: false
|
21
|
+
self._tag_resolvers = []
|
22
|
+
end
|
23
|
+
|
24
|
+
class_methods do
|
25
|
+
def resolve_tag(key:, source:)
|
26
|
+
_tag_resolvers << [key, source]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_tag_resolvers(instance_definition)
|
31
|
+
_tag_resolvers.each { |key, source| _resolve_tag_reference(instance_definition, key, source) }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
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__)
|
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::UnresolvableTagError, message
|
55
|
+
end
|
56
|
+
|
57
|
+
# Replace the tag value with the sourced object.
|
58
|
+
instance_definition[key] = sourced_object
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
3
|
+
#
|
4
|
+
# Creates ghost methods for use in generators.
|
5
|
+
#
|
6
|
+
# All ghost methods are named 'key'_definition where 'key' is a key into the instance_definition hash.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# If an instance definition had "line" and "replenishment_parameters" keys then the following
|
11
|
+
# ghost methods could be used to refer to the value associated with those keys:
|
12
|
+
#
|
13
|
+
# line_definition
|
14
|
+
# replenishment_parameters_definition
|
15
|
+
#
|
16
|
+
module DefinitionSourcable
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
class_methods do
|
20
|
+
def source_definition_from(definition)
|
21
|
+
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
22
|
+
def definition_source
|
23
|
+
@definition_source ||= #{definition}
|
24
|
+
end
|
25
|
+
RUBY
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def configure_definition_source(definition)
|
30
|
+
@definition_source = definition
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def method_missing(method, *args)
|
36
|
+
key = transform_method_to_definition_source_key(method)
|
37
|
+
|
38
|
+
definition_source.key?(key) ? definition_source.fetch(key) : super
|
39
|
+
end
|
40
|
+
|
41
|
+
def respond_to_missing?(method, include_all = false)
|
42
|
+
key = transform_method_to_definition_source_key(method)
|
43
|
+
|
44
|
+
definition_source.key?(key) ? true : super
|
45
|
+
end
|
46
|
+
|
47
|
+
def transform_method_to_definition_source_key(method)
|
48
|
+
method.to_s.gsub(/_definition$/, "")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
3
|
+
#
|
4
|
+
# Abstract base class for all Test Data Catalog generators.
|
5
|
+
#
|
6
|
+
class GeneratorBase
|
7
|
+
attr_reader :data_definition, :current_catalog
|
8
|
+
|
9
|
+
def initialize(data_definition, current_catalog)
|
10
|
+
@data_definition = data_definition
|
11
|
+
@current_catalog = current_catalog
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate
|
15
|
+
raise Tdc::MissingHookOverrideError
|
16
|
+
end
|
17
|
+
|
18
|
+
def instance_definitions
|
19
|
+
raise Tdc::MissingHookOverrideError
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
3
|
+
#
|
4
|
+
# Knows how to provide a configurable instance definition.
|
5
|
+
#
|
6
|
+
# Shared implementation between the StandardGenerator and the SingularGenerator abstract classes.
|
7
|
+
#
|
8
|
+
module InstanceDefinitionConfigurable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include Tdc::Generators::DefinitionSourcable
|
13
|
+
|
14
|
+
attr_reader :instance_definition
|
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
|
25
|
+
|
26
|
+
def run_resolvers_and_generate_instance
|
27
|
+
run_atx_resolvers(instance_definition)
|
28
|
+
run_tag_resolvers(instance_definition)
|
29
|
+
|
30
|
+
generate_instance
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Hook method: subclasses are expected to define how to generate a model instance.
|
35
|
+
#
|
36
|
+
def generate_instance
|
37
|
+
raise Tdc::MissingHookOverrideError
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Hook method: subclasses may include the DefinitionResolvable concern to override.
|
42
|
+
#
|
43
|
+
def run_tag_resolvers(_instance_definition)
|
44
|
+
# Do nothing
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_atx_resolvers(instance_definition)
|
48
|
+
atx_definitions = instance_definition.select { |k, _v| /_atx$/ =~ k }
|
49
|
+
|
50
|
+
atx_definitions.each do |k, v|
|
51
|
+
# Remove the original _atx attribute.
|
52
|
+
instance_definition.delete(k)
|
53
|
+
|
54
|
+
# Add a standard _at attribute.
|
55
|
+
instance_definition[k.delete_suffix("x")] = eval(v) # rubocop:disable Security/Eval
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
3
|
+
#
|
4
|
+
# Abstract class for defining generators that define a single model instance.
|
5
|
+
#
|
6
|
+
# See also StandardGenerator.
|
7
|
+
#
|
8
|
+
class SingularGenerator < Tdc::Generators::GeneratorBase
|
9
|
+
include Tdc::Generators::InstanceDefinitionConfigurable
|
10
|
+
|
11
|
+
def initialize(data_definition, current_catalog)
|
12
|
+
super
|
13
|
+
|
14
|
+
@additional_definitions = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_definition(additional_definitions)
|
18
|
+
@additional_definitions = additional_definitions.stringify_keys.reject { |_, v| v == :missing_definition }
|
19
|
+
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate
|
24
|
+
configure_instance_definition(singular_instance_definition.merge(@additional_definitions))
|
25
|
+
|
26
|
+
run_resolvers_and_generate_instance
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def singular_instance_definition
|
32
|
+
all_instance_definitions = instance_definitions
|
33
|
+
|
34
|
+
if all_instance_definitions.many?
|
35
|
+
raise Tdc::NonSingularInstanceError, "For the moment we only generate a single model instance"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Delete the tag so that the models do not need to filter it out.
|
39
|
+
all_instance_definitions.first.except("tag")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Tdc
|
2
|
+
module Generators
|
3
|
+
#
|
4
|
+
# Abstract class for defining generators that define a collection of model instances.
|
5
|
+
#
|
6
|
+
# See also SingularGenerator.
|
7
|
+
#
|
8
|
+
class StandardGenerator < Tdc::Generators::GeneratorBase
|
9
|
+
include Tdc::Generators::InstanceDefinitionConfigurable
|
10
|
+
|
11
|
+
def generate
|
12
|
+
CatalogEntries.new.tap do |catalog_entries|
|
13
|
+
instance_definitions.each do |instance_definition|
|
14
|
+
configure_instance_definition(instance_definition)
|
15
|
+
|
16
|
+
# Delete the tag so that the models do not need to filter it out.
|
17
|
+
tag = instance_definition.delete("tag")
|
18
|
+
|
19
|
+
generated = run_resolvers_and_generate_instance
|
20
|
+
|
21
|
+
# Add generated instance to the catalog entries whenever a tag provided.
|
22
|
+
catalog_entries.add_catalog_entry(tag, generated) if tag
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Tdc
|
2
|
+
#
|
3
|
+
# Knows how to read test data definitions from an in-memory representation.
|
4
|
+
#
|
5
|
+
class InMemoryDataDefinition
|
6
|
+
def initialize(path_elements_data = {})
|
7
|
+
@store = path_elements_data
|
8
|
+
end
|
9
|
+
|
10
|
+
def store(path_elements, data)
|
11
|
+
@store[path_elements] = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def read(*path_elements)
|
15
|
+
@store.fetch(path_elements) do
|
16
|
+
raise MissingPathElementsError, "The path did not have any data associated with it: #{path_elements.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def with_indifferent_access
|
21
|
+
self.extend(Tdc::WithIndifferentAccessDecorator) # rubocop:disable Style/RedundantSelf
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Tdc
|
2
|
+
#
|
3
|
+
# Knows how to read test data definitions from YAML files.
|
4
|
+
#
|
5
|
+
class TestDataDefinitionReader
|
6
|
+
EMPTY_DEFINITIONS = []
|
7
|
+
|
8
|
+
def initialize(catalog_root_directory)
|
9
|
+
@catalog_root_directory = catalog_root_directory
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(*path_elements)
|
13
|
+
data_definition_from(definitions_file(path_elements))
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_indifferent_access
|
17
|
+
self.extend(Tdc::WithIndifferentAccessDecorator) # rubocop:disable Style/RedundantSelf
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def definitions_file(path_elements)
|
23
|
+
fully_qualified_path_elements = [@catalog_root_directory].concat(path_elements.map(&:to_s))
|
24
|
+
|
25
|
+
fully_qualified_path_elements.last.concat(".yml")
|
26
|
+
|
27
|
+
File.join(*fully_qualified_path_elements)
|
28
|
+
end
|
29
|
+
|
30
|
+
def data_definition_from(definitions_file)
|
31
|
+
if File.exist?(definitions_file)
|
32
|
+
load_yaml(definitions_file) || EMPTY_DEFINITIONS
|
33
|
+
else
|
34
|
+
missing_data_definition(definitions_file)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_yaml(definitions_file)
|
39
|
+
YAML.load(expand_erb(definitions_file)) # rubocop:disable Security/YAMLLoad
|
40
|
+
rescue => e
|
41
|
+
raise Tdc::YamlLoadError, <<~MSG
|
42
|
+
Unable to load YAML from #{definitions_file}
|
43
|
+
Cause: #{e.message}"
|
44
|
+
MSG
|
45
|
+
end
|
46
|
+
|
47
|
+
def expand_erb(definitions_file)
|
48
|
+
ERB.new(File.read(definitions_file)).result
|
49
|
+
end
|
50
|
+
|
51
|
+
def missing_data_definition(definitions_file)
|
52
|
+
return EMPTY_DEFINITIONS if ENV.key?("TDC_IGNORE_MISSING_TEST_DATA_DEFINITION_ERROR")
|
53
|
+
|
54
|
+
raise MissingTestDataDefinitionError, definitions_file
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/tdc/version.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Tdc
|
2
|
+
#
|
3
|
+
# Knows how to transform the result of calling the TestDefinitionReader#read method from an Array
|
4
|
+
# of Hash instances into an Array of ActiveSupport::HashWithIndifferentAccess instances.
|
5
|
+
#
|
6
|
+
module WithIndifferentAccessDecorator
|
7
|
+
def read(*path_elements)
|
8
|
+
definitions = super
|
9
|
+
|
10
|
+
raise DecoratorError, "Use 'with_indifferent_access' only for an Array" unless definitions.is_a?(Array)
|
11
|
+
|
12
|
+
definitions.map do |definition|
|
13
|
+
definition.is_a?(Hash) ? ActiveSupport::HashWithIndifferentAccess.new(definition) : definition
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/tdc.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "lib/tdc/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "tdc"
|
5
|
+
spec.version = Tdc::VERSION
|
6
|
+
spec.authors = ["Alistair McKinnell"]
|
7
|
+
spec.email = ["alistairm@nulogy.com"]
|
8
|
+
|
9
|
+
spec.summary = "A simple framework for creating a Test Data Catalog"
|
10
|
+
spec.homepage = "https://github.com/nulogy/tdc"
|
11
|
+
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
13
|
+
|
14
|
+
spec.metadata = {
|
15
|
+
"homepage_uri" => "https://github.com/nulogy/tdc",
|
16
|
+
"changelog_uri" => "https://github.com/nulogy/tdc/blob/master/CHANGELOG.md",
|
17
|
+
"source_code_uri" => "https://github.com/nulogy/tdc",
|
18
|
+
"bug_tracker_uri" => "https://github.com/nulogy/tdc/issues"
|
19
|
+
}
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_runtime_dependency "activesupport", "~> 5.2.4"
|
31
|
+
|
32
|
+
spec.add_development_dependency "rake", ">= 12.1", "< 13.1"
|
33
|
+
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"
|
36
|
+
spec.add_development_dependency "simplecov", "~> 0.17"
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tdc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alistair McKinnell
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.2.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.2.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '12.1'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '13.1'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '12.1'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '13.1'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.9'
|
54
|
+
- - "<"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '4.0'
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '3.9'
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '4.0'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rubocop
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.82'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0.82'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rubocop-rspec
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.38'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '1.38'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: simplecov
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.17'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0.17'
|
109
|
+
description:
|
110
|
+
email:
|
111
|
+
- alistairm@nulogy.com
|
112
|
+
executables: []
|
113
|
+
extensions: []
|
114
|
+
extra_rdoc_files: []
|
115
|
+
files:
|
116
|
+
- ".gitignore"
|
117
|
+
- ".rspec"
|
118
|
+
- ".rubocop.yml"
|
119
|
+
- ".ruby-version"
|
120
|
+
- CHANGELOG.md
|
121
|
+
- Gemfile
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/console
|
125
|
+
- bin/setup
|
126
|
+
- lib/tdc.rb
|
127
|
+
- lib/tdc/decorator_error.rb
|
128
|
+
- lib/tdc/generators.rb
|
129
|
+
- lib/tdc/generators/catalog_entries.rb
|
130
|
+
- lib/tdc/generators/definition_resolvable.rb
|
131
|
+
- lib/tdc/generators/definition_sourcable.rb
|
132
|
+
- lib/tdc/generators/generator_base.rb
|
133
|
+
- lib/tdc/generators/instance_definition_configurable.rb
|
134
|
+
- lib/tdc/generators/singular_generator.rb
|
135
|
+
- lib/tdc/generators/standard_generator.rb
|
136
|
+
- lib/tdc/in_memory_data_definition.rb
|
137
|
+
- lib/tdc/missing_hook_override_error.rb
|
138
|
+
- lib/tdc/missing_path_elements_error.rb
|
139
|
+
- lib/tdc/missing_test_data_definition_error.rb
|
140
|
+
- lib/tdc/non_singular_instance_error.rb
|
141
|
+
- lib/tdc/test_data_definition_reader.rb
|
142
|
+
- lib/tdc/unresolvable_tag_error.rb
|
143
|
+
- lib/tdc/version.rb
|
144
|
+
- lib/tdc/with_indifferent_access_decorator.rb
|
145
|
+
- lib/tdc/yaml_load_error.rb
|
146
|
+
- tdc.gemspec
|
147
|
+
homepage: https://github.com/nulogy/tdc
|
148
|
+
licenses: []
|
149
|
+
metadata:
|
150
|
+
homepage_uri: https://github.com/nulogy/tdc
|
151
|
+
changelog_uri: https://github.com/nulogy/tdc/blob/master/CHANGELOG.md
|
152
|
+
source_code_uri: https://github.com/nulogy/tdc
|
153
|
+
bug_tracker_uri: https://github.com/nulogy/tdc/issues
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 2.5.0
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubygems_version: 3.1.3
|
170
|
+
signing_key:
|
171
|
+
specification_version: 4
|
172
|
+
summary: A simple framework for creating a Test Data Catalog
|
173
|
+
test_files: []
|