simmer 2.0.0.pre.alpha → 3.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca773bcfd599ef170f20d49b7d7c4cd6fa3d6559d435fe6bc59ad03b2d438ab3
4
- data.tar.gz: 97170a64ec34728574de07e7fb1dde8ba2ca573a0868271942e42af4157fc716
3
+ metadata.gz: 4c2be2ad790619cfd4a18f34df9c05b9a575a67b80a8d8be4a4e2a0fae4f1271
4
+ data.tar.gz: 5467d82cf7c7be7c1aab033b45302d6b97d74b56447194ddd3b8ac4760a7ff11
5
5
  SHA512:
6
- metadata.gz: db9a259095c0be04a8de3d782a54706a42ac6d06a15ea0c53aa371935c17e09b5e6239ebb869b8bf7d75626347e15a7b71ade6bcbe4a780243d641c6dc6779b3
7
- data.tar.gz: c637c746037b0b99a042760b79ba5cedabf5de875db7b1a86ac4e28a7b6948eed32aea9b29be72b7720e2bf5ea825ef9e54f5e2515ac98b6dff01c18e5f2edda
6
+ metadata.gz: 28076b241e673455e18ffc482829425f81754ffde566e58fd9b011cb5d0dd40cb1143b6a35f51f59789096406e5ace09e707e72fa7de640f786b55863a0d7242
7
+ data.tar.gz: eb7a544f07c273e659aa313877741ddb9628ec1e03f04002f63e26663000f47efa8161582a61146f5a5a059130202bafd469047d00fabfcb1371fa1b323d01f2
@@ -13,7 +13,7 @@ Metrics/BlockLength:
13
13
  - define
14
14
 
15
15
  Metrics/MethodLength:
16
- Max: 25
16
+ Max: 30
17
17
 
18
18
  AllCops:
19
19
  TargetRubyVersion: 2.5
@@ -23,3 +23,9 @@ Metrics/AbcSize:
23
23
 
24
24
  Metrics/ClassLength:
25
25
  Max: 125
26
+
27
+ Style/TrailingCommaInHashLiteral:
28
+ Enabled: false
29
+
30
+ Style/TrailingCommaInArrayLiteral:
31
+ Enabled: false
@@ -1 +1 @@
1
- 2.6.5
1
+ 2.6.6
@@ -6,9 +6,9 @@ services:
6
6
  - mysql
7
7
  rvm:
8
8
  # Build on the latest stable of all supported Rubies (https://www.ruby-lang.org/en/downloads/):
9
- - 2.5.5
10
- - 2.6.5
11
- - 2.7.0
9
+ - 2.5.8
10
+ - 2.6.6
11
+ - 2.7.1
12
12
  cache: bundler
13
13
  before_script:
14
14
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
@@ -1 +1,34 @@
1
+ # Simmer Change Log
1
2
 
3
+ ## 3.0.0 (June 8th, 2020)
4
+
5
+ Breaking Changes:
6
+
7
+ * `Simmer::Runner` now accepts a `Simmer::Suite::OutputRouter` instead of an `IO` instance as its 'out' parameter.
8
+ * The `execution_output` and `execution_result` methods have been removed from `Simmer::Runner::Result`.
9
+
10
+ Additions:
11
+
12
+ * pdi_out.txt is written to throughout test execution instead of at the end.
13
+
14
+ Fixes:
15
+
16
+ * Fixtures now handle identifiers which are MySQL reserved words.
17
+
18
+ ## 2.1.0 (May 13th, 2020)
19
+
20
+ Additions:
21
+
22
+ * Do not make missing fixtures short-circuit the rest of the test suite.
23
+ * Do not make PDI timeouts short-circuit the rest of the test suite.
24
+ * Report PDI's exit code and execution time to the console.
25
+
26
+ ## 2.0.0 (May 11th, 2020)
27
+
28
+ Breaking Changes:
29
+
30
+ * Do not emit error file, standard error has been combined with the standard output within the underlying pdi library.
31
+
32
+ Additions:
33
+
34
+ * Enhanced Simmer configuration for `spoon_client` to account for `timeout_in_seconds` option.
data/README.md CHANGED
@@ -281,6 +281,15 @@ Basic steps to take to get this repository compiling:
281
281
  3. Clone the repository (git clone git@github.com:bluemarblepayroll/simmer.git)
