simmer 3.0.0 → 4.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: 4c2be2ad790619cfd4a18f34df9c05b9a575a67b80a8d8be4a4e2a0fae4f1271
4
- data.tar.gz: 5467d82cf7c7be7c1aab033b45302d6b97d74b56447194ddd3b8ac4760a7ff11
3
+ metadata.gz: fcaddd54b4d50b90701d91f9a62fdfd163a249565d88c850386caf22135a0af3
4
+ data.tar.gz: 143b6629e67a14e365d6e16a0d795b607f1f4f29aadc270be6458e715a7b68b3
5
5
  SHA512:
6
- metadata.gz: 28076b241e673455e18ffc482829425f81754ffde566e58fd9b011cb5d0dd40cb1143b6a35f51f59789096406e5ace09e707e72fa7de640f786b55863a0d7242
7
- data.tar.gz: eb7a544f07c273e659aa313877741ddb9628ec1e03f04002f63e26663000f47efa8161582a61146f5a5a059130202bafd469047d00fabfcb1371fa1b323d01f2
6
+ metadata.gz: 6645db0960863e2490964b56228969bd3b4a061cc8ad61b069a239dee8920d2861bdbeb125b758861426079529b3c7faed1bb645c67bb3ebbbbeb7a5a9fc11bf
7
+ data.tar.gz: 257ab72c85cca10bc54a6e23d451b3da17bd056c8d0a2b96a5b493c0f58a2d38f98bd7e6a4fcd14bafe190a8cafecfabf70a713be37777b86befef88e34e7220
@@ -1,5 +1,19 @@
1
1
  # Simmer Change Log
2
2
 
3
+ ## 4.0.0 (TBD, 2020)
4
+
5
+ Additions:
6
+
7
+ * Support for custom test lifecycle hooks to be run before and after a every test or the entire suite.
8
+ * Simmer can now be configured to re-run tests which have failed due to a timeout a custom number of times.
9
+
10
+ Breaking Changes:
11
+
12
+ * The `callback_configuration` and `make_runner` methods have been removed from the `Simmer` module.
13
+ * `Simmer::Runner::Result#errors` now contains error/exception instances instead of strings.
14
+ * `Simmer::Suite.new` and `Simmer::Runner.run` now takes a `Simmer::Configuration` instance instead of a hash of configuration values.
15
+ * The config keyword parameter of `Simmer::Runner.run` is now mandatory.
16
+
3
17
  ## 3.0.0 (June 8th, 2020)
4
18
 
5
19
  Breaking Changes:
data/README.md CHANGED
@@ -53,6 +53,9 @@ The configuration file contains information about external systems, such as:
53
53
  Copy this configuration template into your project's root to: `config/simmer.yaml`:
54
54
 
55
55
  ````yaml
56
+ # Automatically retry a test when it has failed this many times due to a timeout error:
57
+ timeout_failure_retry_count: 0
58
+
56
59
  mysql_database:
57
60
  database:
58
61
  username:
@@ -270,6 +273,34 @@ You can also omit the path altogether to execute all specs:
270
273
  bundle exec simmer
271
274
  ````
272
275
 
276
+ ## Custom Configuration
277
+
278
+ It is possible to define custom test lifecycle hooks. These are very similar to [Rspec](https://relishapp.com/rspec/rspec-core/v/3-9/docs/hooks/before-and-after-hooks). Here is an example of how to ensure that code called before and after the entire suite:
279
+
280
+ ````ruby
281
+ Simmer.configure do |config|
282
+ config.before(:suite) { puts 'about to run the entire suite' }
283
+ config.after(:suite) do |result|
284
+ result_msg = result.passed? ? 'passed' : 'failed'
285
+ puts "The suite #{result_msg}."
286
+ end
287
+ end
288
+ ````
289
+
290
+ Not that after callbacks taken an optional parameter which is the result object.
291
+
292
+ It is also possible to specify custom code which runs before and after each individual specification.
293
+
294
+ ````ruby
295
+ Simmer.configure do |config|
296
+ config.before(:each) { puts 'I will run before each test' }
297
+ config.after(:each) do |result|
298
+ result_msg = result.passed? ? 'passed' : 'failed'
299
+ puts "The specification #{result_msg}."
300
+ end
301
+ end
302
+ ````
303
+
273
304
  ## Contributing
274
305
 
275
306
  ### Development Environment Configuration
@@ -22,7 +22,7 @@ require 'set'
22
22
  require 'stringento'
23
23
  require 'yaml'
24
24
 
25
- # Monkey-patching core libaries
25
+ # Monkey-patching core libraries
26
26
  require_relative 'simmer/core_ext/hash'
27
27
  Hash.include Simmer::CoreExt::Hash
28
28
 
@@ -30,10 +30,12 @@ Hash.include Simmer::CoreExt::Hash
30
30
  require_relative 'simmer/util'
31
31
 
32
32
  # Core code
33
+ require_relative 'simmer/bootstrap'
33
34
  require_relative 'simmer/configuration'
34
35
  require_relative 'simmer/database'
35
36
  require_relative 'simmer/externals'
36
37
  require_relative 'simmer/runner'
38
+ require_relative 'simmer/re_runner'
37
39
  require_relative 'simmer/specification'
38
40
  require_relative 'simmer/suite'
39
41
 
@@ -49,118 +51,28 @@ module Simmer
49
51
  out: $stdout,
50
52
  simmer_dir: DEFAULT_SIMMER_DIR
51
53
  )
