RSpec

概要

RSpecはRubyのテストフレームワーク。Rails開発でよく使われる。

Memo

within

セレクトボックスをクリックしてから選択、というような場合capybaraは不安定になることがある。 まだ表示されてないのに、クリックするためにクリックするポイントがずれたりする。

安直なのはsleepすることだが、いい方法もある。 親要素全体が表示されてから、クリックする。

within '親要素' do
  find('li', text: 'セレクトボックスの中身').click
end

system specとそのrandom落ち (flaky test) との戦い

ENVをテストするためのヘルパー

ENVを変えてテストしたいときがある。 https://github.com/rspec/rspec-rails/issues/1279#issuecomment-70275896 ヘルパーを追加する。

module EnvHelpers
  def with_env_vars(vars)
    original = ENV.to_hash
    vars.each { |k, v| ENV[k] = v }

    begin
      yield
    ensure
      ENV.replace(original)
    end
  end
end
RSpec.configure do |c|
  c.include EnvHelpers
end
it 'does something with the FOO environment variable' do
  with_env_vars 'FOO' => 'bar' do
    # logic that depends upon ENV['FOO'] goes here
  end
end

テスト結果にSQLを出力する

どのようなSQLが発行されるか確認できると便利。

RSpec.describe do
  before do
    ActiveRecord::Base.logger = Logger.new(STDOUT)
  end

  it do
    ...
  end
end

request specでsessionメソッドを使う

allow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return({})

simplecovカバレッジ

COVERAGE=true bundle exec rspec spec/requests/user_spec.rb
open coverage/index.html

たまに失敗するパターン

system specではよくある。

読み込み前に検証して失敗する

expect(page).to have_text 'aaa', wait: 5 #発見できなかったときの最大待ち時間を伸ばす

並び順に依存したテスト

同じ秒数に作成されたとき、createした順番に並ばない可能性がある。

model1 = create(:model)
model2 = create(:model)

created_atでソートして表示しているとして、この作成順にソートされるわけではない。 秒数が同じときはidなどがソートに使われるだろう。 1つcreateするのにはわずかな時間なので、たまに失敗するだけで気づきにくい。

チェックボックス

チェックに少し時間がかかるのでたまにチェックせずに送信して失敗する。

check aaa
expect(page).to have_checked_field(aaa), wait 5 # チェックを確認する

Tasks

Archives

Reference

Better Specs. Testing Guidelines for Developers.

RSpecのベストプラクティス集。

Introduction - rspec-style-guide

可読性の高いテストコードを書くためのRSpecのスタイルガイド。