knapsack_pro 2.1.0 → 2.4.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: fccaa38fe31152f32d7cdd09f7b42eb7e487c7e1c277fb498dc36b13a3356bc4
4
- data.tar.gz: 8611e4cf6c14f3eb86c7b45a2c90df7e33c3500b6f30e86fd1ba596635585479
3
+ metadata.gz: be2eb19b6bc60ed03791ae1fd85b0893d85a42f96be0a584f7774174572e4982
4
+ data.tar.gz: e500f47322535c432f3cc89eed024708cf5e9e66162cecf3af5e6793d90a6794
5
5
  SHA512:
6
- metadata.gz: bd0174542079eab755f963314a17fe804cedce37366074fabc0e169547af7a89f27516f2c48e2052c21b2aa86d24703d17d19d40b8ac29eaacab51f030d51de6
7
- data.tar.gz: 21010bce7d72dc251d85b8d4d04949ceb8f2931eab99be18df2cbafa1479ff062f0e159b599b8b8bde9ef78f71400d2ce0b1724647509ded42018b952a0511ca
6
+ metadata.gz: 2303b72bfe98c25b1b7ec464f0632ce80ae20233457d990c0f92755fff63173bfad4da9dd2f9dc12873892c5157919cdd618d9b3999bef82f46242758bbc18b7
7
+ data.tar.gz: f3f49a0618a13876aaec016e3458a673a4a1ce7a6fb168f8f44409c10d00791a8e2e8c4c542f6c015951d4bcb17c2052e613dcbba69cf898f1d653818ce3eca1
@@ -1,5 +1,47 @@
1
1
  # Change Log
2
2
 