282
282
  4. Navigate to the root folder (cd simmer)
283
283
  5. Install dependencies (bundle)
284
+ 6. Create the 'simmer_test' MySQL database as defined in `spec/db/tables.sql`.
285
+ 7. Add the tables from `spec/db/tables.sql` to this database.
286
+ 8. Configure your test simmer.yaml:
287
+
288
+ ````bash
289
+ cp spec/config/simmer.yaml.ci spec/config/simmer.yaml
290
+ ```
291
+
292
+ 9. Edit `spec/config/simmer.yaml` so that it can connect to the database created in step seven.
284
293
 
285
294
  ### Running Tests
286
295
 
@@ -51,7 +51,8 @@ module Simmer
51
51
  )
52
52
  configuration = make_configuration(config_path: config_path, simmer_dir: simmer_dir)
53
53
  specs = make_specifications(path, configuration.tests_dir)
54
- runner = make_runner(configuration, out)
54
+ out_router = make_output_router(configuration, out)
55
+ runner = make_runner(configuration, out_router)
55
56
  suite = make_suite(configuration, out, runner)
56
57
 
57
58
  suite.run(specs)
@@ -66,6 +67,21 @@ module Simmer
66
67
  Configuration.new(raw_config, simmer_dir)
67
68
  end
68
69
 
70
+ def make_runner(configuration, out_router)
71
+ database = make_mysql_database(configuration)
72
+ file_system = make_file_system(configuration)
73
+ fixture_set = make_fixture_set(configuration)
74
+ spoon_client = make_spoon_client(configuration)
75
+
76
+ Runner.new(
77
+ database: database,
78
+ file_system: file_system,
79
+ fixture_set: fixture_set,
80
+ out: out_router,
81
+ spoon_client: spoon_client
82
+ )
83
+ end
84
+
69
85
  private
70
86
 
71
87
  def yaml_reader
@@ -82,21 +98,6 @@ module Simmer
82
98
  end
83
99
  end
84
100
 
85
- def make_runner(configuration, out)
86
- database = make_mysql_database(configuration)
87
- file_system = make_file_system(configuration)
88
- fixture_set = make_fixture_set(configuration)
89
- spoon_client = make_spoon_client(configuration)
90
-
91
- Runner.new(
92
- database: database,
93
- file_system: file_system,
94
- fixture_set: fixture_set,
95
- out: out,
96
- spoon_client: spoon_client
97
- )
98
- end
99
-
100
101
  def make_fixture_set(configuration)
101
102
  config = Util::YamlReader.new.smash(configuration.fixtures_dir)
102
103
 
@@ -142,7 +143,7 @@ module Simmer
142
143
 
143
144
  def make_spoon_client(configuration)
144
145
  config = (configuration.spoon_client_config || {}).symbolize_keys
145
- spoon_args = config.slice(:args, :dir, :kitchen, :pan)
146
+ spoon_args = config.slice(:args, :dir, :kitchen, :pan, :timeout_in_seconds)
146
147
  spoon = Pdi::Spoon.new(spoon_args)
147
148
 
148
149
  Externals::SpoonClient.new(configuration.files_dir, spoon)
@@ -156,5 +157,10 @@ module Simmer
156
157
  runner: runner
157
158
  )
158
159
  end
160
+
161
+ def make_output_router(configuration, console_out)
162
+ pdi_out = Suite::PdiOutputWriter.new(configuration.results_dir)
163
+ Simmer::Suite::OutputRouter.new(console_out, pdi_out)
164
+ end
159
165
  end
160
166
  end
@@ -13,6 +13,8 @@ module Simmer
13
13
  module Database
14
14
  # Hydrate a collection of Fixture instances from configuration.
15
15
  class FixtureSet
16
+ class FixtureMissingError < StandardError; end
17
+
16
18
  def initialize(config = {})
17
19
  @fixtures_by_name = config_to_fixures_by_name(config)
18
20
 
@@ -22,7 +24,7 @@ module Simmer
22
24
  def get!(name)
23
25
  key = name.to_s
24
26
 
25
- raise ArgumentError, "fixture not found: #{name}" unless fixtures_by_name.key?(key)
27
+ raise FixtureMissingError, "fixture missing: #{name}" unless fixtures_by_name.key?(key)
26
28
 
27
29
  fixtures_by_name[key]
28
30
  end
@@ -27,7 +27,7 @@ module Simmer
27
27
  end
28
28
 
29
29
  def records(table, columns = [])
30
- query = "SELECT #{sql_select_params(columns)} FROM #{table}"
30
+ query = "SELECT #{sql_select_params(columns)} FROM #{qualify(table)}"
31
31
 
32
32
  client.query(query).to_a
33
33
  end
@@ -53,7 +53,11 @@ module Simmer
53
53
  attr_reader :client, :fixture_set, :table_names
54
54
 
55
55
  def sql_select_params(columns)
56
- Array(columns).any? ? Array(columns).map { |c| client.escape(c) }.join(',') : '*'
56
+ if Array(columns).any?
57
+ Array(columns).map { |c| qualify(client.escape(c)).to_s }.join(',')
58
+ else
59
+ '*'
60
+ end
57
61
  end
58
62
 
59
63
  def seed_sql_statements(fixtures)
@@ -62,7 +66,7 @@ module Simmer
62
66
 
63
67
  def clean_sql_statements
64
68
  table_names.map do |table_name|
65
- "TRUNCATE #{table_name}"
69
+ "TRUNCATE #{qualify(table_name)}"
66
70
  end
67
71
  end
68
72
 
@@ -110,6 +114,10 @@ module Simmer
110
114
 
111
115
  raise ArgumentError, "database (#{name}) must end in #{DATABASE_SUFFIX}"
112
116
  end
117
+
118
+ def qualify(identifier)
119
+ "`#{identifier}`"
120
+ end
113
121
  end
