24
24

More than 5 years have passed since last update.

RSpecで外部プロセスを必要とするテスト実行するためのスニペット

Last updated at Posted at 2014-10-26

# spec/support下に配置しておく

# @param [Hash] options Any of :log, :env, :pwd, :command, :stdout_log, :stderr_log, :spawn_options, :spawn_checker, :timeout
def spawn_process(options = {})
  env = options[:env] || {}
  command = options[:command]
  stdout_log = options[:stdout_log] ? [options[:stdout_log], 'w'] : :out
  stderr_log = options[:stderr_log] ? [options[:stderr_log], 'w'] : :err
  pwd = options[:pwd]
  spawn_options = {
    :out => stdout_log,
    :err => stderr_log,
  }
  spawn_options.merge!(:chdir => pwd) if pwd
  spawn_options.merge!(options[:spawn_options]) if options[:spawn_options]
  spawn_checker = options[:spawn_checker]
  timeout_sec = options[:timeout] || 30

  ::ActiveRecord::Base.clear_all_connections!
  pid = spawn(env, command, spawn_options)
  ::ActiveRecord::Base.establish_connection

  at_exit do
    begin
      Process.kill(:SIGINT, pid)
      Process.waitpid(pid)
    rescue Errno::ESRCH, Errno::ECHILD
    end
  end

  if spawn_checker
    begin
      timeout(timeout_sec) do
        until spawn_checker.call
          Process.kill 0, pid # live check. Raise Errno::ESRCH if process died
          sleep 0.1
        end
      end
    rescue Timeout::Error, Errno::ESRCH
      STDERR.puts("Failed to start the backend program #{options.inspect}")
      if File.exist?(stdout_log)
        STDERR.puts(File.read(stdout_log))
      end
    end
  end

  pid
end

# spec_helperの例

  config.before(:each, redis: true) do
    unless $redis_pid
      $redis_pid = spawn_process(
        command: "redis-server #{Rails.root.join('spec', 'redis_test.conf')}",
        spawn_checker: -> { sleep 0.2; true },
      )
    end
    Redis.new(url: redis_url).flushall
  end

  config.before(:each, sidekiq: true) do
    Sidekiq::Testing.disable!

    unless $sidekiq_pid
      log = Rails.root.join('log', 'sidekiq_test.log').to_s
      $sidekiq_pid = spawn_process(
        command: "bundle exec sidekiq -q seirenes -c 1",
        env: {"REDIS_PORT" => "6380"},
        stdout_log: log,
        spawn_checker: -> { File.read(log) =~ /Starting processing/ },
      )
    end
  end

  config.after(:each, sidekiq: true) do
    Sidekiq::Testing.fake!
  end

24
24
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
24