3
+ ### 2.4.0
4
+
5
+ * Update list of non encryptable branches
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/125
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.3.0...v2.4.0
10
+
11
+ ### 2.3.0
12
+
13
+ * When you use Regular Mode then try 6 attempts to connect to the API instead of 3 attempts
14
+
15
+ Add `KNAPSACK_PRO_MAX_REQUEST_RETRIES` environment variable to let user define their own number of request retries to the API. It is useful to set it to `0` for [forked repos](https://knapsackpro.com/faq/question/how-to-make-knapsack_pro-works-for-forked-repositories-of-my-project) when you want to rely on Fallback Mode.
16
+
17
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
18
+
19
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.2.1...v2.3.0
20
+
21
+ ### 2.2.1
22
+
23
+ * Improve detection of test file path in test-unit runner for test files with shared examples
24
+
25
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/123
26
+
27
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.2.0...v2.2.1
28
+
29
+ ### 2.2.0
30
+
31
+ * Allow defining Queue Mode hooks multiple times (`KnapsackPro::Hooks::Queue.before_queue`, `KnapsackPro::Hooks::Queue.after_subset_queue`, `KnapsackPro::Hooks::Queue.after_queue`)
32
+
33
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/122
34
+
35
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.1.1...v2.2.0
36
+
37
+ ### 2.1.1
38
+
39
+ * Explicitly call root test runner class to avoid a confusing error when test runner gem is not loaded
40
+
41
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/120
42
+
43
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v2.1.0...v2.1.1
44
+
3
45
  ### 2.1.0
4
46
 
5
47
  * Add `KNAPSACK_PRO_RSPEC_TEST_EXAMPLE_DETECTOR_PREFIX` to customize prefix for generating test examples report when using RSpec split by test examples
data/README.md CHANGED
@@ -627,7 +627,7 @@ If you will see error like:
627
627
  Don't know how to build task 'knapsack_pro:rspec_test_example_detector' (See the list of available tasks with `rake --tasks`)
628
628
  ```
629
629
 
630
- It probably means bundler can't find the rake task. You can try remove default prefix `bundle exec` used by knapsack_pro gem by setting `KNAPSACK_PRO_RSPEC_TEST_EXAMPLE_DETECTOR_PREFIX=""`.
630
+ It probably means bundler can't find the rake task. You can try to remove the default prefix `bundle exec` used by knapsack_pro gem by setting `KNAPSACK_PRO_RSPEC_TEST_EXAMPLE_DETECTOR_PREFIX=""`.
631
631
 
632
632
  ### How to manually define a list of slow test files to be split by test cases
633
633
 
@@ -2320,11 +2320,19 @@ There are a few ways to reproduce tests executed on CI node in your development
2320
2320
 
2321
2321
  ##### for knapsack_pro regular mode
2322
2322
 
2323
- knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds til it switch to fallback behavior and it will split test files across CI nodes based on popular test directory names. When knapsack_pro starts fallback mode then you will see a warning in the output.
2323
+ knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds till it switches to fallback behavior (Fallback Mode) and it will split test files across CI nodes based on popular test directory names. When knapsack_pro starts Fallback Mode then you will see a warning in the output.
2324
+
2325
+ Note there is an unlikely scenario when some of the CI nodes may start in Fallback Mode but others don't and then it could happen that some of test files might be skipped. You should [read this to learn more](https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124) and decide if you like to use Fallback Mode when running tests with knapsack_pro Regular Mode.
2326
+
2327
+ If your CI provider allows to retry only one of parallel CI nodes then please [read about this edge case as well](#required-ci-configuration-if-you-use-retry-single-failed-ci-node-feature-on-your-ci-server-when-knapsack_pro_fixed_queue_splittrue-in-queue-mode-or-knapsack_pro_fixed_test_suite_splittrue-in-regular-mode).
2324
2328
 
2325
2329
  ##### for knapsack_pro queue mode
2326
2330
 
2327
- knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds till it switches to fallback behavior and it will split test files across CI nodes based on popular test directory names. Note that if one of CI nodes will lose connection to Knapsack Pro API but other not then you may see that some of the test files will be executed on multiple CI nodes. Fallback mode guarantees each of test files is run at least once across CI nodes. Thanks to that we know if the whole test suite is green or not. When knapsack_pro starts fallback mode then you will see a warning in the output.
2331
+ knapsack_pro gem will retry requests to Knapsack Pro API multiple times every few seconds till it switches to fallback behavior (Fallback Mode) and it will split test files across CI nodes based on popular test directory names.
2332
+
2333
+ Note that if one of the CI nodes loses connection to Knapsack Pro API but others don't, then some of the test files may be executed on multiple CI nodes. **Fallback Mode guarantees each of the test files is run at least once across CI nodes when you use knapsack_pro in Queue Mode.** Thanks to that we know if the whole test suite is green or not. When knapsack_pro starts Fallback Mode then you will see a warning in the output.
2334
+
2335
+ If your CI provider allows to retry only one of parallel CI nodes then please [read about this edge case as well](#required-ci-configuration-if-you-use-retry-single-failed-ci-node-feature-on-your-ci-server-when-knapsack_pro_fixed_queue_splittrue-in-queue-mode-or-knapsack_pro_fixed_test_suite_splittrue-in-regular-mode).
2328
2336
 
2329
2337
  #### How can I change log level?
2330
2338
 
@@ -2464,12 +2472,13 @@ Below example is for rspec. You can change `$KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC
2464
2472
  if [ "$KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC" = "" ]; then
2465
2473
  KNAPSACK_PRO_ENDPOINT=https://api-disabled-for-fork.knapsackpro.com \
2466
2474
  KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC=disabled-for-fork \
2475
+ KNAPSACK_PRO_MAX_REQUEST_RETRIES=0 \
2467
2476
  bundle exec rake knapsack_pro:rspec # use Regular Mode here always
2468
2477
  else
2469
2478
  # Regular Mode
2470
2479
  bundle exec rake knapsack_pro:rspec
2471
2480
 
2472
- # You can use Queue Mode instead of Regular Mode if you like
2481
+ # or you can use Queue Mode instead of Regular Mode if you like
2473
2482
  # bundle exec rake knapsack_pro:queue:rspec
2474
2483
  fi
2475
2484
  ```
@@ -2737,6 +2746,8 @@ end
2737
2746
 
2738
2747
  #### What hooks are supported in Queue Mode?
2739
2748
 
2749
+ Note: Each hook type can be defined multiple times. For instance, if you define `KnapsackPro::Hooks::Queue.before_queue` twice then both block of code will be called when running your tests.
2750
+
2740
2751
  * RSpec in knapsack_pro Queue Mode supports hooks:
2741
2752
 
2742
2753
  ```ruby
@@ -4,7 +4,7 @@ module KnapsackPro
4
4
  TEST_DIR_PATTERN = 'features/**{,/*/**}/*.feature'
5
5
 
6
6
  def self.test_path(object)
7
- if Cucumber::VERSION.to_i >= 2
7
+ if ::Cucumber::VERSION.to_i >= 2
8
8
  test_case = object
9
9
  test_case.location.file
10
10
  else
@@ -85,10 +85,10 @@ module KnapsackPro
85
85
  private
86
86
 
87
87
  def add_post_run_callback(&block)
88
- if Minitest.respond_to?(:after_run)
89
- Minitest.after_run { block.call }
88
+ if ::Minitest.respond_to?(:after_run)
89
+ ::Minitest.after_run { block.call }
90
90
  else
91
- Minitest::Unit.after_tests { block.call }
91
+ ::Minitest::Unit.after_tests { block.call }
92
92
  end
93
93
  end
94
94
  end
@@ -4,7 +4,7 @@ module KnapsackPro
4
4
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
5
5
 
6
6
  def self.test_path(example_group)
7
- if defined?(Turnip) && Turnip::VERSION.to_i < 2
7
+ if defined?(::Turnip) && ::Turnip::VERSION.to_i < 2
8
8
  unless example_group[:turnip]
9
9
  until example_group[:parent_example_group].nil?
10
10
  example_group = example_group[:parent_example_group]
@@ -5,9 +5,29 @@ module KnapsackPro
5
5
  @@parent_of_test_dir = nil
6
6
 
7
7
  def self.test_path(obj)
8
- first_test = obj.tests.first
9
- method = first_test.method_name
10
- full_test_path = first_test.method(method).source_location.first
8
+ full_test_path = nil
9
+ found_valid_test_file_path = false
10
+
11
+ obj.tests.each do |test_obj|
12
+ method = test_obj.method_name
13
+ full_test_path = test_obj.method(method).source_location.first
14
+ # if we find a test file path that is a valid test file path within test suite directory
15
+ # then break to stop looking further.
16
+ # If we won't find a valid test file path then the last found path will be used as full_test_path
17
+ # For instance if test file contains only shared examples then it's not possible to properly detect test file path
18
+ # so the wrong path can be used like:
19
+ # /Users/artur/.rvm/gems/ruby-2.6.5/gems/shared_should-0.10.0/lib/shared_should/shared_context.rb
20
+ if full_test_path.include?(@@parent_of_test_dir)
21
+ found_valid_test_file_path = true
22
+ break
23
+ end
24
+ end
25
+
26
+ unless found_valid_test_file_path
27
+ KnapsackPro.logger.warn('cannot detect a valid test file path. Probably the test file contains only shared examples. Please add test cases to your test file. Read more at https://github.com/KnapsackPro/knapsack_pro-ruby/pull/123')
28
+ KnapsackPro.logger.warn("See test file for #{obj.inspect}")
29
+ end
30
+
11
31
  parent_of_test_dir_regexp = Regexp.new("^#{@@parent_of_test_dir}")
12
32
  test_path = full_test_path.gsub(parent_of_test_dir_regexp, '.')
13
33
  # test_path will look like ./test/dir/unit_test.rb
@@ -42,7 +62,7 @@ module KnapsackPro
42
62
  end
43
63
 
44
64
  def bind_time_tracker
45
- Test::Unit::TestSuite.send(:prepend, BindTimeTrackerTestUnitPlugin)
65
+ ::Test::Unit::TestSuite.send(:prepend, BindTimeTrackerTestUnitPlugin)
46
66
 
47
67
  add_post_run_callback do
48
68
  KnapsackPro.logger.debug(KnapsackPro::Presenter.global_time)
@@ -63,7 +83,7 @@ module KnapsackPro
63
83
  private
64
84
 
65
85
  def add_post_run_callback(&block)
66
- Test::Unit.at_exit do
86
+ ::Test::Unit.at_exit do
67
87
  block.call
68
88
  end
69
89
  end
@@ -34,7 +34,7 @@ module KnapsackPro
34
34
  test_files_to_run = all_test_files_to_run
35
35
 
36
36
  if adapter_class == KnapsackPro::Adapters::RSpecAdapter && KnapsackPro::Config::Env.rspec_split_by_test_examples?
37
- unless Gem::Version.new(RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
37
+ unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
38
38
  raise 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases'
39
39
  end
40
40
 
@@ -4,7 +4,6 @@ module KnapsackPro
4
4
  class ServerError < StandardError; end
5
5
 
6
6
  TIMEOUT = 15
7
- MAX_RETRY = -> { KnapsackPro::Config::Env.fallback_mode_enabled? ? 3 : 6 }
8
7
  REQUEST_RETRY_TIMEBOX = 8
9
8
 
10
9
  def initialize(action)
@@ -118,7 +117,7 @@ module KnapsackPro
118
117
  rescue ServerError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
119
118
  logger.warn(e.inspect)
120
119
  retries += 1
121
- if retries < MAX_RETRY.call
120
+ if retries < max_request_retries
122
121
  wait = retries * REQUEST_RETRY_TIMEBOX
123
122
  logger.warn("Wait #{wait}s and retry request to Knapsack Pro API.")
124
123
  print_every = 2 # seconds
@@ -156,6 +155,22 @@ module KnapsackPro
156
155
  http.get(uri, json_headers)
157
156
  end
158
157
  end
158
+
159
+ def max_request_retries
160
+ # when user defined max request retries
161
+ return KnapsackPro::Config::Env.max_request_retries if KnapsackPro::Config::Env.max_request_retries
162
+
163
+ # when Fallback Mode is disabled then try more attempts to connect to the API
164
+ return 6 unless KnapsackPro::Config::Env.fallback_mode_enabled?
165
+
166
+ # when Regular Mode then try more attempts to connect to the API
167
+ # if only one CI node starts Fallback Mode instead of all then we can't guarantee all test files will be run
168
+ # https://github.com/KnapsackPro/knapsack_pro-ruby/pull/124
169
+ return 6 if KnapsackPro::Config::Env.regular_mode?
170
+
171
+ # default number of attempts
172
+ 3
173
+ end
159
174
  end
160
175
  end
161
176
  end
@@ -36,6 +36,13 @@ module KnapsackPro
36
36
  ).to_i
37
37
  end
38
38
 
39
+ def max_request_retries
40
+ number = ENV['KNAPSACK_PRO_MAX_REQUEST_RETRIES']
41
+ if number
42
+ number.to_i
43
+ end
44
+ end
45
+
39
46
  def commit_hash
40
47
  ENV['KNAPSACK_PRO_COMMIT_HASH'] ||
41
48
  ci_env_for(:commit_hash)
@@ -83,6 +90,10 @@ module KnapsackPro
83
90
  recording_enabled == 'true'
84
91
  end
85
92
 
93
+ def regular_mode?
94
+ recording_enabled?
95
+ end
96
+
86
97
  def queue_recording_enabled
87
98
  ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED']
88
99
  end
@@ -1,7 +1,21 @@
1
1
  module KnapsackPro
2
2
  module Crypto
3
3
  class BranchEncryptor
4
- NON_ENCRYPTABLE_BRANCHES = %w(develop development dev master staging)
4
+ NON_ENCRYPTABLE_BRANCHES = [
5
+ 'master',
6
+ 'main',
7
+ 'develop',
8
+ 'development',
9
+ 'dev',
10
+ 'staging',
11
+ # GitHub Actions has branch names starting with refs/heads/
12
+ 'refs/heads/master',
13
+ 'refs/heads/main',
14
+ 'refs/heads/develop',
15
+ 'refs/heads/development',
16
+ 'refs/heads/dev',
17
+ 'refs/heads/staging',
18
+ ]
5
19
 
6
20
  def self.call(branch)
7
21
  if KnapsackPro::Config::Env.branch_encrypted?
@@ -3,8 +3,8 @@ RSpec::Support.require_rspec_core('formatters/json_formatter')
3
3
  # based on https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/formatters/json_formatter.rb
4
4
  module KnapsackPro
5
5
  module Formatters
6
- class RSpecJsonFormatter < RSpec::Core::Formatters::JsonFormatter
7
- RSpec::Core::Formatters.register self
6
+ class RSpecJsonFormatter < ::RSpec::Core::Formatters::JsonFormatter
7
+ ::RSpec::Core::Formatters.register self
8
8
 
9
9
  private
10
10
 
@@ -5,7 +5,7 @@ module KnapsackPro
5
5
  module RSpecQueueProfileFormatterExtension
6
6
  def self.print_summary
7
7
  return unless KnapsackPro::Config::Env.modify_default_rspec_formatters?
8
- RSpec::Core::Formatters::ProfileFormatter.print_profile_summary
8
+ ::RSpec::Core::Formatters::ProfileFormatter.print_profile_summary
9
9
  end
10
10
 
11
11
  def initialize(output)
@@ -9,8 +9,8 @@ module KnapsackPro
9
9
  def dump_summary(summary); end
10
10
  end
11
11
 
12
- class RSpecQueueSummaryFormatter < RSpec::Core::Formatters::BaseFormatter
13
- RSpec::Core::Formatters.register self, :dump_summary, :dump_failures, :dump_pending
12
+ class RSpecQueueSummaryFormatter < ::RSpec::Core::Formatters::BaseFormatter
13
+ ::RSpec::Core::Formatters.register self, :dump_summary, :dump_failures, :dump_pending
14
14
 
15
15
  def self.registered_output=(output)
16
16
  @registered_output = {
@@ -2,54 +2,63 @@ module KnapsackPro
2
2
  module Hooks
3
3
  class Queue
4
4
  class << self
5
- attr_reader :before_queue,
6
- :after_subset_queue,
7
- :after_queue
5
+ attr_reader :before_queue_store,
6
+ :after_subset_queue_store,
7
+ :after_queue_store
8
8
 
9
9
  def reset_before_queue
10
- @before_queue = nil
10
+ @before_queue_store = nil
11
11
  end
12
12
 
13
13
  def reset_after_subset_queue
14
- @after_subset_queue = nil
14
+ @after_subset_queue_store = nil
15
15
  end
16
16
 
17
17
  def reset_after_queue
18
- @after_queue = nil
18
+ @after_queue_store = nil
19
19
  end
20
20
 
21
21
  def before_queue(&block)
22
- @before_queue ||= block
22
+ @before_queue_store ||= []
23
+ @before_queue_store << block
23
24
  end
24
25
 
25
26
  def after_subset_queue(&block)
26
- @after_subset_queue ||= block
27
+ @after_subset_queue_store ||= []
28
+ @after_subset_queue_store << block
27
29
  end
28
30
 
29
31
  def after_queue(&block)
30
- @after_queue ||= block
32
+ @after_queue_store ||= []
33
+ @after_queue_store << block
31
34
  end
32
35
 
33
36
  def call_before_queue
34
- return unless before_queue
35
- before_queue.call(
36
- KnapsackPro::Config::Env.queue_id
37
- )
37
+ return unless before_queue_store
38
+ before_queue_store.each do |block|
39
+ block.call(
40
+ KnapsackPro::Config::Env.queue_id
41
+ )
42
+ end
38
43
  end
39
44
 
40
45
  def call_after_subset_queue
41
- return unless after_subset_queue
42
- after_subset_queue.call(
43
- KnapsackPro::Config::Env.queue_id,
44
- KnapsackPro::Config::Env.subset_queue_id
45
- )
46
+ return unless after_subset_queue_store
47
+ after_subset_queue_store.each do |block|
48
+ block.call(
49
+ KnapsackPro::Config::Env.queue_id,
50
+ KnapsackPro::Config::Env.subset_queue_id
51
+ )
52
+ end
46
53
  end
47
54
 
48
55
  def call_after_queue
49
- return unless after_queue
50
- after_queue.call(
51
- KnapsackPro::Config::Env.queue_id
52
- )
56
+ return unless after_queue_store
57
+ after_queue_store.each do |block|
58
+ block.call(
59
+ KnapsackPro::Config::Env.queue_id
60
+ )
61
+ end
53
62
  end
54
63
  end
55
64
  end
@@ -15,7 +15,7 @@ module KnapsackPro
15
15
  Rake::Task[task_name].clear
16
16
  end
17
17
 
18
- Cucumber::Rake::Task.new(task_name) do |t|
18
+ ::Cucumber::Rake::Task.new(task_name) do |t|
19
19
  t.cucumber_opts = "#{args} --require #{runner.test_dir} -- #{runner.stringify_test_file_paths}"
20
20
  end
21
21
  Rake::Task[task_name].invoke
@@ -89,9 +89,9 @@ module KnapsackPro
89
89
  end
90
90
 
91
91
  # duplicate args because Minitest modifies args
92
- result = Minitest.run(args.dup)
92
+ result = ::Minitest.run(args.dup)
93
93
 
94
- Minitest::Runnable.reset
94
+ ::Minitest::Runnable.reset
95
95
 
96
96
  result
97
97
  end
@@ -79,8 +79,8 @@ module KnapsackPro
79
79
 
80
80
  log_rspec_command(args, test_file_paths, :subset_queue)
81
81
 
82
- options = RSpec::Core::ConfigurationOptions.new(cli_args)
83
- exit_code = RSpec::Core::Runner.new(options).run($stderr, $stdout)
82
+ options = ::RSpec::Core::ConfigurationOptions.new(cli_args)
83
+ exit_code = ::RSpec::Core::Runner.new(options).run($stderr, $stdout)
84
84
  exitstatus = exit_code if exit_code != 0
85
85
 
86
86
  rspec_clear_examples
@@ -124,26 +124,26 @@ module KnapsackPro
124
124
  #
125
125
  # Keep formatters and report to accumulate info about failed/pending tests
126
126
  def self.rspec_clear_examples
127
- if RSpec::ExampleGroups.respond_to?(:remove_all_constants)
128
- RSpec::ExampleGroups.remove_all_constants
127
+ if ::RSpec::ExampleGroups.respond_to?(:remove_all_constants)
128
+ ::RSpec::ExampleGroups.remove_all_constants
129
129
  else
130
- RSpec::ExampleGroups.constants.each do |constant|
131
- RSpec::ExampleGroups.__send__(:remove_const, constant)
130
+ ::RSpec::ExampleGroups.constants.each do |constant|
131
+ ::RSpec::ExampleGroups.__send__(:remove_const, constant)
132
132
  end
133
133
  end
134
- RSpec.world.example_groups.clear
135
- RSpec.configuration.start_time = ::RSpec::Core::Time.now
134
+ ::RSpec.world.example_groups.clear
135
+ ::RSpec.configuration.start_time = ::RSpec::Core::Time.now
136
136
 
137
137
  if KnapsackPro::Config::Env.rspec_split_by_test_examples?
138
138
  # Reset example group counts to ensure scoped example ids in metadata
139
139
  # have correct index (not increased by each subsequent run).
140
140
  # Solves this problem: https://github.com/rspec/rspec-core/issues/2721
141
- RSpec.world.instance_variable_set(:@example_group_counts_by_spec_file, Hash.new(0))
141
+ ::RSpec.world.instance_variable_set(:@example_group_counts_by_spec_file, Hash.new(0))
142
142
  end
143
143
 
144
144
  # skip reset filters for old RSpec versions
145
- if RSpec.configuration.respond_to?(:reset_filters)
146
- RSpec.configuration.reset_filters
145
+ if ::RSpec.configuration.respond_to?(:reset_filters)
146
+ ::RSpec.configuration.reset_filters
147
147
  end
148
148
  end
149
149
  end
@@ -15,7 +15,7 @@ module KnapsackPro
15
15
  Rake::Task[task_name].clear
16
16
  end
17
17
 
18
- RSpec::Core::RakeTask.new(task_name) do |t|
18
+ ::RSpec::Core::RakeTask.new(task_name) do |t|
19
19
  # we cannot pass runner.test_file_paths array to t.pattern
20
20
  # because pattern does not accept test example path like spec/a_spec.rb[1:2]
21
21
  # instead we pass test files and test example paths to t.rspec_opts
@@ -16,7 +16,7 @@ module KnapsackPro
16
16
  File.expand_path(f)
17
17
  end
18
18
 
19
- exit Test::Unit::AutoRunner.run(
19
+ exit ::Test::Unit::AutoRunner.run(
20
20
  true,
21
21
  runner.test_dir,
22
22
  cli_args
@@ -7,7 +7,7 @@ module KnapsackPro
7
7
  require 'rspec/core'
8
8
 
9
9
  cli_format =
10
- if Gem::Version.new(RSpec::Core::Version::STRING) < Gem::Version.new('3.6.0')
10
+ if Gem::Version.new(::RSpec::Core::Version::STRING) < Gem::Version.new('3.6.0')
11
11
  require_relative '../formatters/rspec_json_formatter'
12
12
  ['--format', KnapsackPro::Formatters::RSpecJsonFormatter.to_s]
13
13
  else
@@ -30,8 +30,8 @@ module KnapsackPro
30
30
  '--out', report_path,
31
31
  '--default-path', test_dir,
32
32
  ] + KnapsackPro::TestFilePresenter.paths(test_file_entities)
33
- options = RSpec::Core::ConfigurationOptions.new(cli_args)
34
- exit_code = RSpec::Core::Runner.new(options).run($stderr, $stdout)
33
+ options = ::RSpec::Core::ConfigurationOptions.new(cli_args)
34
+ exit_code = ::RSpec::Core::Runner.new(options).run($stderr, $stdout)
35
35
  if exit_code != 0
36
36
  raise 'There was problem to generate test examples for test suite'
37
37
  end
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '2.1.0'
2
+ VERSION = '2.4.0'
3
3
  end
@@ -10,8 +10,7 @@ describe KnapsackPro::Adapters::TestUnitAdapter do
10
10
 
11
11
  before do
12
12
  parent_of_test_dir = File.expand_path('../../../', File.dirname(__FILE__))
13
- parent_of_test_dir_regexp = Regexp.new("^#{parent_of_test_dir}")
14
- described_class.class_variable_set(:@@parent_of_test_dir, parent_of_test_dir_regexp)
13
+ described_class.class_variable_set(:@@parent_of_test_dir, parent_of_test_dir)
15
14
  end
16
15
 
17
16
  context 'when regular test' do
@@ -108,6 +108,53 @@ shared_examples 'when retry request' do
108
108
  expect(connection.errors?).to be true
109
109
  end
110
110
 
111
+ context 'when max request retries defined' do
112
+ before do
113
+ expect(KnapsackPro::Config::Env).to receive(:max_request_retries).at_least(1).and_return(4)
114
+ end
115
+
116
+ it do
117
+ expect(logger).to receive(:debug).exactly(4).with("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
118
+ expect(logger).to receive(:debug).exactly(4).with('API request UUID: fake-uuid')
119
+ expect(logger).to receive(:debug).exactly(4).with('API response:')
120
+
121
+ parsed_response = { 'error' => 'Internal Server Error' }
122
+
123
+ expect(logger).to receive(:error).exactly(4).with(parsed_response)
124
+
125
+ server_error = described_class::ServerError.new(parsed_response)
126
+ expect(logger).to receive(:warn).exactly(4).with(server_error.inspect)
127
+
128
+ expect(logger).to receive(:warn).with("Wait 8s and retry request to Knapsack Pro API.")
129
+ expect(logger).to receive(:warn).with("Next request in 8s...")
130
+ expect(logger).to receive(:warn).with("Next request in 6s...")
131
+ expect(logger).to receive(:warn).with("Next request in 4s...")
132
+ expect(logger).to receive(:warn).with("Next request in 2s...")
133
+
134
+ expect(logger).to receive(:warn).with("Wait 16s and retry request to Knapsack Pro API.")
135
+ expect(logger).to receive(:warn).with("Next request in 16s...")
136
+ expect(logger).to receive(:warn).with("Next request in 14s...")
137
+ expect(logger).to receive(:warn).with("Next request in 12s...")
138
+ expect(logger).to receive(:warn).with("Next request in 10s...")
139
+ expect(logger).to receive(:warn).with("Next request in 8s...")
140
+ expect(logger).to receive(:warn).with("Next request in 6s...")
141
+ expect(logger).to receive(:warn).with("Next request in 4s...")
142
+ expect(logger).to receive(:warn).with("Next request in 2s...")
143
+
144
+ expect(logger).to receive(:warn).with("Wait 24s and retry request to Knapsack Pro API.")
145
+ 12.times do |i|
146
+ expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
147
+ end
148
+
149
+ expect(Kernel).to receive(:sleep).exactly(4+8+12).with(2)
150
+
151
+ expect(subject).to eq(parsed_response)
152
+
153
+ expect(connection.success?).to be false
154
+ expect(connection.errors?).to be true
155
+ end
156
+ end
157
+
111
158
  context 'when Fallback Mode is disabled' do
112
159
  before do
113
160
  expect(KnapsackPro::Config::Env).to receive(:fallback_mode_enabled?).at_least(1).and_return(false)
@@ -164,6 +211,63 @@ shared_examples 'when retry request' do
164
211
  expect(connection.errors?).to be true
165
212
  end
166
213
  end
214
+
215
+ context 'when Regular Mode' do
216
+ before do
217
+ expect(KnapsackPro::Config::Env).to receive(:regular_mode?).at_least(1).and_return(true)
218
+ end
219
+
220
+ it do
221
+ expect(logger).to receive(:debug).exactly(6).with("#{expected_http_method} http://api.knapsackpro.test:3000/v1/fake_endpoint")
222
+ expect(logger).to receive(:debug).exactly(6).with('API request UUID: fake-uuid')
223
+ expect(logger).to receive(:debug).exactly(6).with('API response:')
224
+
225
+ parsed_response = { 'error' => 'Internal Server Error' }
226
+
227
+ expect(logger).to receive(:error).exactly(6).with(parsed_response)
228
+
229
+ server_error = described_class::ServerError.new(parsed_response)
230
+ expect(logger).to receive(:warn).exactly(6).with(server_error.inspect)
231
+
232
+ expect(logger).to receive(:warn).with("Wait 8s and retry request to Knapsack Pro API.")
233
+ expect(logger).to receive(:warn).with("Next request in 8s...")
234
+ expect(logger).to receive(:warn).with("Next request in 6s...")
235
+ expect(logger).to receive(:warn).with("Next request in 4s...")
236
+ expect(logger).to receive(:warn).with("Next request in 2s...")
237
+
238
+ expect(logger).to receive(:warn).with("Wait 16s and retry request to Knapsack Pro API.")
239
+ expect(logger).to receive(:warn).with("Next request in 16s...")
240
+ expect(logger).to receive(:warn).with("Next request in 14s...")
241
+ expect(logger).to receive(:warn).with("Next request in 12s...")
242
+ expect(logger).to receive(:warn).with("Next request in 10s...")
243
+ expect(logger).to receive(:warn).with("Next request in 8s...")
244
+ expect(logger).to receive(:warn).with("Next request in 6s...")
245
+ expect(logger).to receive(:warn).with("Next request in 4s...")
246
+ expect(logger).to receive(:warn).with("Next request in 2s...")
247
+
248
+ expect(logger).to receive(:warn).with("Wait 24s and retry request to Knapsack Pro API.")
249
+ 12.times do |i|
250
+ expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
251
+ end
252
+
253
+ expect(logger).to receive(:warn).with("Wait 32s and retry request to Knapsack Pro API.")
254
+ 16.times do |i|
255
+ expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
256
+ end
257
+
258
+ expect(logger).to receive(:warn).with("Wait 40s and retry request to Knapsack Pro API.")
259
+ 20.times do |i|
260
+ expect(logger).to receive(:warn).with("Next request in #{(i+1)*2}s...")
261
+ end
262
+
263
+ expect(Kernel).to receive(:sleep).exactly(60).with(2)
264
+
265
+ expect(subject).to eq(parsed_response)
266
+
267
+ expect(connection.success?).to be false
268
+ expect(connection.errors?).to be true
269
+ end
270
+ end
167
271
  end
168
272
  end
169
273
 
@@ -100,6 +100,19 @@ describe KnapsackPro::Config::Env do
100
100
  end
101
101
  end
102
102
 
103
+ describe '.max_request_retries' do
104
+ subject { described_class.max_request_retries }
105
+
106
+ context 'when ENV exists' do
107
+ before { stub_const("ENV", { 'KNAPSACK_PRO_MAX_REQUEST_RETRIES' => '2' }) }
108
+ it { should eq 2 }
109
+ end
110
+
111
+ context "when ENV doesn't exist" do
112
+ it { should be_nil }
113
+ end
114
+ end
115
+
103
116
  describe '.commit_hash' do
104
117
  subject { described_class.commit_hash }
105
118
 
@@ -267,6 +280,25 @@ describe KnapsackPro::Config::Env do
267
280
  end
268
281
  end
269
282
 
283
+
284
+ describe '.regular_mode?' do
285
+ subject { described_class.regular_mode? }
286
+
287
+ before do
288
+ expect(described_class).to receive(:recording_enabled?).and_return(recording_enabled)
289
+ end
290
+
291
+ context 'when recording is enabled' do
292
+ let(:recording_enabled) { true }
293
+ it { should be true }
294
+ end
295
+
296
+ context 'when recording is not enabled' do
297
+ let(:recording_enabled) { false }
298
+ it { should be false }
299
+ end
300
+ end
301
+
270
302
  describe '.recording_enabled?' do
271
303
  subject { described_class.recording_enabled? }
272
304
 
@@ -10,18 +10,30 @@ describe KnapsackPro::Hooks::Queue do
10
10
  it { should be_nil }
11
11
  end
12
12
 
13
- context 'when callback is set' do
13
+ context 'when callback is set multiple times' do
14
14
  let(:queue_id) { double }
15
15
 
16
16
  before do
17
- expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
17
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
18
18
 
19
+ $expected_called_blocks = []
20
+
21
+ described_class.before_queue do |q_id|
22
+ $expected_called_blocks << [:block_1_called, q_id]
23
+ end
19
24
  described_class.before_queue do |q_id|
20
- [:fake_value, q_id]
25
+ $expected_called_blocks << [:block_2_called, q_id]
21
26
  end
22
27
  end
23
28
 
24
- it { should eq [:fake_value, queue_id] }
29
+ it 'each block is called' do
30
+ subject
31
+
32
+ expect($expected_called_blocks).to eq([
33
+ [:block_1_called, queue_id],
34
+ [:block_2_called, queue_id],
35
+ ])
36
+ end
25
37
  end
26
38
  end
27
39
 
@@ -36,20 +48,32 @@ describe KnapsackPro::Hooks::Queue do
36
48
  it { should be_nil }
37
49
  end
38
50
 
39
- context 'when callback is set' do
51
+ context 'when callback is set multiple times' do
40
52
  let(:queue_id) { double }
41
53
  let(:subset_queue_id) { double }
42
54
 
43
55
  before do
44
- expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
45
- expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).and_return(subset_queue_id)
56
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
57
+ expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).twice.and_return(subset_queue_id)
58
+
59
+ $expected_called_blocks = []
46
60
 
47
61
  described_class.after_subset_queue do |q_id, subset_q_id|
48
- [:fake_value, q_id, subset_q_id]
62
+ $expected_called_blocks << [:block_1_called, q_id, subset_q_id]
63
+ end
64
+ described_class.after_subset_queue do |q_id, subset_q_id|
65
+ $expected_called_blocks << [:block_2_called, q_id, subset_q_id]
49
66
  end
50
67
  end
51
68
 
52
- it { should eq [:fake_value, queue_id, subset_queue_id] }
69
+ it 'each block is called' do
70
+ subject
71
+
72
+ expect($expected_called_blocks).to eq([
73
+ [:block_1_called, queue_id, subset_queue_id],
74
+ [:block_2_called, queue_id, subset_queue_id],
75
+ ])
76
+ end
53
77
  end
54
78
  end
55
79
 
@@ -64,18 +88,30 @@ describe KnapsackPro::Hooks::Queue do
64
88
  it { should be_nil }
65
89
  end
66
90
 
67
- context 'when callback is set' do
91
+ context 'when callback is set multiple times' do
68
92
  let(:queue_id) { double }
69
93
 
70
94
  before do
71
- expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
95
+ expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
96
+
97
+ $expected_called_blocks = []
72
98
 
73
99
  described_class.after_queue do |q_id|
74
- [:fake_value, q_id]
100
+ $expected_called_blocks << [:block_1_called, q_id]
101
+ end
102
+ described_class.after_queue do |q_id|
103
+ $expected_called_blocks << [:block_2_called, q_id]
75
104
  end
76
105
  end
77
106
 
78
- it { should eq [:fake_value, queue_id] }
107
+ it 'each block is called' do
108
+ subject
109
+
110
+ expect($expected_called_blocks).to eq([
111
+ [:block_1_called, queue_id],
112
+ [:block_2_called, queue_id],
113
+ ])
114
+ end
79
115
  end
80
116
  end
81
117
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack_pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-17 00:00:00.000000000 Z
11
+ date: 2020-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake