tdc 0.1.2 → 0.2.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: 523892b0a0a870a9b4c5a6abe2b7e0cac37b8dfb51249e50da32fcac29c3e6f6
4
- data.tar.gz: 616521e4890e99edf594c8b6778b2f4ee7680e713077ba4cf08811b91d4adf26
3
+ metadata.gz: ea6a4c15535d29f9f7ab47c6ec12f4c20cc59f588543b19869324f5901097c24
4
+ data.tar.gz: c5d57e1578f9550a725f20f6ef396bd2bb3d5791773929afd9c6605d8686f2b3
5
5
  SHA512:
6
- metadata.gz: e6c1bf80620c67f96f89234a7b578c3a97d42b64a732c1048d489902206f9caa859c998c684f10ac38b87ac67a1cfe11340438708aa391c524381470737265a3
7
- data.tar.gz: d1df65063610d080e53cc57f61b64bca1f48111fb99240702547f609c5f8b446b698de6d816b0f4d4e64d7c9813daad466567ee47df759e9fda497f97a8aa6a4
6
+ metadata.gz: 7829e509a7c5ef3c7db2b947ee109af96a442c662ccb15e0f5ab50a04e70f91eef039944b65a4b6dfcf9eae232e249146062067c79a2ca955cff2027b0aee649
7
+ data.tar.gz: 20eefb49010d15905073f5f823bdc171cc428e5c2ef1217d61ec17210d4426f4dd7de4312c56167cd4b67b37d43c2049b3cfc90b0a8b51f4577eb5c884b94841
@@ -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
@@ -1,3 +1,3 @@
1
1
  --format documentation
2
2
  --color
3
- --require spec_helper
3
+ --require tdc_spec_helper
@@ -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
 
@@ -6,6 +6,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.4] - 2020-07-19
10
+
11
+ - Improve Tdc::MissingOverrideError diagnostics
12
+
13
+ ## [0.2.3] - 2020-05-21
14
+
15
+ - Update the diagram in the README
16
+
17
+ ## [0.2.2] - 2020-05-20
18
+
19
+ - Adding specs
20
+
21
+ ## [0.2.1] - 2020-05-19
22
+
23
+ - Adding specs
24
+
25
+ ## [0.2.0] - 2020-05-19
26
+
27
+ #### Breaking Changes
28
+
29
+ - Renamed TestDataDefinitionReader to DataDefinitionFileReader
30
+ - All errors inherit from Tdc::FatalError
31
+
9
32
  ## [0.1.2] - 2020-05-18
10
33
 
11
34
  - Complete the extraction from PackManager
data/README.md CHANGED
@@ -1,2 +1,13 @@
1
- # TDC: Test Data Catalog
1
+ # TDC: Test Data Catalog Generation
2
2
 
3
+ ![TDC Framelet](/images/Tdc.png)
4
+
5
+ **Extension Points**
6
+
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
+ 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
+
11
+ **Data Definition DSL**
12
+
13
+ ```DefinitionResolvable``` and ```DefinitionSourcable``` provide a DSL that you may use in your generators to work more easily with a ```DataDefinition```.
Binary file
data/lib/tdc.rb CHANGED
@@ -1,30 +1,38 @@
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/hash/indifferent_access"
6
+ require "active_support/core_ext"
5
7
 
6
- require "tdc/in_memory_data_definition"
7
- require "tdc/test_data_definition_reader"
8
8
  require "tdc/version"
9
+
10
+ # Errors
11
+ require "tdc/fatal_error"
12
+ require "tdc/missing_override_error"
13
+
14
+ # Data Definition Hierarchy
15
+ require "tdc/data_definition"
16
+ require "tdc/data_definition_file_reader"
17
+ require "tdc/in_memory_data_definition"
9
18
  require "tdc/with_indifferent_access_decorator"
10
19
 
20
+ # Generators
11
21
  require "tdc/generators"
22
+
23
+ # Current Catalog
12
24
  require "tdc/generators/catalog_entries"
25
+
26
+ # Concerns
13
27
  require "tdc/generators/definition_resolvable"
14
28
  require "tdc/generators/definition_sourcable"
29
+
30
+ # Generator Hierarchy
15
31
  require "tdc/generators/generator_base"
16
- require "tdc/generators/instance_definition_configurable"
32
+ require "tdc/generators/configurable_generator"
17
33
  require "tdc/generators/singular_generator"
18
34
  require "tdc/generators/standard_generator"
19
35
 
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
36
  #
29
37
  # A framework for building a Test Data Catalog
30
38
  #
