parallel_tests 3.4.0 → 3.5.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 +4 -4
- data/Readme.md +22 -7
- data/bin/parallel_cucumber +2 -1
- data/bin/parallel_rspec +2 -1
- data/bin/parallel_spinach +2 -1
- data/bin/parallel_test +2 -1
- data/lib/parallel_tests.rb +4 -2
- data/lib/parallel_tests/cli.rb +88 -51
- data/lib/parallel_tests/cucumber/failures_logger.rb +1 -1
- data/lib/parallel_tests/cucumber/features_with_steps.rb +4 -3
- data/lib/parallel_tests/cucumber/runner.rb +4 -5
- data/lib/parallel_tests/cucumber/scenario_line_logger.rb +3 -3
- data/lib/parallel_tests/cucumber/scenarios.rb +5 -5
- data/lib/parallel_tests/gherkin/io.rb +2 -3
- data/lib/parallel_tests/gherkin/listener.rb +9 -10
- data/lib/parallel_tests/gherkin/runner.rb +16 -21
- data/lib/parallel_tests/gherkin/runtime_logger.rb +2 -1
- data/lib/parallel_tests/grouper.rb +56 -5
- data/lib/parallel_tests/pids.rb +3 -2
- data/lib/parallel_tests/railtie.rb +1 -0
- data/lib/parallel_tests/rspec/failures_logger.rb +2 -2
- data/lib/parallel_tests/rspec/logger_base.rb +9 -7
- data/lib/parallel_tests/rspec/runner.rb +7 -7
- data/lib/parallel_tests/rspec/runtime_logger.rb +12 -10
- data/lib/parallel_tests/rspec/summary_logger.rb +2 -3
- data/lib/parallel_tests/spinach/runner.rb +2 -2
- data/lib/parallel_tests/tasks.rb +35 -28
- data/lib/parallel_tests/test/runner.rb +32 -27
- data/lib/parallel_tests/test/runtime_logger.rb +19 -14
- data/lib/parallel_tests/version.rb +2 -1
- metadata +4 -4
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "parallel_tests/test/runner"
|
2
3
|
|
3
4
|
module ParallelTests
|
@@ -12,10 +13,9 @@ module ParallelTests
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def determine_executable
|
15
|
-
|
16
|
-
when File.exist?("bin/rspec")
|
16
|
+
if File.exist?("bin/rspec")
|
17
17
|
ParallelTests.with_ruby_binary("bin/rspec")
|
18
|
-
|
18
|
+
elsif ParallelTests.bundler_enabled?
|
19
19
|
"bundle exec rspec"
|
20
20
|
else
|
21
21
|
"rspec"
|
@@ -23,7 +23,7 @@ module ParallelTests
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def runtime_log
|
26
|
-
|
26
|
+
"tmp/parallel_runtime_rspec.log"
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_file_name
|
@@ -55,9 +55,9 @@ module ParallelTests
|
|
55
55
|
return text unless $stdout.tty?
|
56
56
|
sums = sum_up_results(results)
|
57
57
|
color =
|
58
|
-
if sums['failure']
|
58
|
+
if sums['failure'] > 0
|
59
59
|
31 # red
|
60
|
-
elsif sums['pending']
|
60
|
+
elsif sums['pending'] > 0
|
61
61
|
33 # yellow
|
62
62
|
else
|
63
63
|
32 # green
|
@@ -77,7 +77,7 @@ module ParallelTests
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def spec_opts
|
80
|
-
options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect{|f| File.file?(f) }
|
80
|
+
options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect { |f| File.file?(f) }
|
81
81
|
return unless options_file
|
82
82
|
"-O #{options_file}"
|
83
83
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'parallel_tests'
|
2
3
|
require 'parallel_tests/rspec/logger_base'
|
3
4
|
|
@@ -8,9 +9,7 @@ class ParallelTests::RSpec::RuntimeLogger < ParallelTests::RSpec::LoggerBase
|
|
8
9
|
@group_nesting = 0
|
9
10
|
end
|
10
11
|
|
11
|
-
unless RSPEC_2
|
12
|
-
RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump
|
13
|
-
end
|
12
|
+
RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump unless RSPEC_2
|
14
13
|
|
15
14
|
def example_group_started(example_group)
|
16
15
|
@time = ParallelTests.now if @group_nesting == 0
|
@@ -27,16 +26,19 @@ class ParallelTests::RSpec::RuntimeLogger < ParallelTests::RSpec::LoggerBase
|
|
27
26
|
super if defined?(super)
|
28
27
|
end
|
29
28
|
|
30
|
-
def dump_summary(*
|
31
|
-
|
32
|
-
def
|
33
|
-
|
29
|
+
def dump_summary(*); end
|
30
|
+
|
31
|
+
def dump_failures(*); end
|
32
|
+
|
33
|
+
def dump_failure(*); end
|
34
|
+
|
35
|
+
def dump_pending(*); end
|
34
36
|
|
35
|
-
def start_dump(*
|
36
|
-
return unless ENV['TEST_ENV_NUMBER'] #only record when running in parallel
|
37
|
+
def start_dump(*)
|
38
|
+
return unless ENV['TEST_ENV_NUMBER'] # only record when running in parallel
|
37
39
|
lock_output do
|
38
40
|
@example_times.each do |file, time|
|
39
|
-
relative_path = file.sub(
|
41
|
+
relative_path = file.sub(%r{^#{Regexp.escape Dir.pwd}/}, '').sub(%r{^\./}, "")
|
40
42
|
@output.puts "#{relative_path}:#{time > 0 ? time : 0}"
|
41
43
|
end
|
42
44
|
end
|
@@ -1,9 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'parallel_tests/rspec/failures_logger'
|
2
3
|
|
3
4
|
class ParallelTests::RSpec::SummaryLogger < ParallelTests::RSpec::LoggerBase
|
4
|
-
unless RSPEC_2
|
5
|
-
RSpec::Core::Formatters.register self, :dump_failures
|
6
|
-
end
|
5
|
+
RSpec::Core::Formatters.register self, :dump_failures unless RSPEC_2
|
7
6
|
|
8
7
|
def dump_failures(*args)
|
9
8
|
lock_output { super }
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "parallel_tests/gherkin/runner"
|
2
3
|
|
3
4
|
module ParallelTests
|
@@ -9,10 +10,9 @@ module ParallelTests
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def runtime_logging
|
12
|
-
#Not Yet Supported
|
13
|
+
# Not Yet Supported
|
13
14
|
""
|
14
15
|
end
|
15
|
-
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/parallel_tests/tasks.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rake'
|
2
3
|
require 'shellwords'
|
3
4
|
|
@@ -27,12 +28,13 @@ module ParallelTests
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
def run_in_parallel(cmd, options={})
|
31
|
+
def run_in_parallel(cmd, options = {})
|
31
32
|
load_lib
|
32
33
|
count = " -n #{options[:count]}" unless options[:count].to_s.empty?
|
33
34
|
# Using the relative path to find the binary allow to run a specific version of it
|
34
|
-
executable = File.expand_path(
|
35
|
-
|
35
|
+
executable = File.expand_path('../../bin/parallel_test', __dir__)
|
36
|
+
non_parallel = (options[:non_parallel] ? ' --non-parallel' : '')
|
37
|
+
command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} --exec '#{cmd}'#{count}#{non_parallel}"
|
36
38
|
abort unless system(command)
|
37
39
|
end
|
38
40
|
|
@@ -50,12 +52,12 @@ module ParallelTests
|
|
50
52
|
# - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0
|
51
53
|
def suppress_output(command, ignore_regex)
|
52
54
|
activate_pipefail = "set -o pipefail"
|
53
|
-
remove_ignored_lines = %
|
55
|
+
remove_ignored_lines = %{(grep -v "#{ignore_regex}" || test 1)}
|
54
56
|
|
55
57
|
if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1")
|
56
58
|
# We need to shell escape single quotes (' becomes '"'"') because
|
57
59
|
# run_in_parallel wraps command in single quotes
|
58
|
-
%
|
60
|
+
%{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'}
|
59
61
|
else
|
60
62
|
command
|
61
63
|
end
|
@@ -83,7 +85,7 @@ module ParallelTests
|
|
83
85
|
# parallel:spec[2,models,options]
|
84
86
|
# parallel:spec[,models,options]
|
85
87
|
count = args.shift if args.first.to_s =~ /^\d*$/
|
86
|
-
num_processes = count.
|
88
|
+
num_processes = (count.to_s.empty? ? nil : Integer(count))
|
87
89
|
pattern = args.shift
|
88
90
|
options = args.shift
|
89
91
|
pass_through = args.shift
|
@@ -96,26 +98,28 @@ end
|
|
96
98
|
|
97
99
|
namespace :parallel do
|
98
100
|
desc "Setup test databases via db:setup --> parallel:setup[num_cpus]"
|
99
|
-
task :setup, :count do |_,args|
|
101
|
+
task :setup, :count do |_, args|
|
100
102
|
command = "#{ParallelTests::Tasks.rake_bin} db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}"
|
101
103
|
ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
|
102
104
|
end
|
103
105
|
|
104
106
|
desc "Create test databases via db:create --> parallel:create[num_cpus]"
|
105
|
-
task :create, :count do |_,args|
|
107
|
+
task :create, :count do |_, args|
|
106
108
|
ParallelTests::Tasks.run_in_parallel(
|
107
|
-
"#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
109
|
+
"#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
110
|
+
)
|
108
111
|
end
|
109
112
|
|
110
113
|
desc "Drop test databases via db:drop --> parallel:drop[num_cpus]"
|
111
|
-
task :drop, :count do |_,args|
|
114
|
+
task :drop, :count do |_, args|
|
112
115
|
ParallelTests::Tasks.run_in_parallel(
|
113
116
|
"#{ParallelTests::Tasks.rake_bin} db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} " \
|
114
|
-
"DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args
|
117
|
+
"DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args
|
118
|
+
)
|
115
119
|
end
|
116
120
|
|
117
121
|
desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]"
|
118
|
-
task(:prepare, [:count]) do |_,args|
|
122
|
+
task(:prepare, [:count]) do |_, args|
|
119
123
|
ParallelTests::Tasks.check_for_pending_migrations
|
120
124
|
if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format)
|
121
125
|
# fast: dump once, load in parallel
|
@@ -128,7 +132,7 @@ namespace :parallel do
|
|
128
132
|
Rake::Task["parallel:load_#{type}"].invoke(args[:count])
|
129
133
|
else
|
130
134
|
# slow: dump and load in in serial
|
131
|
-
args = args.to_hash.merge(:
|
135
|
+
args = args.to_hash.merge(non_parallel: true) # normal merge returns nil
|
132
136
|
task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare'
|
133
137
|
ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{task_name}", args)
|
134
138
|
next
|
@@ -137,20 +141,22 @@ namespace :parallel do
|
|
137
141
|
|
138
142
|
# when dumping/resetting takes too long
|
139
143
|
desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]"
|
140
|
-
task :migrate, :count do |_,args|
|
144
|
+
task :migrate, :count do |_, args|
|
141
145
|
ParallelTests::Tasks.run_in_parallel(
|
142
|
-
"#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
146
|
+
"#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
147
|
+
)
|
143
148
|
end
|
144
149
|
|
145
150
|
desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]"
|
146
|
-
task :rollback, :count do |_,args|
|
151
|
+
task :rollback, :count do |_, args|
|
147
152
|
ParallelTests::Tasks.run_in_parallel(
|
148
|
-
"#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
153
|
+
"#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
154
|
+
)
|
149
155
|
end
|
150
156
|
|
151
157
|
# just load the schema (good for integration server <-> no development db)
|
152
158
|
desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]"
|
153
|
-
task :load_schema, :count do |_,args|
|
159
|
+
task :load_schema, :count do |_, args|
|
154
160
|
command = "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \
|
155
161
|
"db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
|
156
162
|
ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args)
|
@@ -158,28 +164,31 @@ namespace :parallel do
|
|
158
164
|
|
159
165
|
# load the structure from the structure.sql file
|
160
166
|
desc "Load structure for test databases via db:structure:load --> parallel:load_structure[num_cpus]"
|
161
|
-
task :load_structure, :count do |_,args|
|
167
|
+
task :load_structure, :count do |_, args|
|
162
168
|
ParallelTests::Tasks.run_in_parallel(
|
163
169
|
"#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \
|
164
|
-
"db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args
|
170
|
+
"db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args
|
171
|
+
)
|
165
172
|
end
|
166
173
|
|
167
174
|
desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]"
|
168
|
-
task :seed, :count do |_,args|
|
175
|
+
task :seed, :count do |_, args|
|
169
176
|
ParallelTests::Tasks.run_in_parallel(
|
170
|
-
"#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
177
|
+
"#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args
|
178
|
+
)
|
171
179
|
end
|
172
180
|
|
173
181
|
desc "Launch given rake command in parallel"
|
174
182
|
task :rake, :command, :count do |_, args|
|
175
183
|
ParallelTests::Tasks.run_in_parallel(
|
176
184
|
"RAILS_ENV=#{ParallelTests::Tasks.rails_env} #{ParallelTests::Tasks.rake_bin} " \
|
177
|
-
"#{args.command}", args
|
185
|
+
"#{args.command}", args
|
186
|
+
)
|
178
187
|
end
|
179
188
|
|
180
189
|
['test', 'spec', 'features', 'features-spinach'].each do |type|
|
181
190
|
desc "Run #{type} in parallel with parallel:#{type}[num_cpus]"
|
182
|
-
task type, [:count, :pattern, :options, :pass_through] do |
|
191
|
+
task type, [:count, :pattern, :options, :pass_through] do |_t, args|
|
183
192
|
ParallelTests::Tasks.check_for_pending_migrations
|
184
193
|
ParallelTests::Tasks.load_lib
|
185
194
|
|
@@ -188,12 +197,10 @@ namespace :parallel do
|
|
188
197
|
'spec' => 'rspec',
|
189
198
|
'test' => 'test',
|
190
199
|
'features' => 'cucumber',
|
191
|
-
'features-spinach' => 'spinach'
|
200
|
+
'features-spinach' => 'spinach'
|
192
201
|
}[type]
|
193
202
|
|
194
|
-
if test_framework == 'spinach'
|
195
|
-
type = 'features'
|
196
|
-
end
|
203
|
+
type = 'features' if test_framework == 'spinach'
|
197
204
|
# Using the relative path to find the binary allow to run a specific version of it
|
198
205
|
executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test')
|
199
206
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'parallel_tests'
|
2
3
|
|
3
4
|
module ParallelTests
|
@@ -32,7 +33,7 @@ module ParallelTests
|
|
32
33
|
# --- usually used by other runners
|
33
34
|
|
34
35
|
# finds all tests and partitions them into groups
|
35
|
-
def tests_in_groups(tests, num_groups, options={})
|
36
|
+
def tests_in_groups(tests, num_groups, options = {})
|
36
37
|
tests = tests_with_size(tests, options)
|
37
38
|
Grouper.in_even_groups_by_size(tests, num_groups, options)
|
38
39
|
end
|
@@ -46,10 +47,17 @@ module ParallelTests
|
|
46
47
|
when :filesize
|
47
48
|
sort_by_filesize(tests)
|
48
49
|
when :runtime
|
49
|
-
sort_by_runtime(
|
50
|
+
sort_by_runtime(
|
51
|
+
tests, runtimes(tests, options),
|
52
|
+
options.merge(allowed_missing: (options[:allowed_missing_percent] || 50) / 100.0)
|
53
|
+
)
|
50
54
|
when nil
|
51
55
|
# use recorded test runtime if we got enough data
|
52
|
-
runtimes =
|
56
|
+
runtimes = begin
|
57
|
+
runtimes(tests, options)
|
58
|
+
rescue StandardError
|
59
|
+
[]
|
60
|
+
end
|
53
61
|
if runtimes.size * 1.5 > tests.size
|
54
62
|
puts "Using recorded test runtime"
|
55
63
|
sort_by_runtime(tests, runtimes)
|
@@ -67,7 +75,7 @@ module ParallelTests
|
|
67
75
|
env = (options[:env] || {}).merge(
|
68
76
|
"TEST_ENV_NUMBER" => test_env_number(process_number, options).to_s,
|
69
77
|
"PARALLEL_TEST_GROUPS" => num_processes.to_s,
|
70
|
-
"PARALLEL_PID_FILE" => ParallelTests.pid_file_path
|
78
|
+
"PARALLEL_PID_FILE" => ParallelTests.pid_file_path
|
71
79
|
)
|
72
80
|
cmd = "nice #{cmd}" if options[:nice]
|
73
81
|
cmd = "#{cmd} 2>&1" if options[:combine_stderr]
|
@@ -86,13 +94,11 @@ module ParallelTests
|
|
86
94
|
end
|
87
95
|
ParallelTests.pids.delete(pid) if pid
|
88
96
|
exitstatus = $?.exitstatus
|
89
|
-
seed = output[/seed (\d+)/,1]
|
97
|
+
seed = output[/seed (\d+)/, 1]
|
90
98
|
|
91
|
-
if report_process_command?(options) && options[:serialize_stdout]
|
92
|
-
output = [cmd, output].join("\n")
|
93
|
-
end
|
99
|
+
output = [cmd, output].join("\n") if report_process_command?(options) && options[:serialize_stdout]
|
94
100
|
|
95
|
-
{:
|
101
|
+
{ stdout: output, exit_status: exitstatus, command: cmd, seed: seed }
|
96
102
|
end
|
97
103
|
|
98
104
|
def find_results(test_output)
|
@@ -104,7 +110,7 @@ module ParallelTests
|
|
104
110
|
end.compact
|
105
111
|
end
|
106
112
|
|
107
|
-
def test_env_number(process_number, options={})
|
113
|
+
def test_env_number(process_number, options = {})
|
108
114
|
if process_number == 0 && !options[:first_is_1]
|
109
115
|
''
|
110
116
|
else
|
@@ -114,7 +120,7 @@ module ParallelTests
|
|
114
120
|
|
115
121
|
def summarize_results(results)
|
116
122
|
sums = sum_up_results(results)
|
117
|
-
sums.sort.map{|word, number|
|
123
|
+
sums.sort.map { |word, number| "#{number} #{word}#{'s' if number != 1}" }.join(', ')
|
118
124
|
end
|
119
125
|
|
120
126
|
# remove old seed and add new seed
|
@@ -134,19 +140,18 @@ module ParallelTests
|
|
134
140
|
end
|
135
141
|
|
136
142
|
def sum_up_results(results)
|
137
|
-
results = results.join(' ').gsub(/s\b/,'') # combine and singularize results
|
143
|
+
results = results.join(' ').gsub(/s\b/, '') # combine and singularize results
|
138
144
|
counts = results.scan(/(\d+) (\w+)/)
|
139
|
-
counts.
|
145
|
+
counts.each_with_object(Hash.new(0)) do |(number, word), sum|
|
140
146
|
sum[word] += number.to_i
|
141
|
-
sum
|
142
147
|
end
|
143
148
|
end
|
144
149
|
|
145
150
|
# read output of the process and print it in chunks
|
146
|
-
def capture_output(out, env, options={})
|
147
|
-
result = ""
|
148
|
-
|
149
|
-
|
151
|
+
def capture_output(out, env, options = {})
|
152
|
+
result = +""
|
153
|
+
begin
|
154
|
+
loop do
|
150
155
|
read = out.readpartial(1000000) # read whatever chunk we can get
|
151
156
|
if Encoding.default_internal
|
152
157
|
read = read.force_encoding(Encoding.default_internal)
|
@@ -159,11 +164,13 @@ module ParallelTests
|
|
159
164
|
$stdout.flush
|
160
165
|
end
|
161
166
|
end
|
162
|
-
|
167
|
+
rescue EOFError
|
168
|
+
nil
|
169
|
+
end
|
163
170
|
result
|
164
171
|
end
|
165
172
|
|
166
|
-
def sort_by_runtime(tests, runtimes, options={})
|
173
|
+
def sort_by_runtime(tests, runtimes, options = {})
|
167
174
|
allowed_missing = options[:allowed_missing] || 1.0
|
168
175
|
allowed_missing = tests.size * allowed_missing
|
169
176
|
|
@@ -178,9 +185,7 @@ module ParallelTests
|
|
178
185
|
[test, time]
|
179
186
|
end
|
180
187
|
|
181
|
-
if options[:verbose]
|
182
|
-
puts "Runtime found for #{tests.count(&:last)} of #{tests.size} tests"
|
183
|
-
end
|
188
|
+
puts "Runtime found for #{tests.count(&:last)} of #{tests.size} tests" if options[:verbose]
|
184
189
|
|
185
190
|
set_unknown_runtime tests, options
|
186
191
|
end
|
@@ -190,7 +195,7 @@ module ParallelTests
|
|
190
195
|
lines = File.read(log).split("\n")
|
191
196
|
lines.each_with_object({}) do |line, times|
|
192
197
|
test, _, time = line.rpartition(':')
|
193
|
-
next unless test
|
198
|
+
next unless test && time
|
194
199
|
times[test] = time.to_f if tests.include?(test)
|
195
200
|
end
|
196
201
|
end
|
@@ -217,7 +222,7 @@ module ParallelTests
|
|
217
222
|
end.uniq
|
218
223
|
end
|
219
224
|
|
220
|
-
def files_in_folder(folder, options={})
|
225
|
+
def files_in_folder(folder, options = {})
|
221
226
|
pattern = if options[:symlinks] == false # not nil or true
|
222
227
|
"**/*"
|
223
228
|
else
|
@@ -225,7 +230,7 @@ module ParallelTests
|
|
225
230
|
# http://stackoverflow.com/questions/357754/can-i-traverse-symlinked-directories-in-ruby-with-a-glob
|
226
231
|
"**{,/*/**}/*"
|
227
232
|
end
|
228
|
-
Dir[File.join(folder, pattern)].uniq
|
233
|
+
Dir[File.join(folder, pattern)].uniq.sort
|
229
234
|
end
|
230
235
|
|
231
236
|
private
|
@@ -236,7 +241,7 @@ module ParallelTests
|
|
236
241
|
known, unknown = tests.partition(&:last)
|
237
242
|
return if unknown.empty?
|
238
243
|
unknown_runtime = options[:unknown_runtime] ||
|
239
|
-
(known.empty? ? 1 : known.map!(&:last).
|
244
|
+
(known.empty? ? 1 : known.map!(&:last).sum / known.size) # average
|
240
245
|
unknown.each { |set| set[1] = unknown_runtime }
|
241
246
|
end
|
242
247
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'parallel_tests'
|
2
3
|
require 'parallel_tests/test/runner'
|
3
4
|
|
@@ -22,7 +23,7 @@ module ParallelTests
|
|
22
23
|
separator = "\n"
|
23
24
|
groups = logfile.read.split(separator).map { |line| line.split(":") }.group_by(&:first)
|
24
25
|
lines = groups.map do |file, times|
|
25
|
-
time = "%.2f" % times.map(&:last).map(&:to_f).
|
26
|
+
time = "%.2f" % times.map(&:last).map(&:to_f).sum
|
26
27
|
"#{file}:#{time}"
|
27
28
|
end
|
28
29
|
logfile.rewind
|
@@ -34,7 +35,7 @@ module ParallelTests
|
|
34
35
|
private
|
35
36
|
|
36
37
|
def with_locked_log
|
37
|
-
File.open(logfile, File::RDWR|File::CREAT) do |logfile|
|
38
|
+
File.open(logfile, File::RDWR | File::CREAT) do |logfile|
|
38
39
|
logfile.flock(File::LOCK_EX)
|
39
40
|
yield logfile
|
40
41
|
end
|
@@ -59,7 +60,7 @@ module ParallelTests
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def message(test, delta)
|
62
|
-
return unless method = test.public_instance_methods(true).detect { |
|
63
|
+
return unless method = test.public_instance_methods(true).detect { |m| m =~ /^test_/ }
|
63
64
|
filename = test.instance_method(method).source_location.first.sub("#{Dir.pwd}/", "")
|
64
65
|
"#{filename}:#{delta}"
|
65
66
|
end
|
@@ -74,22 +75,26 @@ end
|
|
74
75
|
|
75
76
|
if defined?(Minitest::Runnable) # Minitest 5
|
76
77
|
class << Minitest::Runnable
|
77
|
-
prepend(
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
prepend(
|
79
|
+
Module.new do
|
80
|
+
def run(*)
|
81
|
+
ParallelTests::Test::RuntimeLogger.log_test_run(self) do
|
82
|
+
super
|
83
|
+
end
|
81
84
|
end
|
82
85
|
end
|
83
|
-
|
86
|
+
)
|
84
87
|
end
|
85
88
|
|
86
89
|
class << Minitest
|
87
|
-
prepend(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
prepend(
|
91
|
+
Module.new do
|
92
|
+
def run(*args)
|
93
|
+
result = super
|
94
|
+
ParallelTests::Test::RuntimeLogger.unique_log
|
95
|
+
result
|
96
|
+
end
|
92
97
|
end
|
93
|
-
|
98
|
+
)
|
94
99
|
end
|
95
100
|
end
|