simmer 2.0.0.pre.alpha → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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