@@ -0,0 +1,14 @@
1
+ module Tdc
2
+ #
3
+ # Knows how to read data definitions from the specified path elements.
4
+ #
5
+ class DataDefinition
6
+ def read(*_path_elements)
7
+ raise MissingOverrideError, "Implement the 'read' method"
8
+ end
9
+
10
+ def with_indifferent_access
11
+ self.extend(Tdc::WithIndifferentAccessDecorator) # rubocop:disable Style/RedundantSelf
12
+ end
13
+ end
14
+ end
@@ -1,8 +1,8 @@
1
1
  module Tdc
2
2
  #
3
- # Knows how to read test data definitions from YAML files.
3
+ # Knows how to read data definitions from YAML files.
4
4
  #
5
- class TestDataDefinitionReader
5
+ class DataDefinitionFileReader < Tdc::DataDefinition
6
6
  EMPTY_DEFINITIONS = []
7
7
 
8
8
  def initialize(catalog_root_directory)
@@ -13,10 +13,6 @@ module Tdc
13
13
  data_definition_from(definitions_file(path_elements))
14
14
  end
15
15
 
16
- def with_indifferent_access
17
- self.extend(Tdc::WithIndifferentAccessDecorator) # rubocop:disable Style/RedundantSelf
18
- end
19
-
20
16
  private
21
17
 
22
18
  def definitions_file(path_elements)
@@ -38,7 +34,7 @@ module Tdc
38
34
  def load_yaml(definitions_file)
39
35
  YAML.load(expand_erb(definitions_file)) # rubocop:disable Security/YAMLLoad
40
36
  rescue => e
41
- raise Tdc::YamlLoadError, <<~MSG
37
+ raise Tdc::FatalError, <<~MSG
42
38
  Unable to load YAML from #{definitions_file}
43
39
  Cause: #{e.message}"
44
40
  MSG
@@ -51,7 +47,7 @@ module Tdc
51
47
  def missing_data_definition(definitions_file)
52
48
  return EMPTY_DEFINITIONS if ENV.key?("TDC_IGNORE_MISSING_TEST_DATA_DEFINITION_ERROR")
53
49
 
54
- raise MissingTestDataDefinitionError, definitions_file
50
+ raise Tdc::FatalError, "Missing test definitions file: '#{definitions_file}'"
55
51
  end
56
52
  end
57
53
  end
@@ -0,0 +1,7 @@
1
+ module Tdc
2
+ class FatalError < RuntimeError
3
+ def initialize(msg = nil)
4
+ super
5
+ end
6
+ end
7
+ end
@@ -5,23 +5,12 @@ module Tdc
5
5
  #
6
6
  # Shared implementation between the StandardGenerator and the SingularGenerator abstract classes.
7
7
  #
8
- module InstanceDefinitionConfigurable
9
- extend ActiveSupport::Concern
8
+ class ConfigurableGenerator < Tdc::Generators::GeneratorBase
9
+ include Tdc::Generators::DefinitionSourcable
10
10
 
11
- included do
12
- include Tdc::Generators::DefinitionSourcable
11
+ attr_reader :instance_definition
13
12
 
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
13
+ source_definition_from :instance_definition
25
14
 
26
15
  def run_resolvers_and_generate_instance
27
16
  run_atx_resolvers(instance_definition)
@@ -34,7 +23,7 @@ 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::MissingHookOverrideError
26
+ raise Tdc::MissingOverrideError, "Implement the 'generate_instance' method"
38
27
  end
39
28
 
40
29
  #
@@ -44,6 +33,14 @@ module Tdc
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
 
@@ -51,7 +51,7 @@ module Tdc
51
51
  unless sourced_object
52
52
  message = "Could not find a tag reference for '#{key}' in the catalog entries provided."
53
53
 
54
- raise Tdc::UnresolvableTagError, message
54
+ raise Tdc::FatalError, message
55
55
  end
56
56
 
57
57
  # Replace the tag value with the sourced object.
@@ -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.key?(key) ? definition_source.fetch(key) : super
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.key?(key) ? true : super
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::MissingHookOverrideError
15
+ raise Tdc::MissingOverrideError, "Implement the 'generate' method"
16
16
  end
17
17
 
18
18
  def instance_definitions
19
- raise Tdc::MissingHookOverrideError
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::GeneratorBase
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(@additional_definitions))
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::NonSingularInstanceError, "For the moment we only generate a single model instance"
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::GeneratorBase
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|
@@ -1,24 +1,20 @@
1
1
  module Tdc
2
2
  #
3
- # Knows how to read test data definitions from an in-memory representation.
3
+ # Knows how to read data definitions from an in-memory representation.
4
4
  #
