Class: KnapsackPro::Runners::Queue::RSpecRunner

Inherits:
BaseRunner
  • Object
show all
Defined in:
lib/knapsack_pro/runners/queue/rspec_runner.rb

Constant Summary

Constants inherited from BaseRunner

BaseRunner::TERMINATION_SIGNALS, BaseRunner::TerminationError

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseRunner

child_status, handle_signal!, run_tests, set_terminate_process, #test_dir, #test_file_paths

Constructor Details

#initialize(adapter_class, rspec_pure, args, stream_error, stream_out) ⇒ RSpecRunner

Returns a new instance of RSpecRunner.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/knapsack_pro/runners/queue/rspec_runner.rb', line 24

def initialize(adapter_class, rspec_pure, args, stream_error, stream_out)
  ENV['KNAPSACK_PRO_RSPEC_OPTIONS'] = args.to_s
  super(adapter_class)
  @adapter_class = adapter_class
  @rspec_pure = rspec_pure
  args_array = (args || '').split
  has_format_option = @adapter_class.has_format_option?(args_array)
  has_require_rails_helper_option = @adapter_class.has_require_rails_helper_option?(args_array)
  rails_helper_exists = @adapter_class.rails_helper_exists?(test_dir)
  @cli_args = rspec_pure.prepare_cli_args(args, has_format_option, has_require_rails_helper_option, rails_helper_exists, test_dir)
  @stream_error = stream_error
  @stream_out = stream_out
  @node_test_file_paths = []
  @rspec_runner = nil # RSpec::Core::Runner is lazy initialized
  @queue = KnapsackPro::Queue.new
end

Class Method Details

.run(args, stream_error = $stderr, stream_out = $stdout) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/knapsack_pro/runners/queue/rspec_runner.rb', line 7

def self.run(args, stream_error = $stderr, stream_out = $stdout)
  require 'rspec/core'
  require_relative '../../extensions/rspec_extension'
  require_relative '../../formatters/time_tracker'
  require_relative '../../formatters/time_tracker_fetcher'

  KnapsackPro::Extensions::RSpecExtension.setup!

  ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec
  ENV['KNAPSACK_PRO_NODE_UUID'] = SecureRandom.uuid

  rspec_pure = KnapsackPro::Pure::Queue::RSpecPure.new

  queue_runner = new(KnapsackPro::Adapters::RSpecAdapter, rspec_pure, args, stream_error, stream_out)
  queue_runner.run
end

Instance Method Details

#handle_signal!Object



112
113
114
# File 'lib/knapsack_pro/runners/queue/rspec_runner.rb', line 112

def handle_signal!
  self.class.handle_signal!
end

#log_fail_fast_limit_metObject



116
117
118
# File 'lib/knapsack_pro/runners/queue/rspec_runner.rb', line 116

def log_fail_fast_limit_met
  KnapsackPro.logger.warn('Test execution has been canceled because the RSpec --fail-fast option is enabled. It will cause other CI nodes to run tests longer because they need to consume more tests from the Knapsack Pro Queue API.')
end

#runFixnum

Returns:

  • (Fixnum)

    exit status code. 0 if all specs passed, or the configured failure exit code (1 by default) if specs failed.



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
# File 'lib/knapsack_pro/runners/queue/rspec_runner.rb', line 47

def run
  pre_run_setup

  if @rspec_runner.knapsack__wants_to_quit?
    exit_code = @rspec_runner.knapsack__exit_early
    Kernel.exit(exit_code)
  end

  begin
    exit_code = @rspec_runner.knapsack__run_specs(self)
  rescue KnapsackPro::Runners::Queue::BaseRunner::TerminationError
    exit_code = @rspec_pure.error_exit_code(@rspec_runner.knapsack__error_exit_code)
    Kernel.exit(exit_code)
  rescue KnapsackPro::QueueAllocator::FallbackModeError
    exit_code = KnapsackPro::Config::Env.fallback_mode_error_exit_code
    Kernel.exit(exit_code)
  rescue Exception => exception
    KnapsackPro.logger.error("An unexpected exception happened. RSpec cannot handle it. The exception: #{exception.inspect}")
    KnapsackPro.logger.error("Exception message: #{exception.message}")
    KnapsackPro.logger.error("Exception backtrace: #{exception.backtrace&.join("\n")}")

    message = @rspec_pure.exit_summary(unexecuted_test_paths)
    KnapsackPro.logger.warn(message) if message

    exit_code = @rspec_pure.error_exit_code(@rspec_runner.knapsack__error_exit_code)
    Kernel.exit(exit_code)
  end

  post_run_tasks(exit_code)
end

#with_batchObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/knapsack_pro/runners/queue/rspec_runner.rb', line 78

def with_batch
  can_initialize_queue = true

  loop do
    handle_signal!
    test_file_paths = pull_tests_from_queue(can_initialize_queue: can_initialize_queue)
    can_initialize_queue = false

    break if test_file_paths.empty?

    subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id
    ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id

    @queue.add_batch_for(test_file_paths)

    KnapsackPro::Hooks::Queue.call_before_subset_queue(@queue)

    yield test_file_paths, @queue

    KnapsackPro::Hooks::Queue.call_after_subset_queue(@queue)

    if @rspec_runner.knapsack__wants_to_quit?
      KnapsackPro.logger.warn('RSpec wants to quit.')
      set_terminate_process
    end
    if @rspec_runner.knapsack__rspec_is_quitting?
      KnapsackPro.logger.warn('RSpec is quitting.')
      set_terminate_process
    end

    log_rspec_batch_command(test_file_paths)
  end
end