52
- configuration = make_configuration(config_path: config_path, simmer_dir: simmer_dir)
53
- specs = make_specifications(path, configuration.tests_dir)
54
- out_router = make_output_router(configuration, out)
55
- runner = make_runner(configuration, out_router)
56
- suite = make_suite(configuration, out, runner)
57
-
58
- suite.run(specs)
54
+ Bootstrap.new(
55
+ spec_path: path,
56
+ config_path: config_path,
57
+ simmer_dir: simmer_dir,
58
+ callback_configuration: callback_configuration,
59
+ console_out: out
60
+ ).run_suite
59
61
  end
60
62
 
61
- def make_configuration(
62
- config_path: DEFAULT_CONFIG_PATH,
63
- simmer_dir: DEFAULT_SIMMER_DIR
64
- )
65
- raw_config = yaml_reader.smash(config_path)
66
-
67
- Configuration.new(raw_config, simmer_dir)
63
+ def configuration(config_path: DEFAULT_CONFIG_PATH, simmer_dir: DEFAULT_SIMMER_DIR)
64
+ Bootstrap.new(config_path: config_path, simmer_dir: simmer_dir).configuration
68
65
  end
66
+ alias make_configuration configuration
69
67
 
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
- )
68
+ def configure
69
+ yield callback_configuration
83
70
  end
84
71
 
85
72
  private
86
73
 
87
- def yaml_reader
88
- Util::YamlReader.new
89
- end
90
-
91
- def make_specifications(path, tests_dir)
92
- path = path.to_s.empty? ? tests_dir : path
93
-
94
- Util::YamlReader.new.read(path).map do |file|
95
- config = (file.data || {}).merge(path: file.path)
96
-
97
- Specification.make(config)
98
- end
99
- end
100
-
101
- def make_fixture_set(configuration)
102
- config = Util::YamlReader.new.smash(configuration.fixtures_dir)
103
-
104
- Database::FixtureSet.new(config)
105
- end
106
-
107
- def make_mysql_database(configuration)
108
- config = configuration.mysql_database_config.symbolize_keys
109
- client = Mysql2::Client.new(config)
110
- exclude_tables = config[:exclude_tables]
111
-
112
- Externals::MysqlDatabase.new(client, exclude_tables)
113
- end
114
-
115
- def make_file_system(configuration)
116
- if configuration.aws_file_system?
117
- make_aws_file_system(configuration)
118
- elsif configuration.local_file_system?
119
- make_local_file_system(configuration)
120
- else
121
- raise ArgumentError, 'cannot determine file system'
122
- end
123
- end
124
-
125
- def make_aws_file_system(configuration)
126
- config = configuration.aws_file_system_config.symbolize_keys
127
- client_args = config.slice(:access_key_id, :secret_access_key, :region)
128
- client = Aws::S3::Client.new(client_args)
129
-
130
- Externals::AwsFileSystem.new(
131
- client,
132
- config[:bucket],
133
- config[:encryption],
134
- configuration.files_dir
135
- )
136
- end
137
-
138
- def make_local_file_system(configuration)
139
- config = configuration.local_file_system_config.symbolize_keys
140
-
141
- Externals::LocalFileSystem.new(config[:dir], configuration.files_dir)
142
- end
143
-
144
- def make_spoon_client(configuration)
145
- config = (configuration.spoon_client_config || {}).symbolize_keys
146
- spoon_args = config.slice(:args, :dir, :kitchen, :pan, :timeout_in_seconds)
147
- spoon = Pdi::Spoon.new(spoon_args)
148
-
149
- Externals::SpoonClient.new(configuration.files_dir, spoon)
150
- end
151
-
152
- def make_suite(configuration, out, runner)
153
- Suite.new(
154
- config: configuration.config,
155
- out: out,
156
- results_dir: configuration.results_dir,
157
- runner: runner
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)
74
+ def callback_configuration
75
+ @callback_configuration ||= Configuration::CallbackDsl.new
164
76
  end