114
122
  end
115
123
  end
@@ -13,6 +13,8 @@ module Simmer
13
13
  module Externals
14
14
  # Wraps up Pdi::Spoon at a higher-level for Simmer to consume.
15
15
  class SpoonClient
16
+ attr_reader :spoon
17
+
16
18
  def initialize(files_dir, spoon)
17
19
  raise ArgumentError, 'spoon is required' unless spoon
18
20
 
@@ -22,13 +24,13 @@ module Simmer
22
24
  freeze
23
25
  end
24
26
 
25
- def run(specification, config)
27
+ def run(specification, config, &output_capturer)
26
28
  execution_result = nil
27
29
  time_in_seconds = nil
28
30
 
29
31
  begin
30
32
  time_in_seconds = Benchmark.measure do
31
- execution_result = execute!(specification, config)
33
+ execution_result = execute!(specification, config, &output_capturer)
32
34
  end.real
33
35
  rescue Pdi::Spoon::PanError, Pdi::Spoon::KitchenError => e
34
36
  return Result.new(
@@ -46,16 +48,17 @@ module Simmer
46
48
 
47
49
  private
48
50
 
49
- attr_reader :files_dir, :spoon
51
+ attr_reader :files_dir
50
52
 
51
- def execute!(specification, config)
53
+ def execute!(specification, config, &output_capturer)
52
54
  act = specification.act
53
55
 
54
56
  spoon.run(
55
57
  repository: act.repository,
56
58
  name: act.name,
57
59
  params: act.compiled_params(files_dir, config),
58
- type: act.type
60
+ type: act.type,
61
+ &output_capturer
59
62
  )
60
63
  end
61
64
  end
@@ -13,7 +13,7 @@ module Simmer
13
13
  class Result
14
14
  attr_reader :bad_assertions
15
15
 
16
- def initialize(bad_assertions)
16
+ def initialize(bad_assertions = [])
17
17
  @bad_assertions = bad_assertions
18
18
 
19
19
  freeze
@@ -13,6 +13,8 @@ require_relative 'runner/result'
13
13
  module Simmer
14
14
  # Runs a single specification.
15
15
  class Runner
16
+ attr_reader :spoon_client
17
+
16
18
  def initialize(database:, file_system:, fixture_set:, out:, spoon_client:)
17
19
  @database = database
18
20
  @file_system = file_system
@@ -25,109 +27,112 @@ module Simmer
25
27
  end
26
28
 
27
29
  def run(specification, config: {}, id: SecureRandom.uuid)
28
- print("Name: #{specification.name}")
29
- print("Path: #{specification.path}")
30
-
31
- clean_db
32
- seed_db(specification)
33
- clean_file_system
34
- seed_file_system(specification)
30
+ out.announce_start(id, specification)
31
+ clean_and_seed(specification)
35
32
 
36
33
  spoon_client_result = execute_spoon(specification, config)
37
34
  judge_result = assert(specification, spoon_client_result)
38
35
 
39
- Result.new(id, judge_result, specification, spoon_client_result).tap do |result|
40
- msg = pass_message(result)
41
- print_waiting('Done', 'Final verdict')
42
- print(msg)
36
+ Result.new(
37
+ id: id,
38
+ judge_result: judge_result,
39
+ specification: specification,
40
+ spoon_client_result: spoon_client_result
41
+ ).tap do |result|
42
+ out.final_verdict(result)
43
+ end
44
+ rescue Database::FixtureSet::FixtureMissingError, Timeout::Error => e
45
+ Result.new(
46
+ id: id,
47
+ specification: specification,
48
+ errors: e.message
49
+ ).tap do |result|
50
+ out.final_verdict(result)
43
51
  end
44
52
  end
45
53
 
54
+ def complete
55
+ out.close
56
+ end
57
+
46
58
  private
47
59
 
48
- attr_reader :database, :file_system, :fixture_set, :judge, :out, :spoon_client
60
+ attr_reader :database, :file_system, :fixture_set, :judge, :out
61
+
62
+ def clean_and_seed(specification)
63
+ clean_db
64
+ seed_db(specification)
65
+ clean_file_system
66
+ seed_file_system(specification)
67
+ end
49
68
 
50
69
  def clean_db
51
- print_waiting('Stage', 'Cleaning database')
70
+ out.waiting('Stage', 'Cleaning database')
52
71
  count = database.clean!
53
- print("#{count} table(s) emptied")
72
+ out.console_puts("#{count} table(s) emptied")
54
73
 
55
74
  count
56
75
  end
57
76
 
58
77
  def seed_db(specification)
59
- print_waiting('Stage', 'Seeding database')
78
+ out.waiting('Stage', 'Seeding database')
60
79
 
61
80
  fixtures = specification.stage.fixtures.map { |f| fixture_set.get!(f) }
62
81
  count = database.seed!(fixtures)
63
82
 
64
- print("#{count} record(s) inserted")
83
+ out.console_puts("#{count} record(s) inserted")
65
84
 
66
85
  count
86
+ rescue Database::FixtureSet::FixtureMissingError => e
87
+ out.console_puts('Missing Fixture(s)')
88
+ raise e
67
89
  end
68
90
 
69
91
  def clean_file_system
70
- print_waiting('Stage', 'Cleaning File System')
92
+ out.waiting('Stage', 'Cleaning File System')
71
93
  count = file_system.clean!
72
- print("#{count} file(s) deleted")
94
+ out.console_puts("#{count} file(s) deleted")
73
95
 
74
96
  count
75
97
  end
76
98
 
77
99
  def seed_file_system(specification)
78
- print_waiting('Stage', 'Seeding File System')
100
+ out.waiting('Stage', 'Seeding File System')
79
101
  count = file_system.write!(specification.stage.files)
80
- print("#{count} file(s) uploaded")
102
+ out.console_puts("#{count} file(s) uploaded")
81
103
 
82
104
  count
83
105
  end
84
106
 
85
107
  def execute_spoon(specification, config)
86
- print_waiting('Act', 'Executing Spoon')
87
- spoon_client_result = spoon_client.run(specification, config)
88
- msg = pass_message(spoon_client_result)
89
- print(msg)
108
+ out.waiting('Act', 'Executing Spoon')
109
+
110
+ spoon_client_result = spoon_client.run(specification, config) do |output|
111
+ out.capture_spoon_output(output)
112
+ end
113
+
114
+ out.finish_spec
115
+ out.spoon_execution_detail_message(spoon_client_result)
90
116
 
91
117
  spoon_client_result
118
+ rescue Timeout::Error => e
119
+ out.console_puts('Timed out')
120
+ raise e
92
121
  end
93
122
 
94
123
  def assert(specification, spoon_client_result)
95
- print_waiting('Assert', 'Checking results')
124
+ out.waiting('Assert', 'Checking results')
96
125
 
97
126
  if spoon_client_result.fail?
98
- print('Skipped')
127
+ out.console_puts('Skipped')
99
128
  return nil
100
129
  end
101
130
 
102
131
  output = spoon_client_result.execution_result.out
103
132
  judge_result = judge.assert(specification, output)
104
- msg = pass_message(judge_result)
105
-
106
- print(msg)
133
+ out.result(judge_result)
107
134
 
108
135
  judge_result
109
136
  end
110
-
111
- def print(msg)
112
- out.puts(msg)
113
- end
114
-
115
- def print_waiting(stage, msg)
116
- max = 25
117
- char = '.'
118
- msg = " > #{pad_right(stage, 6)} - #{pad_right(msg, max, char)}"
119
-
120
- out.print(msg)
121
- end
122
-
123
- def pad_right(msg, len, char = ' ')
124
- missing = len - msg.length
125
-
126
- "#{msg}#{char * missing}"
127
- end
128
-
129
- def pass_message(obj)
130
- obj.pass? ? 'Pass' : 'Fail'
131
- end
132
137
  end
133
138
  end
@@ -13,23 +13,36 @@ module Simmer
13
13
  class Result
14
14
  extend Forwardable
15
15
 
16
- attr_reader :id, :judge_result, :specification, :spoon_client_result
17
-
18
- def_delegators :spoon_client_result, :time_in_seconds
16
+ attr_reader :errors, :id, :judge_result, :specification, :spoon_client_result
19
17
 
20
18
  def_delegators :specification, :name
21
19
 
22
- def initialize(id, judge_result, specification, spoon_client_result)
20
+ def initialize(
21
+ id:,
22
+ specification:,
23
+ judge_result: nil,
24
+ spoon_client_result: nil,
25
+ errors: []
26
+ )
23
27
  @id = id.to_s
24
28
  @judge_result = judge_result
25
29
  @specification = specification
26
30
  @spoon_client_result = spoon_client_result
31
+ @errors = Array(errors)
27
32
 
28
33
  freeze
29
34
  end
30
35
 
36
+ def time_in_seconds
37
+ spoon_client_result&.time_in_seconds || 0
38
+ end
39
+
31
40
  def pass?
32
- judge_result&.pass? && spoon_client_result&.pass?
41
+ [
42
+ judge_result&.pass?,
43
+ spoon_client_result&.pass?,
44
+ errors.empty?,
45
+ ].all?
33
46
  end
34
47
 
35
48
  def fail?
@@ -44,7 +57,8 @@ module Simmer
44
57
  'time_in_seconds' => time_in_seconds,
45
58
  'pass' => pass?,
46
59
  'spoon_client_result' => spoon_client_result.to_h,
47
- 'judge_result' => judge_result.to_h
60
+ 'judge_result' => judge_result.to_h,
61
+ 'errors' => errors,
48
62
  }
