Class: ParallelTests::Test::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/parallel_tests/test/runner.rb

Direct Known Subclasses

Gherkin::Runner, RSpec::Runner

Constant Summary collapse

NAME =
'Test'

Class Method Summary collapse

Class Method Details

.execute_command(cmd, process_number, num_processes, options) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/parallel_tests/test/runner.rb', line 72

def execute_command(cmd, process_number, num_processes, options)
  env = (options[:env] || {}).merge(
    "TEST_ENV_NUMBER" => test_env_number(process_number, options),
    "PARALLEL_TEST_GROUPS" => num_processes
  )
  cmd = "nice #{cmd}" if options[:nice]
  cmd = "#{cmd} 2>&1" if options[:combine_stderr]
  puts cmd if options[:verbose]

  execute_command_and_capture_output(env, cmd, options[:serialize_stdout])
end

.execute_command_and_capture_output(env, cmd, silence) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/parallel_tests/test/runner.rb', line 84

def execute_command_and_capture_output(env, cmd, silence)
  # make processes descriptive / visible in ps -ef
  separator = (WINDOWS ? ' & ' : ';')
  exports = env.map do |k,v|
    if WINDOWS
      "(SET \"#{k}=#{v}\")"
    else
      "#{k}=#{v};export #{k}"
    end
  end.join(separator)
  cmd = "#{exports}#{separator}#{cmd}"

  output = open("|#{cmd}", "r") { |output| capture_output(output, silence) }
  exitstatus = $?.exitstatus

  {:stdout => output, :exit_status => exitstatus}
end

.find_results(test_output) ⇒ Object



102
103
104
105
106
107
108
# File 'lib/parallel_tests/test/runner.rb', line 102

def find_results(test_output)
  test_output.split("\n").map {|line|
    line.gsub!(/\e\[\d+m/,'')
    next unless line_is_result?(line)
    line
  }.compact
end

.line_is_result?(line) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
36
# File 'lib/parallel_tests/test/runner.rb', line 33

def line_is_result?(line)
  line.gsub!(/[.F*]/,'')
  line =~ /\d+ failure/
end

.nameObject

— usually overwritten by other runners



11
12
13
# File 'lib/parallel_tests/test/runner.rb', line 11

def name
  NAME
end

.run_tests(test_files, process_number, num_processes, options) ⇒ Object



27
28
29
30
31
# File 'lib/parallel_tests/test/runner.rb', line 27

def run_tests(test_files, process_number, num_processes, options)
  require_list = test_files.map { |file| file.sub(" ", "\\ ") }.join(" ")
  cmd = "#{executable} -Itest -e '%w[#{require_list}].each { |f| require %{./\#{f}} }' -- #{options[:test_options]}"
  execute_command(cmd, process_number, num_processes, options)
end

.runtime_logObject



15
16
17
# File 'lib/parallel_tests/test/runner.rb', line 15

def runtime_log
  'tmp/parallel_runtime_test.log'
end

.summarize_results(results) ⇒ Object



115
116
117
118
# File 'lib/parallel_tests/test/runner.rb', line 115

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



110
111
112
113
# File 'lib/parallel_tests/test/runner.rb', line 110

def test_env_number(process_number, options)
  n = options[:advance_number].to_i + process_number + 1
  n == 0 ? '' : n
end

.test_file_nameObject



23
24
25
# File 'lib/parallel_tests/test/runner.rb', line 23

def test_file_name
  "test"
end

.test_suffixObject



19
20
21
# File 'lib/parallel_tests/test/runner.rb', line 19

def test_suffix
  /_(test|spec).rb$/
end

.tests_in_groups(tests, num_groups, options = {}) ⇒ Object

finds all tests and partitions them into groups



41
42
43
44
# File 'lib/parallel_tests/test/runner.rb', line 41

def tests_in_groups(tests, num_groups, options={})
  tests = tests_with_size(tests, options)
  Grouper.in_even_groups_by_size(tests, num_groups, options)
end

.tests_with_size(tests, options) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/parallel_tests/test/runner.rb', line 46

def tests_with_size(tests, options)
  tests = find_tests(tests, options)

  case options[:group_by]
  when :found
    tests.map! { |t| [t, 1] }
  when :filesize
    sort_by_filesize(tests)
  when :runtime
    sort_by_runtime(tests, runtimes(tests, options), options.merge(allowed_missing: 0.5))
  when nil
    # use recorded test runtime if we got enough data
    runtimes = runtimes(tests, options) rescue []
    if runtimes.size * 1.5 > tests.size
      puts "Using recorded test runtime"
      sort_by_runtime(tests, runtimes)
    else
      sort_by_filesize(tests)
    end
  else
    raise ArgumentError, "Unsupported option #{options[:group_by]}"
  end

  tests
end