🗂

test-queueを使ったRSpecの並列化

に公開

みなさんテスト書いてますか
テスト書いてないようじゃ無理か
テストはね〜書いとかないと

現在minitestからrspecへ移行しており、rspecのテスト時間が伸びてきているのでこのタイミングで並列化しちゃおうということで並列化することにしました

rspecの並列化で有名どころだと、parallel_testがありますが、なぜかCI上でだけテストが失敗してしまう現象が発生したのでやめました

今回はtest-queueを使ってRSpecを並列化してみました

結果的に8分くらいのテスト時間が2分弱に短縮されました!(4vCPUの場合)

test_queueの導入

まずはGemfileにtest-queueを追加します

Gemfile
group :test do
  gem "test-queue"
end

次にbundle-installを実行しましょう

テストランナーの実装

このままだと並列に動かすテストが全て同一のデータベースにアクセスしてしまうので、ランナーを実装しましょう
どんなファイル名でも良いですが、spec/runner.rbとしました

spec/runner.rb
#!/usr/bin/env ruby
# frozen_string_literal: true

ENV["RAILS_ENV"] = "test"
require File.expand_path("../config/environment", __dir__)

require "test_queue"
require "test_queue/runner/rspec"

class RSpecRunner < TestQueue::Runner::RSpec
  def after_fork(num)
    ::ActiveRecord::Base.configurations.configs_for(env_name: "test", name: "primary").database << num.to_s
    ::ActiveRecord::Base.establish_connection(:test)

    ::ActiveRecord::Tasks::DatabaseTasks.drop_current
    ::ActiveRecord::Tasks::DatabaseTasks.create_current
    ::ActiveRecord::Tasks::DatabaseTasks.load_schema_current
  end
end

RSpecRunner.new.execute

動かしてみよう

ここまでできたら、実施にテストを並列で動かしてみましょう!

spec/runner.rb spec

動きませんでした

はい、動きませんでした
通常のrspecだと動くのに、、、、

わけわからず調べていたら、webmockがうまく動いていなさそうなことがわかりました
なぜか本当に外部に通信しちゃってた

動きました!!!!!!!!!!!!!!!

とりあえずwebmockを強制的にONにしたらテストが通るようになりました

spec/rails_helper.rb
WebMock.enable!

まとめ

「テストはしっかり書きたいが、パイプラインが遅くなるとな〜」とお悩みの方はぜひ並列化を行なって、爆速パイプラインを実現しましょう!

wwwave's Techblog

Discussion