49
63
  end
50
64
  end
@@ -7,7 +7,9 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- require_relative 'suite/reporter'
10
+ require_relative 'suite/output_router'
11
+ require_relative 'suite/pdi_output_writer'
12
+ require_relative 'suite/results_writer'
11
13
  require_relative 'suite/result'
12
14
 
13
15
  module Simmer
@@ -33,15 +35,12 @@ module Simmer
33
35
 
34
36
  def run(specifications)
35
37
  runner_results = run_all_specs(specifications)
38
+ runner.complete
36
39
 
37
40
  Result.new(runner_results).tap do |result|
38
- if result.pass?
39
- out.puts('Suite ended successfully')
40
- else
41
- out.puts('Suite ended but was not successful')
42
- end
41
+ output_summary(result.pass?)
43
42
 
44
- Reporter.new(result).write!(results_dir)
43
+ ResulstWriter.new(result, results_dir).write!
45
44
 
46
45
  out.puts("Results can be viewed at #{results_dir}")
47
46
  end
@@ -77,5 +76,13 @@ module Simmer
77
76
  def print_line
78
77
  out.puts('-' * LINE_LENGTH)
79
78
  end
79
+
80
+ def output_summary(passed)
81
+ if passed
82
+ out.puts('Suite ended successfully')
83
+ else
84
+ out.puts('Suite ended but was not successful')
85
+ end
86
+ end
80
87
  end