165
77
  end
166
78
  end
@@ -0,0 +1,133 @@
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
+ # :nodoc:
12
+ # Responsible for creating core objects needed to run tests.
13
+ class Bootstrap
14
+ attr_reader :callback_configuration, :configuration, :console_out, :spec_path
15
+
16
+ def initialize(
17
+ config_path:,
18
+ simmer_dir:,
19
+ spec_path: nil,
20
+ console_out: $stdout,
21
+ callback_configuration: Configuration::CallbackDsl.new
22
+ )
23
+ @spec_path = spec_path.to_s
24
+ raw_config = yaml_reader.smash(config_path)
25
+ @configuration = Configuration.new(raw_config, simmer_dir, callbacks: callback_configuration)
26
+ @console_out = console_out
27
+ @callback_configuration = callback_configuration
28
+
29
+ freeze
30
+ end
31
+
32
+ def run_suite
33
+ suite.run(specs)
34
+ end
35
+
36
+ private
37
+
38
+ def specs
39
+ path = spec_path.empty? ? configuration.tests_dir : spec_path
40
+
41
+ Util::YamlReader.new.read(path).map do |file|
42
+ config = (file.data || {}).merge(path: file.path)
43
+
44
+ Specification.make(config)
45
+ end
46
+ end
47
+
48
+ def suite
49
+ Suite.new(
50
+ config: configuration,
51
+ out: console_out,
52
+ results_dir: configuration.results_dir,
53
+ runner: runner
54
+ )
55
+ end
56
+
57
+ def runner
58
+ runner = Runner.new(
59
+ database: mysql_database,
60
+ file_system: file_system,
61
+ fixture_set: fixture_set,
62
+ out: output_router,
63
+ spoon_client: spoon_client
64
+ )
65
+
66
+ ReRunner.new(
67
+ runner,
68
+ output_router,
69
+ timeout_failure_retry_count: configuration.timeout_failure_retry_count
70
+ )
71
+ end
72
+
73
+ def yaml_reader
74
+ Util::YamlReader.new
75
+ end
76
+
77
+ def fixture_set
78
+ config = Util::YamlReader.new.smash(configuration.fixtures_dir)
79
+
80
+ Database::FixtureSet.new(config)
81
+ end
82
+
83
+ def mysql_database
84
+ config = configuration.mysql_database_config.symbolize_keys
85
+ client = Mysql2::Client.new(config)
86
+ exclude_tables = config[:exclude_tables]
87
+
88
+ Externals::MysqlDatabase.new(client, exclude_tables)
89
+ end
90
+
91
+ def file_system
92
+ if configuration.aws_file_system?
93
+ aws_file_system
94
+ elsif configuration.local_file_system?
95
+ local_file_system
96
+ else
97
+ raise ArgumentError, 'cannot determine file system'
98
+ end
99
+ end
100
+
101
+ def aws_file_system
102
+ config = configuration.aws_file_system_config.symbolize_keys
103
+ client_args = config.slice(:access_key_id, :secret_access_key, :region)
104
+ client = Aws::S3::Client.new(client_args)
105
+
106
+ Externals::AwsFileSystem.new(
107
+ client,
108
+ config[:bucket],
109
+ config[:encryption],
110
+ configuration.files_dir
111
+ )
112
+ end
113
+
114
+ def local_file_system
115
+ config = configuration.local_file_system_config.symbolize_keys
116
+
117
+ Externals::LocalFileSystem.new(config[:dir], configuration.files_dir)
118
+ end
119
+
120
+ def spoon_client
121
+ config = (configuration.spoon_client_config || {}).symbolize_keys
122
+ spoon_args = config.slice(:args, :dir, :kitchen, :pan, :timeout_in_seconds)
123
+ spoon = Pdi::Spoon.new(spoon_args)
124
+
125
+ Externals::SpoonClient.new(configuration.files_dir, spoon)
126
+ end
127
+
128
+ def output_router
129
+ pdi_out = Suite::PdiOutputWriter.new(configuration.results_dir)
130
+ Simmer::Suite::OutputRouter.new(console_out, pdi_out)
131
+ end
132
+ end
133
+ end
@@ -7,14 +7,19 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
+ require_relative 'configuration/callback_dsl'
11
+
10
12
  module Simmer
