knapsack_pro 3.0.0 → 3.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +1 -1
- data/.gitignore +1 -0
- data/CHANGELOG.md +32 -0
- data/README.md +5 -0
- data/lib/knapsack_pro/adapters/base_adapter.rb +4 -4
- data/lib/knapsack_pro/client/connection.rb +1 -1
- data/lib/knapsack_pro/config/env.rb +0 -1
- data/lib/knapsack_pro/config/temp_files.rb +38 -0
- data/lib/knapsack_pro/report.rb +7 -8
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +2 -2
- data/lib/knapsack_pro/slow_test_file_determiner.rb +10 -5
- data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +9 -6
- data/lib/knapsack_pro/tracker.rb +4 -2
- data/lib/knapsack_pro/version.rb +1 -1
- data/lib/knapsack_pro.rb +1 -0
- data/spec/knapsack_pro/adapters/base_adapter_spec.rb +9 -7
- data/spec/knapsack_pro/config/temp_files_spec.rb +25 -0
- data/spec/knapsack_pro/report_spec.rb +11 -10
- data/spec/knapsack_pro/slow_test_file_determiner_spec.rb +34 -17
- data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +8 -6
- data/spec/spec_helper.rb +5 -2
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4fec041f1d838c8672e70c4a3703a2adfd3d727c912b2543c88c3cf01fe9ae65
|
4
|
+
data.tar.gz: 789349de506fcc48e3e76a881f9f87205544792c8d49243e4f20342c01627b01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b28ea456bda112b8c2329a4728b82fa5d3363a883d090a10066023bf246f6f12f98c573f62cefc3d791aacca27f18a37cfc294ddd61b6b5f43af4027e4818e16
|
7
|
+
data.tar.gz: 90ee101ba4dc5a01e13960fe1fd469259b3242b0b0daeccfbc38300c20a3b0d7bf9f3849be6ffc8ebd649705838549a06519e031c13ba4c0896d0f019b3e255c
|
data/.circleci/config.yml
CHANGED
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 3.1.3
|
4
|
+
|
5
|
+
* Run Fallback Mode when `Errno::ECONNRESET` exception happens
|
6
|
+
|
7
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/164
|
8
|
+
|
9
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.1.2...v3.1.3
|
10
|
+
|
11
|
+
### 3.1.2
|
12
|
+
|
13
|
+
* Fix bug when test files have no recorded time execution then they should not be detected as slow test files for RSpec split by test examples feature
|
14
|
+
|
15
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/163
|
16
|
+
|
17
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.1.1...v3.1.2
|
18
|
+
|
19
|
+
### 3.1.1
|
20
|
+
|
21
|
+
* Rephrase log outputs in the Queue Mode RSpec runner
|
22
|
+
|
23
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/160
|
24
|
+
|
25
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.1.0...v3.1.1
|
26
|
+
|
27
|
+
### 3.1.0
|
28
|
+
|
29
|
+
* Use `.knapsack_pro` directory for temporary files instead of the `tmp` directory in the user's project directory
|
30
|
+
|
31
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/155
|
32
|
+
|
33
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v3.0.0...v3.1.0
|
34
|
+
|
3
35
|
### 3.0.0
|
4
36
|
|
5
37
|
* __(breaking change)__ Remove support for RSpec 2.x. This change was already done by accident in [the pull request](https://github.com/KnapsackPro/knapsack_pro-ruby/pull/143) when we added the RSpec `context` hook, which is available only since RSpec 3.x.
|
data/README.md
CHANGED
@@ -1714,6 +1714,11 @@ $ gem push knapsack_pro-X.X.X.gem
|
|
1714
1714
|
|
1715
1715
|
Update the latest available gem version in `TestSuiteClientVersionChecker` for the Knapsack Pro API repository.
|
1716
1716
|
|
1717
|
+
Update knapsack_pro gem version in:
|
1718
|
+
|
1719
|
+
* https://github.com/KnapsackPro/rails-app-with-knapsack_pro
|
1720
|
+
* our private Knapsack Pro API repository
|
1721
|
+
|
1717
1722
|
## Mentions
|
1718
1723
|
|
1719
1724
|
List of articles where people mentioned Knapsack Pro:
|
@@ -6,7 +6,7 @@ module KnapsackPro
|
|
6
6
|
|
7
7
|
def self.adapter_bind_method_called_file
|
8
8
|
adapter_name = self.to_s.gsub('::', '-')
|
9
|
-
"#{KnapsackPro::Config::
|
9
|
+
"#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/#{adapter_name}-bind_method_called_for_node_#{KnapsackPro::Config::Env.ci_node_index}.txt"
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.slow_test_file?(adapter_class, test_file_path)
|
@@ -33,20 +33,20 @@ module KnapsackPro
|
|
33
33
|
|
34
34
|
def self.verify_bind_method_called
|
35
35
|
::Kernel.at_exit do
|
36
|
-
if File.
|
36
|
+
if File.exist?(adapter_bind_method_called_file)
|
37
37
|
File.delete(adapter_bind_method_called_file)
|
38
38
|
else
|
39
39
|
puts "\n\n"
|
40
40
|
KnapsackPro.logger.error('-'*10 + ' Configuration error ' + '-'*50)
|
41
41
|
KnapsackPro.logger.error("You forgot to call #{self}.bind method in your test runner configuration file. It is needed to record test files time execution. Please follow the installation guide to configure your project properly https://docs.knapsackpro.com/knapsack_pro-ruby/guide/")
|
42
|
-
KnapsackPro.logger.error("If you already have #{self}.bind method added and you still see this error then one of your tests must
|
42
|
+
KnapsackPro.logger.error("If you already have #{self}.bind method added and you still see this error then one of your tests must have deleted the .knapsack_pro directory from the disk accidentally. Please ensure you do not remove the .knapsack_pro directory: https://knapsackpro.com/faq/question/why-all-test-files-have-01s-time-execution-for-my-ci-build-in-user-dashboard")
|
43
43
|
Kernel.exit(1)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
def bind
|
49
|
-
|
49
|
+
KnapsackPro::Config::TempFiles.ensure_temp_directory_exists!
|
50
50
|
File.write(self.class.adapter_bind_method_called_file, nil)
|
51
51
|
|
52
52
|
if KnapsackPro::Config::Env.recording_enabled?
|
@@ -119,7 +119,7 @@ module KnapsackPro
|
|
119
119
|
end
|
120
120
|
|
121
121
|
response_body
|
122
|
-
rescue ServerError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
|
122
|
+
rescue ServerError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
|
123
123
|
logger.warn("#{action.http_method.to_s.upcase} #{endpoint_url}")
|
124
124
|
logger.warn('Request failed due to:')
|
125
125
|
logger.warn(e.inspect)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module KnapsackPro
|
2
|
+
module Config
|
3
|
+
class TempFiles
|
4
|
+
# relative to the directory where you run knapsack_pro gem (user's project)
|
5
|
+
TEMP_DIRECTORY_PATH = '.knapsack_pro'
|
6
|
+
|
7
|
+
def self.ensure_temp_directory_exists!
|
8
|
+
unless File.exist?(gitignore_file_path)
|
9
|
+
create_temp_directory!
|
10
|
+
create_gitignore_file!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def self.create_temp_directory!
|
17
|
+
FileUtils.mkdir_p(TEMP_DIRECTORY_PATH)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.gitignore_file_path
|
21
|
+
File.join(TEMP_DIRECTORY_PATH, '.gitignore')
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.gitignore_file_content
|
25
|
+
"# This directory is used by knapsack_pro gem for storing temporary files during tests runtime.\n" <<
|
26
|
+
"# Ignore all files, and do not commit this directory into your repository.\n" <<
|
27
|
+
"# Learn more at https://knapsackpro.com\n" <<
|
28
|
+
"*"
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create_gitignore_file!
|
32
|
+
File.open(gitignore_file_path, 'w+') do |f|
|
33
|
+
f.write(gitignore_file_content)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/knapsack_pro/report.rb
CHANGED
@@ -5,7 +5,7 @@ module KnapsackPro
|
|
5
5
|
|
6
6
|
if test_files.empty?
|
7
7
|
KnapsackPro.logger.warn("No test files were executed on this CI node.")
|
8
|
-
KnapsackPro.logger.debug("When you use knapsack_pro
|
8
|
+
KnapsackPro.logger.debug("When you use knapsack_pro Regular Mode, the reason for no tests executing might be a very narrow tests list. Most likely, you run only tests with a specified tag, and there were fewer test files with the tag than parallel CI nodes.")
|
9
9
|
end
|
10
10
|
|
11
11
|
create_build_subset(test_files)
|
@@ -16,6 +16,7 @@ module KnapsackPro
|
|
16
16
|
|
17
17
|
subset_queue_id = KnapsackPro::Config::Env.subset_queue_id
|
18
18
|
|
19
|
+
KnapsackPro::Config::TempFiles.ensure_temp_directory_exists!
|
19
20
|
FileUtils.mkdir_p(queue_path)
|
20
21
|
|
21
22
|
subset_queue_file_name = "#{subset_queue_id}.json"
|
@@ -36,8 +37,7 @@ module KnapsackPro
|
|
36
37
|
|
37
38
|
if test_files.empty?
|
38
39
|
KnapsackPro.logger.warn("No test files were executed on this CI node.")
|
39
|
-
KnapsackPro.logger.debug("
|
40
|
-
KnapsackPro.logger.debug("Another reason might be when your CI node failed in a way that prevented knapsack_pro to save time execution data to Knapsack Pro API and you have just tried to retry failed CI node but instead you got no test files to execute. In that case knapsack_pro don't know what tests should be executed here.")
|
40
|
+
KnapsackPro.logger.debug("This CI node likely started work late after the test files were already executed by other CI nodes consuming the queue.")
|
41
41
|
end
|
42
42
|
|
43
43
|
measured_test_files = test_files
|
@@ -46,9 +46,9 @@ module KnapsackPro
|
|
46
46
|
|
47
47
|
if test_files.size > 0 && measured_test_files.size == 0
|
48
48
|
KnapsackPro.logger.warn("#{test_files.size} test files were executed on this CI node but the recorded time was lost due to:")
|
49
|
-
KnapsackPro.logger.warn("1.
|
50
|
-
KnapsackPro.logger.warn("2.
|
51
|
-
KnapsackPro.logger.warn("3.
|
49
|
+
KnapsackPro.logger.warn("1. Please ensure you do not remove the contents of the .knapsack_pro directory between tests run.")
|
50
|
+
KnapsackPro.logger.warn("2. Ensure you've added Knapsack::Adapters::RSpecAdapter.bind in your rails_helper.rb or spec_helper.rb. Please follow the installation guide again: https://docs.knapsackpro.com/integration/")
|
51
|
+
KnapsackPro.logger.warn("3. Another potential reason for this warning is that all your tests are empty test files, pending tests, or they have syntax errors, and the time execution was not recorded for them.")
|
52
52
|
end
|
53
53
|
|
54
54
|
create_build_subset(test_files)
|
@@ -79,8 +79,7 @@ module KnapsackPro
|
|
79
79
|
private
|
80
80
|
|
81
81
|
def self.queue_path
|
82
|
-
|
83
|
-
"#{KnapsackPro::Config::Env::TMP_DIR}/queue/#{queue_id}"
|
82
|
+
"#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/queue/#{KnapsackPro::Config::Env.queue_id}"
|
84
83
|
end
|
85
84
|
end
|
86
85
|
end
|
@@ -110,9 +110,9 @@ module KnapsackPro
|
|
110
110
|
def self.log_rspec_command(cli_args, test_file_paths, type)
|
111
111
|
case type
|
112
112
|
when :subset_queue
|
113
|
-
KnapsackPro.logger.info("To retry
|
113
|
+
KnapsackPro.logger.info("To retry the last batch of tests fetched from the API Queue, please run the following command on your machine. (If you use the `-- order random` option, remember to add correct `--seed 123` that you can find at the end of the RSpec output.)")
|
114
114
|
when :end_of_queue
|
115
|
-
KnapsackPro.logger.info("To retry
|
115
|
+
KnapsackPro.logger.info("To retry all the tests assigned to this CI node, please run the following command on your machine:")
|
116
116
|
end
|
117
117
|
|
118
118
|
stringify_cli_args = cli_args.join(' ')
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module KnapsackPro
|
2
2
|
class SlowTestFileDeterminer
|
3
3
|
TIME_THRESHOLD_PER_CI_NODE = 0.7 # 70%
|
4
|
-
REPORT_DIR = "#{KnapsackPro::Config::Env::TMP_DIR}/slow_test_file_determiner"
|
5
4
|
|
6
5
|
# test_files: { 'path' => 'a_spec.rb', 'time_execution' => 0.0 }
|
7
6
|
# time_execution: of build distribution (total time of CI build run)
|
@@ -9,17 +8,19 @@ module KnapsackPro
|
|
9
8
|
time_threshold = (time_execution / KnapsackPro::Config::Env.ci_node_total) * TIME_THRESHOLD_PER_CI_NODE
|
10
9
|
|
11
10
|
test_files.select do |test_file|
|
12
|
-
test_file.fetch('time_execution')
|
11
|
+
time_execution = test_file.fetch('time_execution')
|
12
|
+
time_execution >= time_threshold && time_execution > 0
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.save_to_json_report(test_files)
|
17
|
-
|
17
|
+
KnapsackPro::Config::TempFiles.ensure_temp_directory_exists!
|
18
|
+
FileUtils.mkdir_p(report_dir)
|
18
19
|
File.write(report_path, test_files.to_json)
|
19
20
|
end
|
20
21
|
|
21
22
|
def self.read_from_json_report
|
22
|
-
raise '
|
23
|
+
raise 'The report with slow test files has not been generated yet. If you have enabled split by test cases https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases and you see this error it means that your tests accidentally cleaned up the .knapsack_pro directory. Please do not remove this directory during tests runtime!' unless File.exist?(report_path)
|
23
24
|
slow_test_files_json_report = File.read(report_path)
|
24
25
|
JSON.parse(slow_test_files_json_report)
|
25
26
|
end
|
@@ -27,7 +28,11 @@ module KnapsackPro
|
|
27
28
|
private
|
28
29
|
|
29
30
|
def self.report_path
|
30
|
-
"#{
|
31
|
+
"#{report_dir}/slow_test_files_node_#{KnapsackPro::Config::Env.ci_node_index}.json"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.report_dir
|
35
|
+
"#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/slow_test_file_determiner"
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module KnapsackPro
|
2
2
|
module TestCaseDetectors
|
3
3
|
class RSpecTestExampleDetector
|
4
|
-
REPORT_DIR = "#{KnapsackPro::Config::Env::TMP_DIR}/test_case_detectors/rspec"
|
5
|
-
|
6
4
|
def generate_json_report
|
7
5
|
require 'rspec/core'
|
8
6
|
|
@@ -47,7 +45,7 @@ module KnapsackPro
|
|
47
45
|
end
|
48
46
|
|
49
47
|
def test_file_example_paths
|
50
|
-
raise "No report found at #{report_path}" unless File.
|
48
|
+
raise "No report found at #{report_path}" unless File.exist?(report_path)
|
51
49
|
|
52
50
|
json_report = File.read(report_path)
|
53
51
|
hash_report = JSON.parse(json_report)
|
@@ -69,8 +67,12 @@ module KnapsackPro
|
|
69
67
|
|
70
68
|
private
|
71
69
|
|
70
|
+
def report_dir
|
71
|
+
"#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/test_case_detectors/rspec"
|
72
|
+
end
|
73
|
+
|
72
74
|
def report_path
|
73
|
-
"#{
|
75
|
+
"#{report_dir}/rspec_dry_run_json_report_node_#{KnapsackPro::Config::Env.ci_node_index}.json"
|
74
76
|
end
|
75
77
|
|
76
78
|
def adapter_class
|
@@ -86,11 +88,12 @@ module KnapsackPro
|
|
86
88
|
end
|
87
89
|
|
88
90
|
def ensure_report_dir_exists
|
89
|
-
|
91
|
+
KnapsackPro::Config::TempFiles.ensure_temp_directory_exists!
|
92
|
+
FileUtils.mkdir_p(report_dir)
|
90
93
|
end
|
91
94
|
|
92
95
|
def remove_old_json_report
|
93
|
-
File.delete(report_path) if File.
|
96
|
+
File.delete(report_path) if File.exist?(report_path)
|
94
97
|
end
|
95
98
|
|
96
99
|
def test_file_hash_for(test_file_path)
|
data/lib/knapsack_pro/tracker.rb
CHANGED
@@ -11,6 +11,7 @@ module KnapsackPro
|
|
11
11
|
|
12
12
|
def initialize
|
13
13
|
@global_time_since_beginning = 0
|
14
|
+
KnapsackPro::Config::TempFiles.ensure_temp_directory_exists!
|
14
15
|
FileUtils.mkdir_p(tracker_dir_path)
|
15
16
|
set_defaults
|
16
17
|
end
|
@@ -21,7 +22,7 @@ module KnapsackPro
|
|
21
22
|
# Remove report only when the reset! method is called explicitly.
|
22
23
|
# The report should be persisted on the disk so that multiple tracker instances can share the report state.
|
23
24
|
# Tracker instance can be created by knapsack_pro process and a separate tracker is created by rake task (e.g., RSpec) in Regular Mode.
|
24
|
-
File.delete(prerun_tests_report_path) if File.
|
25
|
+
File.delete(prerun_tests_report_path) if File.exist?(prerun_tests_report_path)
|
25
26
|
end
|
26
27
|
|
27
28
|
def start_timer
|
@@ -92,7 +93,7 @@ module KnapsackPro
|
|
92
93
|
end
|
93
94
|
|
94
95
|
def tracker_dir_path
|
95
|
-
"#{KnapsackPro::Config::
|
96
|
+
"#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/tracker"
|
96
97
|
end
|
97
98
|
|
98
99
|
def prerun_tests_report_path
|
@@ -110,6 +111,7 @@ module KnapsackPro
|
|
110
111
|
end
|
111
112
|
|
112
113
|
def read_prerun_tests_report
|
114
|
+
raise "Report #{prerun_tests_report_path} doest not exist on the disk. Most likely, it was removed accidentally. Please report the bug to the Knapsack Pro support team at https://knapsackpro.com/contact" unless File.exist?(prerun_tests_report_path)
|
113
115
|
JSON.parse(File.read(prerun_tests_report_path))
|
114
116
|
end
|
115
117
|
|
data/lib/knapsack_pro/version.rb
CHANGED
data/lib/knapsack_pro.rb
CHANGED
@@ -27,6 +27,7 @@ require_relative 'knapsack_pro/config/ci/github_actions'
|
|
27
27
|
require_relative 'knapsack_pro/config/ci/heroku'
|
28
28
|
require_relative 'knapsack_pro/config/env'
|
29
29
|
require_relative 'knapsack_pro/config/env_generator'
|
30
|
+
require_relative 'knapsack_pro/config/temp_files'
|
30
31
|
require_relative 'knapsack_pro/logger_wrapper'
|
31
32
|
require_relative 'knapsack_pro/client/api/action'
|
32
33
|
require_relative 'knapsack_pro/client/api/v1/base'
|
@@ -32,14 +32,13 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
32
32
|
context 'when CI node index 0' do
|
33
33
|
let(:ci_node_index) { 0 }
|
34
34
|
|
35
|
-
it { expect(subject).to eq '
|
36
|
-
|
35
|
+
it { expect(subject).to eq '.knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt' }
|
37
36
|
end
|
38
37
|
|
39
38
|
context 'when CI node index 1' do
|
40
39
|
let(:ci_node_index) { 1 }
|
41
40
|
|
42
|
-
it { expect(subject).to eq '
|
41
|
+
it { expect(subject).to eq '.knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_1.txt' }
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
@@ -93,18 +92,20 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
93
92
|
end
|
94
93
|
|
95
94
|
describe '.verify_bind_method_called' do
|
95
|
+
let(:temp_directory_path) { '.knapsack_pro' }
|
96
|
+
|
96
97
|
subject { described_class.verify_bind_method_called }
|
97
98
|
|
98
99
|
before do
|
99
100
|
expect(::Kernel).to receive(:at_exit).and_yield
|
100
|
-
expect(File).to receive(:
|
101
|
+
expect(File).to receive(:exist?).with('.knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt').and_return(adapter_bind_method_called_file_exists)
|
101
102
|
end
|
102
103
|
|
103
104
|
context 'when adapter bind method called' do
|
104
105
|
let(:adapter_bind_method_called_file_exists) { true }
|
105
106
|
|
106
107
|
it do
|
107
|
-
expect(File).to receive(:delete).with('
|
108
|
+
expect(File).to receive(:delete).with('.knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt')
|
108
109
|
subject
|
109
110
|
end
|
110
111
|
end
|
@@ -120,12 +121,13 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
120
121
|
end
|
121
122
|
|
122
123
|
describe '#bind' do
|
124
|
+
let(:temp_directory_path) { '.knapsack_pro' }
|
123
125
|
let(:recording_enabled?) { false }
|
124
126
|
let(:queue_recording_enabled?) { false }
|
125
127
|
|
126
128
|
before do
|
127
|
-
expect(
|
128
|
-
expect(File).to receive(:write).with('
|
129
|
+
expect(KnapsackPro::Config::TempFiles).to receive(:ensure_temp_directory_exists!)
|
130
|
+
expect(File).to receive(:write).with('.knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt', nil)
|
129
131
|
|
130
132
|
expect(KnapsackPro::Config::Env).to receive(:recording_enabled?).and_return(recording_enabled?)
|
131
133
|
expect(KnapsackPro::Config::Env).to receive(:queue_recording_enabled?).and_return(queue_recording_enabled?)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
describe KnapsackPro::Config::TempFiles do
|
2
|
+
describe 'TEMP_DIRECTORY_PATH' do
|
3
|
+
subject { described_class::TEMP_DIRECTORY_PATH }
|
4
|
+
|
5
|
+
it 'returns temporary directory path' do
|
6
|
+
expect(subject).to eq '.knapsack_pro'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.ensure_temp_directory_exists!', :clear_tmp do
|
11
|
+
let(:gitignore_file_path) { '.knapsack_pro/.gitignore' }
|
12
|
+
|
13
|
+
subject { described_class.ensure_temp_directory_exists! }
|
14
|
+
|
15
|
+
it 'creates .gitignore file' do
|
16
|
+
expect { subject }.to change { File.exist?(gitignore_file_path) }.from(false).to(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it '.gitignore file has correct content to ignore all files in temporary directory' do
|
20
|
+
subject
|
21
|
+
|
22
|
+
expect(File.read(gitignore_file_path)).to match /^\*$/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -25,6 +25,8 @@ describe KnapsackPro::Report do
|
|
25
25
|
subset_queue_id = 'fake-subset-queue-id'
|
26
26
|
expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).and_return(subset_queue_id)
|
27
27
|
|
28
|
+
expect(KnapsackPro::Config::TempFiles).to receive(:ensure_temp_directory_exists!)
|
29
|
+
|
28
30
|
queue_id = 'fake-queue-id'
|
29
31
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
|
30
32
|
end
|
@@ -34,7 +36,7 @@ describe KnapsackPro::Report do
|
|
34
36
|
|
35
37
|
expect(
|
36
38
|
JSON.parse(
|
37
|
-
File.read('
|
39
|
+
File.read('.knapsack_pro/queue/fake-queue-id/fake-subset-queue-id.json')
|
38
40
|
)
|
39
41
|
).to eq([
|
40
42
|
{ 'path' => fake_path }
|
@@ -56,7 +58,7 @@ describe KnapsackPro::Report do
|
|
56
58
|
queue_id = 'fake-queue-id'
|
57
59
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
|
58
60
|
|
59
|
-
expect(Dir).to receive(:glob).with('
|
61
|
+
expect(Dir).to receive(:glob).with('.knapsack_pro/queue/fake-queue-id/*.json').and_return([
|
60
62
|
json_test_file_a_path,
|
61
63
|
json_test_file_b_path
|
62
64
|
])
|
@@ -89,7 +91,7 @@ describe KnapsackPro::Report do
|
|
89
91
|
queue_id = 'fake-queue-id'
|
90
92
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
|
91
93
|
|
92
|
-
expect(Dir).to receive(:glob).with('
|
94
|
+
expect(Dir).to receive(:glob).with('.knapsack_pro/queue/fake-queue-id/*.json').and_return([
|
93
95
|
json_test_file_a_path,
|
94
96
|
json_test_file_b_path
|
95
97
|
])
|
@@ -102,9 +104,9 @@ describe KnapsackPro::Report do
|
|
102
104
|
logger = instance_double(Logger)
|
103
105
|
expect(KnapsackPro).to receive(:logger).exactly(4).and_return(logger)
|
104
106
|
expect(logger).to receive(:warn).with('2 test files were executed on this CI node but the recorded time was lost due to:')
|
105
|
-
expect(logger).to receive(:warn).with('1.
|
106
|
-
expect(logger).to receive(:warn).with(
|
107
|
-
expect(logger).to receive(:warn).with('3.
|
107
|
+
expect(logger).to receive(:warn).with('1. Please ensure you do not remove the contents of the .knapsack_pro directory between tests run.')
|
108
|
+
expect(logger).to receive(:warn).with("2. Ensure you've added Knapsack::Adapters::RSpecAdapter.bind in your rails_helper.rb or spec_helper.rb. Please follow the installation guide again: https://docs.knapsackpro.com/integration/")
|
109
|
+
expect(logger).to receive(:warn).with('3. Another potential reason for this warning is that all your tests are empty test files, pending tests, or they have syntax errors, and the time execution was not recorded for them.')
|
108
110
|
|
109
111
|
expect(described_class).to receive(:create_build_subset).with(
|
110
112
|
json_test_file_a + json_test_file_b
|
@@ -121,15 +123,14 @@ describe KnapsackPro::Report do
|
|
121
123
|
queue_id = 'fake-queue-id'
|
122
124
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
|
123
125
|
|
124
|
-
expect(Dir).to receive(:glob).with('
|
126
|
+
expect(Dir).to receive(:glob).with('.knapsack_pro/queue/fake-queue-id/*.json').and_return([])
|
125
127
|
end
|
126
128
|
|
127
129
|
it 'logs warning about reasons why no test files were executed on this CI node' do
|
128
130
|
logger = instance_double(Logger)
|
129
|
-
expect(KnapsackPro).to receive(:logger).exactly(
|
131
|
+
expect(KnapsackPro).to receive(:logger).exactly(2).and_return(logger)
|
130
132
|
expect(logger).to receive(:warn).with('No test files were executed on this CI node.')
|
131
|
-
expect(logger).to receive(:debug).with('
|
132
|
-
expect(logger).to receive(:debug).with("Another reason might be when your CI node failed in a way that prevented knapsack_pro to save time execution data to Knapsack Pro API and you have just tried to retry failed CI node but instead you got no test files to execute. In that case knapsack_pro don't know what tests should be executed here.")
|
133
|
+
expect(logger).to receive(:debug).with('This CI node likely started work late after the test files were already executed by other CI nodes consuming the queue.')
|
133
134
|
|
134
135
|
expect(described_class).to receive(:create_build_subset).with([])
|
135
136
|
|
@@ -1,16 +1,6 @@
|
|
1
1
|
describe KnapsackPro::SlowTestFileDeterminer do
|
2
2
|
describe '.call' do
|
3
3
|
let(:node_total) { 4 }
|
4
|
-
let(:time_execution) { 20.0 }
|
5
|
-
let(:test_files) do
|
6
|
-
[
|
7
|
-
{ 'path' => 'a_spec.rb', 'time_execution' => 1.0 },
|
8
|
-
{ 'path' => 'b_spec.rb', 'time_execution' => 3.4 },
|
9
|
-
# slow tests are above 3.5s threshold (20.0 / 4 * 0.7 = 3.5)
|
10
|
-
{ 'path' => 'c_spec.rb', 'time_execution' => 3.5 },
|
11
|
-
{ 'path' => 'd_spec.rb', 'time_execution' => 5.9 },
|
12
|
-
]
|
13
|
-
end
|
14
4
|
|
15
5
|
before do
|
16
6
|
expect(KnapsackPro::Config::Env).to receive(:ci_node_total).and_return(node_total)
|
@@ -18,16 +8,43 @@ describe KnapsackPro::SlowTestFileDeterminer do
|
|
18
8
|
|
19
9
|
subject { described_class.call(test_files, time_execution) }
|
20
10
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
11
|
+
context 'when test files have recorded time execution' do
|
12
|
+
let(:time_execution) { 20.0 }
|
13
|
+
let(:test_files) do
|
14
|
+
[
|
15
|
+
{ 'path' => 'a_spec.rb', 'time_execution' => 1.0 },
|
16
|
+
{ 'path' => 'b_spec.rb', 'time_execution' => 3.4 },
|
17
|
+
# slow tests are above 3.5s threshold (20.0 / 4 * 0.7 = 3.5)
|
18
|
+
{ 'path' => 'c_spec.rb', 'time_execution' => 3.5 },
|
19
|
+
{ 'path' => 'd_spec.rb', 'time_execution' => 5.9 },
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
it do
|
24
|
+
expect(subject).to eq([
|
25
|
+
{ 'path' => 'c_spec.rb', 'time_execution' => 3.5 },
|
26
|
+
{ 'path' => 'd_spec.rb', 'time_execution' => 5.9 },
|
27
|
+
])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when test files have no recorded time execution' do
|
32
|
+
let(:time_execution) { 0.0 }
|
33
|
+
let(:test_files) do
|
34
|
+
[
|
35
|
+
{ 'path' => 'a_spec.rb', 'time_execution' => 0.0 },
|
36
|
+
{ 'path' => 'b_spec.rb', 'time_execution' => 0.0 },
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
it do
|
41
|
+
expect(subject).to eq([])
|
42
|
+
end
|
26
43
|
end
|
27
44
|
end
|
28
45
|
|
29
46
|
describe '.save_to_json_report', :clear_tmp do
|
30
|
-
let(:json_report_path) { '
|
47
|
+
let(:json_report_path) { '.knapsack_pro/slow_test_file_determiner/slow_test_files_node_0.json' }
|
31
48
|
let(:test_files) do
|
32
49
|
[
|
33
50
|
{ 'path' => 'a_spec.rb', 'time_execution' => 1.0 },
|
@@ -67,7 +84,7 @@ describe KnapsackPro::SlowTestFileDeterminer do
|
|
67
84
|
|
68
85
|
context 'when json report does not exist' do
|
69
86
|
it do
|
70
|
-
expect { subject }.to raise_error(RuntimeError, '
|
87
|
+
expect { subject }.to raise_error(RuntimeError, 'The report with slow test files has not been generated yet. If you have enabled split by test cases https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases and you see this error it means that your tests accidentally cleaned up the .knapsack_pro directory. Please do not remove this directory during tests runtime!')
|
71
88
|
end
|
72
89
|
end
|
73
90
|
end
|
@@ -1,15 +1,17 @@
|
|
1
1
|
describe KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector do
|
2
|
-
let(:report_dir) { '
|
3
|
-
let(:report_path) { '
|
2
|
+
let(:report_dir) { '.knapsack_pro/test_case_detectors/rspec' }
|
3
|
+
let(:report_path) { '.knapsack_pro/test_case_detectors/rspec/rspec_dry_run_json_report_node_0.json' }
|
4
4
|
let(:rspec_test_example_detector) { described_class.new }
|
5
5
|
|
6
6
|
describe '#generate_json_report' do
|
7
7
|
subject { rspec_test_example_detector.generate_json_report }
|
8
8
|
|
9
9
|
before do
|
10
|
+
expect(KnapsackPro::Config::TempFiles).to receive(:ensure_temp_directory_exists!)
|
11
|
+
|
10
12
|
expect(FileUtils).to receive(:mkdir_p).with(report_dir)
|
11
13
|
|
12
|
-
expect(File).to receive(:
|
14
|
+
expect(File).to receive(:exist?).with(report_path).and_return(true)
|
13
15
|
expect(File).to receive(:delete).with(report_path)
|
14
16
|
|
15
17
|
expect(rspec_test_example_detector).to receive(:slow_test_files).and_return(test_file_entities)
|
@@ -95,7 +97,7 @@ describe KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector do
|
|
95
97
|
|
96
98
|
context 'when JSON report exists' do
|
97
99
|
it do
|
98
|
-
expect(File).to receive(:
|
100
|
+
expect(File).to receive(:exist?).with(report_path).and_return(true)
|
99
101
|
|
100
102
|
json_file = {
|
101
103
|
'examples' => [
|
@@ -114,9 +116,9 @@ describe KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector do
|
|
114
116
|
|
115
117
|
context 'when JSON report does not exist' do
|
116
118
|
it do
|
117
|
-
expect(File).to receive(:
|
119
|
+
expect(File).to receive(:exist?).with(report_path).and_return(false)
|
118
120
|
|
119
|
-
expect { subject }.to raise_error(RuntimeError,
|
121
|
+
expect { subject }.to raise_error(RuntimeError, "No report found at .knapsack_pro/test_case_detectors/rspec/rspec_dry_run_json_report_node_0.json")
|
120
122
|
end
|
121
123
|
end
|
122
124
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -16,6 +16,8 @@ require 'knapsack_pro'
|
|
16
16
|
|
17
17
|
Dir["#{KnapsackPro.root}/spec/{support,fixtures}/**/*.rb"].each { |f| require f }
|
18
18
|
|
19
|
+
KNAPSACK_PRO_TMP_DIR = File.join(KnapsackPro.root, '.knapsack_pro')
|
20
|
+
|
19
21
|
RSpec.configure do |config|
|
20
22
|
config.order = :random
|
21
23
|
config.mock_with :rspec do |mocks|
|
@@ -29,13 +31,14 @@ RSpec.configure do |config|
|
|
29
31
|
|
30
32
|
config.before(:each) do
|
31
33
|
if RSpec.current_example.metadata[:clear_tmp]
|
32
|
-
FileUtils.
|
34
|
+
FileUtils.rm_r(KNAPSACK_PRO_TMP_DIR) if File.exist?(KNAPSACK_PRO_TMP_DIR)
|
35
|
+
FileUtils.mkdir_p(KNAPSACK_PRO_TMP_DIR)
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
36
39
|
config.after(:each) do
|
37
40
|
if RSpec.current_example.metadata[:clear_tmp]
|
38
|
-
FileUtils.rm_r(File.
|
41
|
+
FileUtils.rm_r(KNAPSACK_PRO_TMP_DIR) if File.exist?(KNAPSACK_PRO_TMP_DIR)
|
39
42
|
end
|
40
43
|
end
|
41
44
|
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: 3.
|
4
|
+
version: 3.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -233,6 +233,7 @@ files:
|
|
233
233
|
- lib/knapsack_pro/config/ci/travis.rb
|
234
234
|
- lib/knapsack_pro/config/env.rb
|
235
235
|
- lib/knapsack_pro/config/env_generator.rb
|
236
|
+
- lib/knapsack_pro/config/temp_files.rb
|
236
237
|
- lib/knapsack_pro/crypto/branch_encryptor.rb
|
237
238
|
- lib/knapsack_pro/crypto/decryptor.rb
|
238
239
|
- lib/knapsack_pro/crypto/digestor.rb
|
@@ -328,6 +329,7 @@ files:
|
|
328
329
|
- spec/knapsack_pro/config/ci/travis_spec.rb
|
329
330
|
- spec/knapsack_pro/config/env_generator_spec.rb
|
330
331
|
- spec/knapsack_pro/config/env_spec.rb
|
332
|
+
- spec/knapsack_pro/config/temp_files_spec.rb
|
331
333
|
- spec/knapsack_pro/crypto/branch_encryptor_spec.rb
|
332
334
|
- spec/knapsack_pro/crypto/decryptor_spec.rb
|
333
335
|
- spec/knapsack_pro/crypto/digestor_spec.rb
|
@@ -449,6 +451,7 @@ test_files:
|
|
449
451
|
- spec/knapsack_pro/config/ci/travis_spec.rb
|
450
452
|
- spec/knapsack_pro/config/env_generator_spec.rb
|
451
453
|
- spec/knapsack_pro/config/env_spec.rb
|
454
|
+
- spec/knapsack_pro/config/temp_files_spec.rb
|
452
455
|
- spec/knapsack_pro/crypto/branch_encryptor_spec.rb
|
453
456
|
- spec/knapsack_pro/crypto/decryptor_spec.rb
|
454
457
|
- spec/knapsack_pro/crypto/digestor_spec.rb
|