81
88
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Simmer
4
+ class Suite
5
+ # Routes output either to the console or the <tt>PdiOutputWriter</tt>. It
6
+ # also provides some methods to help format output.
7
+ class OutputRouter
8
+ extend Forwardable
9
+
10
+ attr_reader :console, :pdi_out
11
+
12
+ def_delegator :console, :puts, :console_puts
13
+ def_delegators :pdi_out, :close, :finish_spec
14
+ def_delegator :pdi_out, :write, :capture_spoon_output
15
+
16
+ def initialize(console, pdi_out)
17
+ @console = console || raise(ArgumentError, 'console is required')
18
+ @pdi_out = pdi_out || raise(ArgumentError, 'pdi_out is required')
19
+
20
+ freeze
21
+ end
22
+
23
+ def announce_start(id, specification)
24
+ console_puts("Name: #{specification.name}")
25
+ console_puts("Path: #{specification.path}")
26
+ pdi_out.demarcate_spec(id, specification.name)
27
+ end
28
+
29
+ def result(result)
30
+ console_puts(pass_message(result))
31
+ end
32
+
33
+ def final_verdict(result)
34
+ msg = pass_message(result)
35
+ waiting('Done', 'Final verdict')
36
+ console_puts(msg)
37
+ end
38
+
39
+ def waiting(stage, msg)
40
+ # This is not for debugging.
41
+ # rubocop:disable Lint/Debugger
42
+ console.print(
43
+ " > #{pad_right(stage, 6)} - #{pad_right(msg, WAITING_MAX_WIDTH, WAITING_PADDING_CHAR)}"
44
+ )
45
+ # rubocop:enable Lint/Debugger
46
+ end
47
+
48
+ def spoon_execution_detail_message(spoon_client_result)
49
+ code = spoon_client_result.execution_result.status.code
50
+ detail = "(Exited with code #{code} after #{spoon_client_result.time_in_seconds} seconds)"
51
+
52
+ console_puts("#{pass_message(spoon_client_result)} #{detail}")
53
+ end
54
+
55
+ private
56
+
57
+ WAITING_MAX_WIDTH = 25
58
+ WAITING_PADDING_CHAR = '.'
59
+
60
+ private_constant :WAITING_MAX_WIDTH, :WAITING_PADDING_CHAR
61
+
62
+ def pad_right(msg, len, char = ' ')
63
+ missing = len - msg.length
64
+
65
+ "#{msg}#{char * missing}"
66
+ end
67
+
68
+ def pass_message(obj)
69
+ obj.pass? ? 'Pass' : 'Fail'
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,56 @@
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 Suite
12
+ # Captures PDI output from multiple specifications to a single file.
13
+ class PdiOutputWriter # :nodoc:
14
+ PDI_OUT_FILE = 'pdi_out.txt'
15
+
16
+ attr_reader :results_dir
17
+
18
+ def initialize(results_dir)
19
+ raise ArgumentError, 'results_dir is required' unless results_dir
20
+
21
+ results_dir = Util::FileSystem.setup_directory(results_dir)
22
+ @out = File.new(File.join(results_dir, PDI_OUT_FILE), 'w')
23
+
24
+ freeze
25
+ end
26
+
27
+ def demarcate_spec(runner_id, spec_name)
28
+ out.puts(LINE_OF_HYPHENS)
29
+ out.puts("Name: #{spec_name}")
30
+ out.puts("Runner ID: #{runner_id}")
31
+ out.puts(LINE_OF_HYPHENS)
32
+ end
33
+
34
+ def write(contents)
35
+ bytes_written = out.write(contents)
36
+ out.flush
37
+ bytes_written
38
+ end
39
+
40
+ def finish_spec
41
+ out.puts
42
+ end
43
+
44
+ def close
45
+ out.close
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :out
51
+
52
+ LINE_OF_HYPHENS = ('-' * 80).freeze
53
+ private_constant :LINE_OF_HYPHENS
54
+ end
55
+ end
56
+ end
@@ -22,6 +22,7 @@ module Simmer
22
22
  def pass?