11
13
  # Reads in the Simmer configuration file and options and provides it to the rest of the
12
14
  # Simmer implementation.
13
15
  class Configuration
16
+ extend Forwardable
17
+
14
18
  # Configuration Keys
15
19
  AWS_FILE_SYSTEM_KEY = :aws_file_system
16
20
  LOCAL_FILE_SYSTEM_KEY = :local_file_system
17
21
  MYSQL_DATABASE_KEY = :mysql_database
22
+ TIMEOUT_RETRY_KEY = :timeout_failure_retry_count
18
23
  SPOON_CLIENT_KEY = :spoon_client
19
24
 
20
25
  # Paths
@@ -32,10 +37,14 @@ module Simmer
32
37
 
33
38
  attr_reader :config
34
39
 
35
- def initialize(config, simmer_dir, resolver: Objectable.resolver)
40
+ # :nodoc:
41
+ def_delegators :callbacks, :run_single_test_with_callbacks, :run_suite_with_callbacks
42
+
43
+ def initialize(config, simmer_dir, resolver: Objectable.resolver, callbacks: nil)
36
44
  @config = config || {}
37
45
  @resolver = resolver
38
46
  @simmer_dir = simmer_dir
47
+ @callbacks = callbacks
39
48
 
40
49
  freeze
41
50
  end
@@ -60,6 +69,10 @@ module Simmer
60
69
  config.key?(LOCAL_FILE_SYSTEM_KEY.to_s)
61
70
  end
62
71
 
72
+ def timeout_failure_retry_count
73
+ get(TIMEOUT_RETRY_KEY) || 0
74
+ end
75
+
63
76
  def spoon_client_config
64
77
  get(SPOON_CLIENT_KEY) || {}
65
78
  end
@@ -82,7 +95,8 @@ module Simmer
82
95
 
83
96
  private
84
97
 
85
- attr_reader :resolver,
98
+ attr_reader :callbacks,
99
+ :resolver,
86
100
  :simmer_dir,
87
101
  :yaml_reader
88
102
 
