Class: ParallelTests::Test::Runner
- Inherits:
-
Object
- Object
- ParallelTests::Test::Runner
- Defined in:
- lib/parallel_tests/test/runner.rb
Direct Known Subclasses
Constant Summary collapse
- RuntimeLogTooSmallError =
Class.new(StandardError)
Class Method Summary collapse
-
.command_with_seed(cmd, seed) ⇒ Object
remove old seed and add new seed.
- .default_test_folder ⇒ Object
- .execute_command(cmd, process_number, num_processes, options) ⇒ Object
- .execute_command_and_capture_output(env, cmd, options) ⇒ Object
- .find_results(test_output) ⇒ Object
-
.line_is_result?(line) ⇒ Boolean
ignores other commands runner noise.
- .print_command(command, env) ⇒ Object
- .run_tests(test_files, process_number, num_processes, options) ⇒ Object
-
.runtime_log ⇒ Object
— usually overwritten by other runners.
- .summarize_results(results) ⇒ Object
- .test_env_number(process_number, options = {}) ⇒ Object
- .test_file_name ⇒ Object
- .test_suffix ⇒ Object
-
.tests_in_groups(tests, num_groups, options = {}) ⇒ Object
finds all tests and partitions them into groups.
- .tests_with_size(tests, options) ⇒ Object
Class Method Details
.command_with_seed(cmd, seed) ⇒ Object
remove old seed and add new seed
144 145 146 147 |
# File 'lib/parallel_tests/test/runner.rb', line 144 def command_with_seed(cmd, seed) clean = remove_command_arguments(cmd, '--seed') [*clean, '--seed', seed] end |
.default_test_folder ⇒ Object
21 22 23 |
# File 'lib/parallel_tests/test/runner.rb', line 21 def default_test_folder "test" end |
.execute_command(cmd, process_number, num_processes, options) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/parallel_tests/test/runner.rb', line 80 def execute_command(cmd, process_number, num_processes, ) number = test_env_number(process_number, ).to_s env = ([:env] || {}).merge( "TEST_ENV_NUMBER" => number, "PARALLEL_TEST_GROUPS" => num_processes.to_s, "PARALLEL_PID_FILE" => ParallelTests.pid_file_path ) cmd = ["nice", *cmd] if [:nice] # being able to run with for example `-output foo-$TEST_ENV_NUMBER` worked originally and is convenient cmd = cmd.map { |c| c.gsub("$TEST_ENV_NUMBER", number).gsub("${TEST_ENV_NUMBER}", number) } print_command(cmd, env) if report_process_command?() && ![:serialize_stdout] execute_command_and_capture_output(env, cmd, ) end |
.execute_command_and_capture_output(env, cmd, options) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/parallel_tests/test/runner.rb', line 102 def execute_command_and_capture_output(env, cmd, ) = {} # do not add `pgroup: true`, it will break `binding.irb` inside the test [:err] = [:child, :out] if [:combine_stderr] pid = nil output = IO.popen(env, cmd, ) do |io| pid = io.pid ParallelTests.pids.add(pid) capture_output(io, env, ) end ParallelTests.pids.delete(pid) if pid exitstatus = $?.exitstatus seed = output[/seed (\d+)/, 1] output = "#{Shellwords.shelljoin(cmd)}\n#{output}" if report_process_command?() && [:serialize_stdout] { env: env, stdout: output, exit_status: exitstatus, command: cmd, seed: seed } end |
.find_results(test_output) ⇒ Object
121 122 123 124 125 126 127 128 |
# File 'lib/parallel_tests/test/runner.rb', line 121 def find_results(test_output) test_output.lines.map do |line| line.chomp! line.gsub!(/\e\[\d+m/, '') # remove color coding next unless line_is_result?(line) line end.compact end |
.line_is_result?(line) ⇒ Boolean
ignores other commands runner noise
35 36 37 |
# File 'lib/parallel_tests/test/runner.rb', line 35 def line_is_result?(line) line =~ /\d+ failure(?!:)/ end |
.print_command(command, env) ⇒ Object
97 98 99 100 |
# File 'lib/parallel_tests/test/runner.rb', line 97 def print_command(command, env) env_str = ['TEST_ENV_NUMBER', 'PARALLEL_TEST_GROUPS'].map { |e| "#{e}=#{env[e]}" }.join(' ') puts [env_str, Shellwords.shelljoin(command)].compact.join(' ') end |
.run_tests(test_files, process_number, num_processes, options) ⇒ Object
29 30 31 32 |
# File 'lib/parallel_tests/test/runner.rb', line 29 def run_tests(test_files, process_number, num_processes, ) require_list = test_files.map { |file| file.gsub(" ", "\\ ") }.join(" ") execute_command(build_command(require_list, ), process_number, num_processes, ) end |
.runtime_log ⇒ Object
— usually overwritten by other runners
13 14 15 |
# File 'lib/parallel_tests/test/runner.rb', line 13 def runtime_log 'tmp/parallel_runtime_test.log' end |
.summarize_results(results) ⇒ Object
138 139 140 141 |
# File 'lib/parallel_tests/test/runner.rb', line 138 def summarize_results(results) sums = sum_up_results(results) sums.sort.map { |word, number| "#{number} #{word}#{'s' if number != 1}" }.join(', ') end |
.test_env_number(process_number, options = {}) ⇒ Object
130 131 132 133 134 135 136 |
# File 'lib/parallel_tests/test/runner.rb', line 130 def test_env_number(process_number, = {}) if process_number == 0 && ![:first_is_1] '' else process_number + 1 end end |
.test_file_name ⇒ Object
25 26 27 |
# File 'lib/parallel_tests/test/runner.rb', line 25 def test_file_name "test" end |
.test_suffix ⇒ Object
17 18 19 |
# File 'lib/parallel_tests/test/runner.rb', line 17 def test_suffix /_(test|spec).rb$/ end |
.tests_in_groups(tests, num_groups, options = {}) ⇒ Object
finds all tests and partitions them into groups
42 43 44 45 |
# File 'lib/parallel_tests/test/runner.rb', line 42 def tests_in_groups(tests, num_groups, = {}) tests = tests_with_size(tests, ) Grouper.in_even_groups_by_size(tests, num_groups, ) end |
.tests_with_size(tests, options) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/parallel_tests/test/runner.rb', line 47 def tests_with_size(tests, ) tests = find_tests(tests, ) case [:group_by] when :found tests.map! { |t| [t, 1] } when :filesize sort_by_filesize(tests) when :runtime sort_by_runtime( tests, runtimes(tests, ), .merge(allowed_missing: ([:allowed_missing_percent] || 50) / 100.0) ) when nil # use recorded test runtime if we got enough data runtimes = begin runtimes(tests, ) rescue StandardError [] end if runtimes.size * 1.5 > tests.size puts "Using recorded test runtime" unless [:quiet] sort_by_runtime(tests, runtimes) else sort_by_filesize(tests) end else raise ArgumentError, "Unsupported option #{options[:group_by]}" end tests end |