23
23
  !fail?
24
24
  end
25
+ alias passing? pass?
25
26
 
26
27
  def fail?
27
28
  runner_results.any?(&:fail?)
@@ -0,0 +1,44 @@
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 Suite
12
+ # Understands how to write a SessionResult instance to disk.
13
+ class ResulstWriter
14
+ DATA_FILE = 'data.yaml'
15
+
16
+ # Pass in dir here:
17
+ def initialize(session_result, results_dir)
18
+ raise ArgumentError, 'session_result is required' unless session_result
19
+ raise ArgumentError, 'results_directory is required' unless results_dir
20
+
21
+ @session_result = session_result
22
+ @results_directory = Util::FileSystem.setup_directory(results_dir)
23
+
24
+ freeze
25
+ end
26
+
27
+ def write!
28
+ dir = Util::FileSystem.setup_directory(results_directory)
29
+
30
+ IO.write(data_path(dir), session_result.to_h.to_yaml)
31
+
32
+ self
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :results_directory, :session_result
38
+
39
+ def data_path(dir)
40
+ File.join(dir, DATA_FILE)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -8,5 +8,6 @@
8
8
  #
9
9
 
10
10
  require_relative 'util/evaluator'
11
+ require_relative 'util/file_system'
11
12
  require_relative 'util/record_set'
