class KnapsackPro::Adapters::RSpecAdapter

Constants

TEST_DIR_PATTERN

Public Class Methods

ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 39
def self.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
  if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
    error_message = "It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature. Please see: #{KnapsackPro::Urls::RSPEC__SPLIT_BY_TEST_EXAMPLES__TAG}"
    KnapsackPro.logger.error(error_message)
    raise error_message
  end
end
file_path_for(example) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 63
def self.file_path_for(example)
  [
    -> { parse_file_path(example.id) },
    -> { example.metadata[:file_path] },
    -> { example.metadata[:example_group][:file_path] },
    -> { top_level_group(example)[:file_path] },
  ]
    .each do |path|
      p = path.call
      return p if p.include?('_spec.rb') || p.include?('.feature')
    end

  return ''
end
has_format_option?(cli_args) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 51
def self.has_format_option?(cli_args)
  !!parsed_options(cli_args)&.[](:formatters)
end
has_require_rails_helper_option?(cli_args) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 55
def self.has_require_rails_helper_option?(cli_args)
  (parsed_options(cli_args)&.[](:requires) || []).include?("rails_helper")
end
has_tag_option?(cli_args) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 47
def self.has_tag_option?(cli_args)
  !!parsed_options(cli_args)&.[](:inclusion_filter)
end
order_option(cli_args) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 59
def self.order_option(cli_args)
  parsed_options(cli_args)&.[](:order)
end
parse_file_path(id) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 78
def self.parse_file_path(id)
  # https://github.com/rspec/rspec-core/blob/1eeadce5aa7137ead054783c31ff35cbfe9d07cc/lib/rspec/core/example.rb#L122
  id.match(/\A(.*?)(?:\[([\d\s:,]+)\])?\z/).captures.first
end
parsed_options(cli_args) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 161
def self.parsed_options(cli_args)
  ::RSpec::Core::Parser.parse(cli_args)
rescue SystemExit
  nil
end
rails_helper_exists?(test_dir) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 83
def self.rails_helper_exists?(test_dir)
  File.exist?("#{test_dir}/rails_helper.rb")
end
rspec_configuration() click to toggle source

Hide RSpec configuration so that we could mock it in the spec. Mocking existing RSpec configuration could impact test’s runtime.

# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 157
def self.rspec_configuration
  ::RSpec.configuration
end
split_by_test_cases_enabled?() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 10
def self.split_by_test_cases_enabled?
  return false unless KnapsackPro::Config::Env.rspec_split_by_test_examples?

  require 'rspec/core/version'
  unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
    raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
  end

  true
end
test_file_cases_for(slow_test_files) click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 21
def self.test_file_cases_for(slow_test_files)
  KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing #{slow_test_files.size} slow test files.")

  # generate the RSpec JSON report in a separate process to not pollute the RSpec state
  cmd = [
    'RACK_ENV=test',
    'RAILS_ENV=test',
    KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
    'rake knapsack_pro:rspec_test_example_detector',
  ].join(' ')
  unless Kernel.system(cmd)
    raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
  end

  # read the JSON report
  KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new.test_file_example_paths
end
top_level_group(example) click to toggle source

private

# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 88
def self.top_level_group(example)
  group = example.metadata[:example_group]
  until group[:parent_example_group].nil?
    group = group[:parent_example_group]
  end
  group
end

Public Instance Methods

bind_after_queue_hook() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 145
def bind_after_queue_hook
  ::RSpec.configure do |config|
    config.after(:suite) do
      KnapsackPro::Hooks::Queue.call_after_queue
    end
  end
end
bind_before_queue_hook() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 137
def bind_before_queue_hook
  ::RSpec.configure do |config|
    config.before(:suite) do
      KnapsackPro::Hooks::Queue.call_before_queue
    end
  end
end
bind_save_report() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 128
def bind_save_report
  ::RSpec.configure do |config|
    config.after(:suite) do
      time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
      KnapsackPro::Report.save(time_tracker.batch)
    end
  end
end
bind_time_tracker() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 96
def bind_time_tracker
  ensure_no_focus!
  log_tests_duration
end
ensure_no_focus!() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 101
def ensure_no_focus!
  ::RSpec.configure do |config|
    config.around(:each) do |example|
      if example.metadata[:focus] && KnapsackPro::Adapters::RSpecAdapter.rspec_configuration.filter.rules[:focus]
        file_path = KnapsackPro::Adapters::RSpecAdapter.file_path_for(example)
        file_path = KnapsackPro::TestFileCleaner.clean(file_path)

        raise "Knapsack Pro found an example tagged with focus in #{file_path}, please remove it. See more: #{KnapsackPro::Urls::RSPEC__SKIPS_TESTS}"
      end

      example.run
    end
  end
end
log_tests_duration() click to toggle source
# File lib/knapsack_pro/adapters/rspec_adapter.rb, line 116
def log_tests_duration
  ::RSpec.configure do |config|
    config.append_after(:suite) do
      time_tracker = KnapsackPro::Formatters::TimeTrackerFetcher.call
      if time_tracker
        formatted = KnapsackPro::Presenter.global_time(time_tracker.duration)
        KnapsackPro.logger.debug(formatted)
      end
    end
  end
end