@@ -0,0 +1,79 @@
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 Configuration
12
+ # Defines lifecycle hooks which can be run before and after the entire
13
+ # suite or just a single test. Very similar to Rspec
14
+ # (https://relishapp.com/rspec/rspec-core/v/3-9/docs/hooks/before-and-after-hooks).
15
+ class CallbackDsl
16
+ def initialize
17
+ @before_suite = []
18
+ @after_suite = []
19
+ @before_each = []
20
+ @after_each = []
21
+
22
+ freeze
23
+ end
24
+
25
+ # Used to create a before callback. This accepts and optional level
26
+ # parameter which can either be :suite or :each. ":each" is implied if no
27
+ # level is provided.
28
+ def before(level = LEVEL_EACH, &block)
29
+ verify_level!(level)
30
+
31
+ level == LEVEL_SUITE ? before_suite.push(block) : before_each.push(block)
32
+ end
33
+
34
+ # Used to create an after callback. This accepts and optional level
35
+ # parameter which can either be :suite or :each. ":each" is implied if no
36
+ # level is provided.
37
+ def after(level = LEVEL_EACH, &block)
38
+ verify_level!(level)
39
+
40
+ level == LEVEL_SUITE ? after_suite.push(block) : after_each.push(block)
41
+ end
42
+
43
+ # :nodoc:
44
+ def run_single_test_with_callbacks
45
+ before_each.each(&:call)
46
+
47
+ result = yield
48
+
49
+ after_each.each { |block| block.call(result) }
50
+
51
+ result
52
+ end
53
+
54
+ # :nodoc:
55
+ def run_suite_with_callbacks
56
+ before_suite.each(&:call)
57
+
58
+ result = yield
59
+
60
+ after_suite.each { |block| block.call(result) }
61
+
62
+ result
63
+ end
64
+
65
+ private
66
+
67
+ def verify_level!(level)
68
+ raise ArgumentError, "unknown test level: #{level}" unless CALLBACK_LEVELS.include?(level)
69
+ end
70
+
71
+ attr_reader :after_each, :before_each, :after_suite, :before_suite
72
+
73
+ LEVEL_EACH = :each
74
+ LEVEL_SUITE = :suite
75
+ CALLBACK_LEVELS = Set.new([LEVEL_EACH, LEVEL_SUITE])
76
+ private_constant :LEVEL_EACH, :LEVEL_SUITE, :CALLBACK_LEVELS
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,46 @@
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 'judge'
11
+ require_relative 'runner/result'
12
+
13
+ module Simmer
14
+ # :nodoc:
15
+ # Wraps a <tt>Simmer::Runner</tt> and knows how to re-run tests based
16
+ # on certain failure cases.
17
+ class ReRunner < SimpleDelegator
18
+ attr_reader :timeout_failure_retry_count
19
+
20
+ def initialize(runner, out, timeout_failure_retry_count: 0)
21
+ @timeout_failure_retry_count = timeout_failure_retry_count.to_i
22
+ @out = out
23
+
24
+ super(runner)
25
+ end
26
+
27
+ def run(*args)
28
+ rerun_on_timeout(args, timeout_failure_retry_count)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :out
34
+
35
+ def rerun_on_timeout(run_args, times)
36
+ result = __getobj__.run(*run_args)
37
+
38
+ if result.timed_out? && times.positive?
39
+ out.console_puts('Retrying due to a timeout...')
40
+ rerun_on_timeout(run_args, times - 1)
41
+ else
42
+ result
43
+ end
44
+ end
45
+ end
46
+ end
@@ -9,6 +9,7 @@
9
9
 
10
10
  require_relative 'judge'
11
11
  require_relative 'runner/result'
12
+ require_relative 'runner/timeout_error'
12
13
 
13
14
  module Simmer
14
15
  # Runs a single specification.
@@ -26,28 +27,24 @@ module Simmer
26
27
  freeze
27
28
  end
28
29
 
29
- def run(specification, config: {}, id: SecureRandom.uuid)
30
+ def run(specification, config:, id: SecureRandom.uuid)
30
31
  out.announce_start(id, specification)
31
- clean_and_seed(specification)
32
-
33
- spoon_client_result = execute_spoon(specification, config)
34
- judge_result = assert(specification, spoon_client_result)
35
-
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)
32
+
33
+ config.run_single_test_with_callbacks do
34
+ clean_and_seed(specification)
35
+
36
+ spoon_client_result = execute_spoon(specification, config)
37
+ judge_result = assert(specification, spoon_client_result)
38
+
39
+ Result.new(
40
+ id: id,
41
+ judge_result: judge_result,
42
+ specification: specification,
43
+ spoon_client_result: spoon_client_result
44
+ ).tap { |result| out.final_verdict(result) }
45
+ rescue Database::FixtureSet::FixtureMissingError, Simmer::Runner::TimeoutError => e
46
+ Result.new(id: id, specification: specification, errors: e)
47
+ .tap { |result| out.final_verdict(result) }
51
48
  end
52
49
  end
53
50
 
@@ -107,7 +104,7 @@ module Simmer
107
104
  def execute_spoon(specification, config)
108
105
  out.waiting('Act', 'Executing Spoon')
109
106
 
110
- spoon_client_result = spoon_client.run(specification, config) do |output|
107
+ spoon_client_result = spoon_client.run(specification, config.config) do |output|
111
108
  out.capture_spoon_output(output)
112
109
  end
113
110
 
@@ -117,7 +114,7 @@ module Simmer
117
114
  spoon_client_result
118
115
  rescue Timeout::Error => e
119
116
  out.console_puts('Timed out')
120
- raise e
117
+ raise Simmer::Runner::TimeoutError, e
121
118
  end
122
119
 
123
120
  def assert(specification, spoon_client_result)
@@ -44,11 +44,16 @@ module Simmer
44
44
  errors.empty?,
45
45
  ].all?
46
46
  end
47
+ alias passing? pass?
47
48
 
48
49
  def fail?
49
50
  !pass?
50
51
  end
51
52
 