12
13
  require_relative 'util/yaml_reader'
@@ -0,0 +1,25 @@
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
+ # Provides convenience methods for working with the file system.
15
+ class FileSystem # :nodoc:
16
+ class << self
17
+ def setup_directory(dir_path)
18
+ File.expand_path(dir_path).tap do |expanded_dir|
19
+ FileUtils.mkdir_p(expanded_dir)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Simmer
11
- VERSION = '2.0.0-alpha'
11
+ VERSION = '3.0.0'
12
12
  end
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  Provides a harness for testing Pentaho Data Integration jobs and transformations.
12
12
  DESCRIPTION
13
13
 
14
- s.authors = ['Matthew Ruggio']
14
+ s.authors = ['Matthew Ruggio', 'Ryan Gerry']
15
15
  s.email = ['mruggio@bluemarblepayroll.com']
16
16
  s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
  s.bindir = 'exe'
@@ -32,11 +32,12 @@ Gem::Specification.new do |s|
32
32
  s.add_dependency('aws-sdk-s3', '~>1.6')
33
33
  s.add_dependency('mysql2', '~>0.5')
34
34
  s.add_dependency('objectable', '~>1')
35
- s.add_dependency('pdi', '>=2.0.0.pre.alpha')
35
+ s.add_dependency('pdi', '~>2.1')
36
36
  s.add_dependency('stringento', '~>2')
37
37
 
38
38
  s.add_development_dependency('guard-rspec', '~>4.7')
39
39
  s.add_development_dependency('pry', '~>0')
40
+ s.add_development_dependency 'pry-byebug'
40
41
  s.add_development_dependency('rake', '~> 13')
41
42
  s.add_development_dependency('rspec')
42
43
  s.add_development_dependency('rubocop', '~>0.79.0')
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.alpha
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
+ - Ryan Gerry
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2020-05-08 00:00:00.000000000 Z
12
+ date: 2020-06-10 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: acts_as_hashable
@@ -70,16 +71,16 @@ dependencies:
70
71
  name: pdi
71
72
  requirement: !ruby/object:Gem::Requirement
72
73
  requirements:
73
- - - ">="
74
+ - - "~>"
74
75
  - !ruby/object:Gem::Version
75
- version: 2.0.0.pre.alpha
76
+ version: '2.1'
76
77
  type: :runtime