5
- class InMemoryDataDefinition
5
+ class InMemoryDataDefinition < Tdc::DataDefinition
6
6
  def initialize(path_elements_data = {})
7
7
  @store = path_elements_data
8
8
  end
9
9
 
10
- def store(path_elements, data)
11
- @store[path_elements] = data
12
- end
13
-
14
10
  def read(*path_elements)
15
11
  @store.fetch(path_elements) do
16
- raise MissingPathElementsError, "The path did not have any data associated with it: #{path_elements.inspect}"
12
+ raise Tdc::FatalError, "The path did not have any data associated with it: #{path_elements.inspect}"
17
13
  end
18
14
  end
19
15
 
20
- def with_indifferent_access
21
- self.extend(Tdc::WithIndifferentAccessDecorator) # rubocop:disable Style/RedundantSelf
16
+ def store(path_elements, data)
17
+ @store[path_elements] = data
22
18
  end
23
19
  end
24
20
  end
@@ -0,0 +1,3 @@
1
+ module Tdc
2
+ MissingOverrideError = Class.new(Tdc::FatalError)
3
+ end
@@ -1,3 +1,3 @@
1
1
  module Tdc
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.4"
3
3
  end
@@ -7,7 +7,7 @@ module Tdc
7
7
  def read(*path_elements)
8
8
  definitions = super
9
9
 
10
- raise DecoratorError, "Use 'with_indifferent_access' only for an Array" unless definitions.is_a?(Array)
10
+ raise Tdc::FatalError, "Use 'with_indifferent_access' only for an Array" unless definitions.is_a?(Array)
11
11
 
12
12
  definitions.map do |definition|
13
13
  definition.is_a?(Hash) ? ActiveSupport::HashWithIndifferentAccess.new(definition) : definition
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.1.2
4
+ version: 0.2.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-05-19 00:00:00.000000000 Z
11
+ date: 2020-07-19 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"
@@ -123,26 +124,23 @@ files:
123
124
  - Rakefile
124
125
  - bin/console
125
126
  - bin/setup
127
+ - images/Tdc.png
126
128
  - lib/tdc.rb
127
- - lib/tdc/decorator_error.rb
129
+ - lib/tdc/data_definition.rb
130
+ - lib/tdc/data_definition_file_reader.rb
131
+ - lib/tdc/fatal_error.rb
128
132
  - lib/tdc/generators.rb
129
133
  - lib/tdc/generators/catalog_entries.rb
134
+ - lib/tdc/generators/configurable_generator.rb
130
135
  - lib/tdc/generators/definition_resolvable.rb
131
136
  - lib/tdc/generators/definition_sourcable.rb
132
137
  - lib/tdc/generators/generator_base.rb
133
- - lib/tdc/generators/instance_definition_configurable.rb
134
138
  - lib/tdc/generators/singular_generator.rb
135
139
  - lib/tdc/generators/standard_generator.rb
136
140
  - 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
141
+ - lib/tdc/missing_override_error.rb
143
142
  - lib/tdc/version.rb
144
143
  - lib/tdc/with_indifferent_access_decorator.rb
145
- - lib/tdc/yaml_load_error.rb
146
144
  - tdc.gemspec
147
145
  homepage: https://github.com/nulogy/tdc
148
146
  licenses: []
@@ -166,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
164
  - !ruby/object:Gem::Version
167
165
  version: '0'
168
166
  requirements: []
169
- rubygems_version: 3.1.3
167
+ rubygems_version: 3.1.4
170
168
  signing_key:
171
169
  specification_version: 4
172
170
  summary: A simple framework for creating a Test Data Catalog
@@ -1,3 +0,0 @@
1
- module Tdc
2
- DecoratorError = Class.new(RuntimeError)
3
- end
@@ -1,7 +0,0 @@
1
- module Tdc
2
- class MissingHookOverrideError < RuntimeError
3
- def initialize
4
- super("Must be implemented")
5
- end
6
- end
7
- end
@@ -1,3 +0,0 @@
1
- module Tdc
2
- MissingPathElementsError = Class.new(RuntimeError)
3
- end
@@ -1,3 +0,0 @@
1
- module Tdc
2
- MissingTestDataDefinitionError = Class.new(RuntimeError)
3
- end
@@ -1,3 +0,0 @@
1
- module Tdc
2
- NonSingularInstanceError = Class.new(RuntimeError)
3
- end
@@ -1,3 +0,0 @@
1
- module Tdc
2
- UnresolvableTagError = Class.new(RuntimeError)
3
- end
@@ -1,3 +0,0 @@
1
- module Tdc
2
- YamlLoadError = Class.new(RuntimeError)
3
- end