53
+ def timed_out?
54
+ errors.any? { |e| e.is_a?(Simmer::Runner::TimeoutError) }
55
+ end
56
+
52
57
  def to_h
53
58
  {
54
59
  'name' => specification.name,
@@ -58,7 +63,7 @@ module Simmer
58
63
  'pass' => pass?,
59
64
  'spoon_client_result' => spoon_client_result.to_h,
60
65
  'judge_result' => judge_result.to_h,
61
- 'errors' => errors,
66
+ 'errors' => errors.map(&:message),
62
67
  }
63
68
  end
64
69
  end
@@ -0,0 +1,23 @@
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 Runner
12
+ # This error used when a specification times out. It is stored in
13
+ # <tt>Simmer::Runner::Results#errors</tt> when a specification times out.
14
+ class TimeoutError < RuntimeError
15
+ def message
16
+ cause ? cause.message : DEFAULT_MESSAGE
17
+ end
18
+
19
+ DEFAULT_MESSAGE = 'a timeout occurred'
20
+ private_constant :DEFAULT_MESSAGE
21
+ end
22
+ end
23
+ end
@@ -24,7 +24,7 @@ module Simmer
24
24
  results_dir:,
25
25
  runner:
26
26
  )
27
- @config = config || {}
27
+ @config = config
28
28
  @out = out
29
29
  @resolver = resolver
30
30
  @results_dir = results_dir
@@ -34,15 +34,17 @@ module Simmer
34
34
  end
35
35
 
36
36
  def run(specifications)
37
- runner_results = run_all_specs(specifications)
38
- runner.complete
37
+ config.run_suite_with_callbacks do
38
+ runner_results = run_all_specs(specifications)
39
+ runner.complete
39
40
 
40
- Result.new(runner_results).tap do |result|
41
- output_summary(result.pass?)
41
+ Result.new(runner_results).tap do |result|
42
+ output_summary(result.pass?)
42
43
 
43
- ResulstWriter.new(result, results_dir).write!
44
+ ResulstWriter.new(result, results_dir).write!
44
45
 
45
- out.puts("Results can be viewed at #{results_dir}")
46
+ out.puts("Results can be viewed at #{results_dir}")
47
+ end
46
48
  end
47
49
  end
48
50
 
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Simmer
11
- VERSION = '3.0.0'
11
+ VERSION = '4.0.0'
12
12
  end
@@ -43,4 +43,5 @@ Gem::Specification.new do |s|
43
43
  s.add_development_dependency('rubocop', '~>0.79.0')
44
44
  s.add_development_dependency('simplecov', '~>0.17.0')
45
45
  s.add_development_dependency('simplecov-console', '~>0.6.0')
46
+ s.add_development_dependency('terminal-notifier-guard')
46
47
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-06-10 00:00:00.000000000 Z
12
+ date: 2020-06-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: acts_as_hashable
@@ -207,6 +207,20 @@ dependencies:
207
207
  - - "~>"
208
208
  - !ruby/object:Gem::Version
209
209
  version: 0.6.0
210
+ - !ruby/object:Gem::Dependency
211
+ name: terminal-notifier-guard
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ type: :development
218
+ prerelease: false
219
+ version_requirements: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
210
224
  description: " Provides a harness for testing Pentaho Data Integration jobs and
211
225
  transformations.\n"
212
226
  email:
@@ -231,7 +245,9 @@ files:
231
245
  - bin/console
232
246
  - exe/simmer
233
247
  - lib/simmer.rb
248
+ - lib/simmer/bootstrap.rb
234
249
  - lib/simmer/configuration.rb
250
+ - lib/simmer/configuration/callback_dsl.rb
235
251
  - lib/simmer/core_ext/hash.rb
236
252
  - lib/simmer/database.rb
237
253
  - lib/simmer/database/fixture.rb
@@ -246,8 +262,10 @@ files:
246
262
  - lib/simmer/externals/sql_writers/sql_fixture.rb
247
263
  - lib/simmer/judge.rb
248
264
  - lib/simmer/judge/result.rb
265
+ - lib/simmer/re_runner.rb
249
266
  - lib/simmer/runner.rb
250
267
  - lib/simmer/runner/result.rb
268
+ - lib/simmer/runner/timeout_error.rb
251
269
  - lib/simmer/specification.rb
252
270
  - lib/simmer/specification/act.rb
253
271
  - lib/simmer/specification/act/params.rb