77
78
  prerelease: false
78
79
  version_requirements: !ruby/object:Gem::Requirement
79
80
  requirements:
80
- - - ">="
81
+ - - "~>"
81
82
  - !ruby/object:Gem::Version
82
- version: 2.0.0.pre.alpha
83
+ version: '2.1'
83
84
  - !ruby/object:Gem::Dependency
84
85
  name: stringento
85
86
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +123,20 @@ dependencies:
122
123
  - - "~>"
123
124
  - !ruby/object:Gem::Version
124
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: pry-byebug
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
125
140
  - !ruby/object:Gem::Dependency
126
141
  name: rake
127
142
  requirement: !ruby/object:Gem::Requirement
@@ -245,10 +260,13 @@ files:
245
260
  - lib/simmer/specification/stage.rb
246
261
  - lib/simmer/specification/stage/input_file.rb
247
262
  - lib/simmer/suite.rb
248
- - lib/simmer/suite/reporter.rb
263
+ - lib/simmer/suite/output_router.rb
264
+ - lib/simmer/suite/pdi_output_writer.rb
249
265
  - lib/simmer/suite/result.rb
266
+ - lib/simmer/suite/results_writer.rb
250
267
  - lib/simmer/util.rb
251
268
  - lib/simmer/util/evaluator.rb
269
+ - lib/simmer/util/file_system.rb
252
270
  - lib/simmer/util/record.rb
253
271
  - lib/simmer/util/record_set.rb
254
272
  - lib/simmer/util/resolver.rb
@@ -275,9 +293,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
275
293
  version: '2.5'
276
294
  required_rubygems_version: !ruby/object:Gem::Requirement
277
295
  requirements:
278
- - - ">"
296
+ - - ">="
279
297
  - !ruby/object:Gem::Version
280
- version: 1.3.1
298
+ version: '0'
281
299
  requirements: []
282
300
  rubygems_version: 3.0.3
283
301
  signing_key:
@@ -1,83 +0,0 @@
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 Suite
12
- # Understands how to write a SessionResult instance to disk.
13
- class Reporter
14
- DATA_FILE = 'data.yaml'
15
- PDI_OUT_FILE = 'pdi_out.txt'
16
-
17
- def initialize(session_result)
18
- raise ArgumentError, 'session_result is required' unless session_result
19
-
20
- @session_result = session_result
21
-
22
- freeze
23
- end
24
-
25
- def write!(dir)
26
- dir = setup_directory(dir)
27
-
28
- IO.write(data_path(dir), session_result.to_h.to_yaml)
29
-
30
- pdi_out_file = File.open(pdi_out_path(dir), 'w')
31
-
32
- write_part(session_result.runner_results, pdi_out_file)
33
-
34
- pdi_out_file.close
35
-
36
- self
37
- end
38
-
39
- private
40
-
41
- attr_reader :session_result
42
-
43
- def data_path(dir)
44
- File.join(dir, DATA_FILE)
45
- end
46
-
47
- def pdi_out_path(dir)
48
- File.join(dir, PDI_OUT_FILE)
49
- end
50
-
51
- def setup_directory(dir)
52
- File.expand_path(dir).tap do |expanded_dir|
53
- FileUtils.mkdir_p(expanded_dir)
54
- end
55
- end
56
-
57
- def write_part(runner_results, pdi_out_file)
58
- runner_results.each do |runner_result|
59
- name = runner_result.name
60
- runner_id = runner_result.id
61
- out_contents = runner_result.spoon_client_result.execution_result.out
62
-
63
- write_block(pdi_out_file, name, runner_id, out_contents)
64
- end
65
-
66
- nil
67
- end
68
-
69
- def write_block(file, name, runner_id, contents)
70
- hyphens = '-' * 80
71
-
72
- file.write("#{hyphens}\n")
73
- file.write("Name: #{name}\n")
74
- file.write("Runner ID: #{runner_id}\n")
75
- file.write("#{hyphens}\n")
76
- file.write("#{contents}\n")
77
- file.write("\n")
78
-
79
- nil
80
- end
81
- end
82
- end
83
- end