simmer 1.0.0.pre.alpha.2
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 +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +25 -0
- data/.ruby-version +1 -0
- data/.travis.yml +25 -0
- data/CHANGELOG.md +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Guardfile +16 -0
- data/LICENSE +7 -0
- data/README.md +5 -0
- data/Rakefile +17 -0
- data/bin/console +18 -0
- data/bin/simmer +11 -0
- data/lib/simmer.rb +50 -0
- data/lib/simmer/configuration.rb +90 -0
- data/lib/simmer/core_ext/hash.rb +21 -0
- data/lib/simmer/externals.rb +12 -0
- data/lib/simmer/externals/aws_file_system.rb +81 -0
- data/lib/simmer/externals/mysql_database.rb +114 -0
- data/lib/simmer/externals/mysql_database/sql_fixture.rb +43 -0
- data/lib/simmer/externals/spoon_client.rb +77 -0
- data/lib/simmer/externals/spoon_client/mock.rb +39 -0
- data/lib/simmer/externals/spoon_client/result.rb +48 -0
- data/lib/simmer/judge.rb +38 -0
- data/lib/simmer/judge/result.rb +34 -0
- data/lib/simmer/runner.rb +125 -0
- data/lib/simmer/runner/result.rb +52 -0
- data/lib/simmer/session.rb +79 -0
- data/lib/simmer/session/reporter.rb +100 -0
- data/lib/simmer/session/result.rb +45 -0
- data/lib/simmer/specification.rb +34 -0
- data/lib/simmer/specification/act.rb +48 -0
- data/lib/simmer/specification/act/params.rb +55 -0
- data/lib/simmer/specification/assert.rb +27 -0
- data/lib/simmer/specification/assert/assertions.rb +27 -0
- data/lib/simmer/specification/assert/assertions/bad_output_assertion.rb +34 -0
- data/lib/simmer/specification/assert/assertions/bad_table_assertion.rb +38 -0
- data/lib/simmer/specification/assert/assertions/output.rb +37 -0
- data/lib/simmer/specification/assert/assertions/table.rb +47 -0
- data/lib/simmer/specification/stage.rb +28 -0
- data/lib/simmer/specification/stage/input_file.rb +33 -0
- data/lib/simmer/suite.rb +73 -0
- data/lib/simmer/util.rb +13 -0
- data/lib/simmer/util/evaluator.rb +32 -0
- data/lib/simmer/util/fixture.rb +32 -0
- data/lib/simmer/util/fixture_set.rb +41 -0
- data/lib/simmer/util/record.rb +54 -0
- data/lib/simmer/util/record_set.rb +51 -0
- data/lib/simmer/util/resolver.rb +28 -0
- data/lib/simmer/util/yaml_reader.rb +61 -0
- data/lib/simmer/version.rb +12 -0
- data/simmer.gemspec +38 -0
- data/spec/simmer/core_ext/hash_spec.rb +16 -0
- data/spec/spec_helper.rb +22 -0
- metadata +284 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'assertions/bad_output_assertion'
|
11
|
+
require_relative 'assertions/bad_table_assertion'
|
12
|
+
require_relative 'assertions/output'
|
13
|
+
require_relative 'assertions/table'
|
14
|
+
|
15
|
+
module Simmer
|
16
|
+
class Specification
|
17
|
+
class Assert
|
18
|
+
# Factory class for assertions.
|
19
|
+
class Assertions
|
20
|
+
acts_as_hashable_factory
|
21
|
+
|
22
|
+
register 'output', Output
|
23
|
+
register 'table', Table
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Specification
|
12
|
+
class Assert
|
13
|
+
class Assertions
|
14
|
+
# Describes when the output does not meet expectations.
|
15
|
+
class BadOutputAssertion
|
16
|
+
attr_reader :expected_value
|
17
|
+
|
18
|
+
def initialize(expected_value)
|
19
|
+
@expected_value = expected_value
|
20
|
+
|
21
|
+
freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
{
|
26
|
+
'type' => 'output',
|
27
|
+
'expected_value' => expected_value
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Specification
|
12
|
+
class Assert
|
13
|
+
class Assertions
|
14
|
+
# Describes when a database table does not meet expectations.
|
15
|
+
class BadTableAssertion
|
16
|
+
attr_reader :name, :expected_record_set, :actual_record_set
|
17
|
+
|
18
|
+
def initialize(name, expected_record_set, actual_record_set)
|
19
|
+
@name = name
|
20
|
+
@expected_record_set = expected_record_set
|
21
|
+
@actual_record_set = actual_record_set
|
22
|
+
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
{
|
28
|
+
'type' => 'table',
|
29
|
+
'name' => name,
|
30
|
+
'expected_record_set' => expected_record_set.to_h,
|
31
|
+
'actual_record_set' => actual_record_set.to_h
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'bad_output_assertion'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
class Specification
|
14
|
+
class Assert
|
15
|
+
class Assertions
|
16
|
+
# Describes an expected state of the output (log).
|
17
|
+
class Output
|
18
|
+
acts_as_hashable
|
19
|
+
|
20
|
+
attr_reader :value
|
21
|
+
|
22
|
+
def initialize(value:)
|
23
|
+
@value = value.to_s
|
24
|
+
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def assert(_database, output)
|
29
|
+
return nil if output.to_s.include?(value)
|
30
|
+
|
31
|
+
BadOutputAssertion.new(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'bad_table_assertion'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
class Specification
|
14
|
+
class Assert
|
15
|
+
class Assertions
|
16
|
+
# Describes an expected state of a database table.
|
17
|
+
class Table
|
18
|
+
acts_as_hashable
|
19
|
+
|
20
|
+
attr_reader :name, :record_set
|
21
|
+
|
22
|
+
def initialize(name:, records: [])
|
23
|
+
@name = name.to_s
|
24
|
+
@record_set = Util::RecordSet.new(records)
|
25
|
+
|
26
|
+
freeze
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert(database, _output)
|
30
|
+
actual_records = database.records(name, keys)
|
31
|
+
actual_record_set = Util::RecordSet.new(actual_records)
|
32
|
+
|
33
|
+
return nil if actual_record_set == record_set
|
34
|
+
|
35
|
+
BadTableAssertion.new(name, record_set, actual_record_set)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def keys
|
41
|
+
record_set.keys
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'stage/input_file'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
class Specification
|
14
|
+
# Describes the state necessary to exist before Spoon can be executed successfully.
|
15
|
+
class Stage
|
16
|
+
acts_as_hashable
|
17
|
+
|
18
|
+
attr_reader :files, :fixtures
|
19
|
+
|
20
|
+
def initialize(files: [], fixtures: [])
|
21
|
+
@files = InputFile.array(files)
|
22
|
+
@fixtures = Array(fixtures).map(&:to_s)
|
23
|
+
|
24
|
+
freeze
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Specification
|
12
|
+
class Stage
|
13
|
+
# Describes a file needing to be staged for a specification to execute properly.
|
14
|
+
# It understands where the file exists in the local repository and where to transfer it
|
15
|
+
# to.
|
16
|
+
class InputFile
|
17
|
+
acts_as_hashable
|
18
|
+
|
19
|
+
attr_reader :dest, :src
|
20
|
+
|
21
|
+
def initialize(dest:, src:)
|
22
|
+
raise ArgumentError, 'dest is required' if dest.to_s.empty?
|
23
|
+
raise ArgumentError, 'src is required' if src.to_s.empty?
|
24
|
+
|
25
|
+
@dest = dest.to_s
|
26
|
+
@src = src.to_s
|
27
|
+
|
28
|
+
freeze
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/simmer/suite.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'configuration'
|
11
|
+
require_relative 'externals'
|
12
|
+
require_relative 'runner'
|
13
|
+
require_relative 'session'
|
14
|
+
require_relative 'specification'
|
15
|
+
|
16
|
+
# Entrypoint to the library
|
17
|
+
module Simmer
|
18
|
+
# The main object entrypoint that brings the entire codebase together.
|
19
|
+
class Suite
|
20
|
+
attr_reader :configuration, :session
|
21
|
+
|
22
|
+
def initialize(config_path:, out:, results_dir:, simmer_dir:)
|
23
|
+
@configuration = Configuration.new(
|
24
|
+
config_path: config_path,
|
25
|
+
results_dir: results_dir,
|
26
|
+
simmer_dir: simmer_dir
|
27
|
+
)
|
28
|
+
|
29
|
+
runner = Runner.new(
|
30
|
+
database: database,
|
31
|
+
file_system: file_system,
|
32
|
+
out: out,
|
33
|
+
spoon_client: spoon_client
|
34
|
+
)
|
35
|
+
|
36
|
+
@session = Session.new(
|
37
|
+
config: configuration.config,
|
38
|
+
out: out,
|
39
|
+
results_dir: results_dir,
|
40
|
+
runner: runner
|
41
|
+
)
|
42
|
+
|
43
|
+
freeze
|
44
|
+
end
|
45
|
+
|
46
|
+
def run(path)
|
47
|
+
session.run(specifications(path))
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def specifications(path)
|
53
|
+
path = path.to_s.empty? ? configuration.tests_dir : path
|
54
|
+
|
55
|
+
Util::YamlReader.new.all(path).map do |file, config|
|
56
|
+
config = (config || {}).merge(path: file)
|
57
|
+
Specification.make(config)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def database
|
62
|
+
Externals::MysqlDatabase.new(configuration.database_config, configuration.fixture_set)
|
63
|
+
end
|
64
|
+
|
65
|
+
def file_system
|
66
|
+
Externals::AwsFileSystem.new(configuration.file_system_config, configuration.files_dir)
|
67
|
+
end
|
68
|
+
|
69
|
+
def spoon_client
|
70
|
+
Externals::SpoonClient.new(configuration.spoon_client_config, configuration.files_dir)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/simmer/util.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'util/evaluator'
|
11
|
+
require_relative 'util/fixture_set'
|
12
|
+
require_relative 'util/record_set'
|
13
|
+
require_relative 'util/yaml_reader'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'resolver'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
module Util
|
14
|
+
# Text template renderer. It knows how to take a string and object as an input and
|
15
|
+
# output a compiled string.
|
16
|
+
class Evaluator
|
17
|
+
def initialize
|
18
|
+
@resolver = Objectable.resolver
|
19
|
+
|
20
|
+
freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def evaluate(string, input = {})
|
24
|
+
Stringento.evaluate(string, input, resolver: Resolver.new)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :resolver
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
module Util
|
12
|
+
# A fixture is a database record that can be inserted in the Stage phase of a specification
|
13
|
+
# execution.
|
14
|
+
class Fixture
|
15
|
+
acts_as_hashable
|
16
|
+
|
17
|
+
attr_reader :fields,
|
18
|
+
:name,
|
19
|
+
:table
|
20
|
+
|
21
|
+
def initialize(fields: {}, name:, table:)
|
22
|
+
@fields = fields || {}
|
23
|
+
@name = name.to_s
|
24
|
+
@table = table.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"#{name} (#{table}) #{fields}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'fixture'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
module Util
|
14
|
+
# Hydrate a collection of Fixture instances from configuration.
|
15
|
+
class FixtureSet
|
16
|
+
def initialize(config = {})
|
17
|
+
@fixtures_by_name = config.each_with_object({}) do |(name, fixture_config), memo|
|
18
|
+
memo[name.to_s] = Fixture.make((fixture_config || {}).merge('name' => name))
|
19
|
+
end
|
20
|
+
|
21
|
+
freeze
|
22
|
+
end
|
23
|
+
|
24
|
+
def get!(name)
|
25
|
+
key = name.to_s
|
26
|
+
|
27
|
+
raise ArgumentError, "fixture not found: #{name}" unless fixtures_by_name.key?(key)
|
28
|
+
|
29
|
+
fixtures_by_name[key]
|
30
|
+
end
|
31
|
+
|
32
|
+
def all
|
33
|
+
fixtures_by_name.values
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :fixtures_by_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|