RSpecでsampleするとコケるんだけど特定しづらい…みたいな奴を解消する。
環境
$ ruby -v ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin18] $ bin/rails --version Rails 5.2.2 $ bundle exec rspec --version RSpec 3.8 - rspec-core 3.8.0 - rspec-expectations 3.8.2 - rspec-mocks 3.8.0 - rspec-rails 3.8.1 - rspec-support 3.8.0
やり方
spec_helperでsrandのseed値を固定する
bin/rails g rspec:install
で生成される rspec_helperだと以下のようにbeginでまるまるコメントアウトされているので直す(昔はコメントアウトされてなかったみたいなの場合によって齟齬がある)
# The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin # This allows you to limit a spec run to individual examples or groups # you care about by tagging them with `:focus` metadata. When nothing # is tagged with `:focus`, all examples get run. RSpec also provides # aliases for `it`, `describe`, and `context` that include `:focus` # metadata: `fit`, `fdescribe` and `fcontext`, respectively. config.filter_run_when_matching :focus #### 中略 #### # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 config.order = :random # Seed global randomization in this process using the `--seed` CLI option. # Setting this allows you to use `--seed` to deterministically reproduce # test failures related to randomization by passing the same `--seed` value # as the one that triggered the failure. Kernel.srand config.seed =end
Kernel.srand config.seed
これを指定すると rand
にまつわるものはすべてseed値が rspecの --seed {{seed数値}}
もしくは --order rand:{{seed数値}}
のオプションのseed数値を使うようになる。
rspec実行時に指定する
前述通りseedの値を指定する
bundle exec rspec --seed {{seed数値}}
もしくは
bundle exec rspec --order rand:{{seed数値}}
※もともとのRSpecのオプションとしては order とあるとおりテスト順番を変えるためのものなので注意
例
対象とするコード
1から10000の値の数値が入った配列からsampleで1個取り出す
▼ spec/sample/demo_spec.rb
require 'rails_helper' RSpec.describe "sample" do let(:demo_array) { (1..10000).map{|x| x} } subject { demo_array.sample} context "sample実行した場合" do it "期待した結果が返ってくる" do expect(subject).to eq(1548) end end end
spec_helplerの値をコメントアウトした状態の場合
▼実行1回目
$ bundle exec rspec spec/sample/demo_spec.rb F Failures: 1) sample sample実行した場合 期待した結果が返ってくる Failure/Error: expect(subject).to eq(1548) expected: 1548 got: 6736 (compared using ==) # ./spec/sample/demo_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.02443 seconds (files took 7.75 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/sample/demo_spec.rb:8 # sample sample実行した場合 期待した結果が返ってくる
▼実行2回目
$ bundle exec rspec spec/sample/demo_spec.rb F Failures: 1) sample sample実行した場合 期待した結果が返ってくる Failure/Error: expect(subject).to eq(1548) expected: 1548 got: 9457 (compared using ==) # ./spec/sample/demo_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.02021 seconds (files took 5.08 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/sample/demo_spec.rb:8 # sample sample実行した場合 期待した結果が返ってくる
実行毎に数値が違う。
ではそのまま --seed
をつけるとどうなるか
▼seedつけて1回目
$ bundle exec rspec spec/sample/demo_spec.rb --seed 100 Randomized with seed 100 F Failures: 1) sample sample実行した場合 期待した結果が返ってくる Failure/Error: expect(subject).to eq(1548) expected: 1548 got: 6560 (compared using ==) # ./spec/sample/demo_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.01806 seconds (files took 2.08 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/sample/demo_spec.rb:8 # sample sample実行した場合 期待した結果が返ってくる Randomized with seed 100
▼seedつけて2回目
$ bundle exec rspec spec/sample/demo_spec.rb --seed 100 Randomized with seed 100 F Failures: 1) sample sample実行した場合 期待した結果が返ってくる Failure/Error: expect(subject).to eq(1548) expected: 1548 got: 2008 (compared using ==) # ./spec/sample/demo_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.01302 seconds (files took 2.04 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/sample/demo_spec.rb:8 # sample sample実行した場合 期待した結果が返ってくる Randomized with seed 100
特に固定はされない
spec_helperで Kernel.srand config.seed
を指定した場合
ちゃんとspec_helperに記述して、--seed
をつけてやってみる
▼seedつけて1回目
$ bundle exec rspec spec/sample/demo_spec.rb --seed 100 Randomized with seed 100 F Failures: 1) sample sample実行した場合 期待した結果が返ってくる Failure/Error: expect(subject).to eq(1548) expected: 1548 got: 5641 (compared using ==) # ./spec/sample/demo_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.02062 seconds (files took 4.1 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/sample/demo_spec.rb:8 # sample sample実行した場合 期待した結果が返ってくる Randomized with seed 100
▼seedつけて2回目
$ bundle exec rspec spec/sample/demo_spec.rb --seed 100 Randomized with seed 100 F Failures: 1) sample sample実行した場合 期待した結果が返ってくる Failure/Error: expect(subject).to eq(1548) expected: 1548 got: 5641 (compared using ==) # ./spec/sample/demo_spec.rb:9:in `block (3 levels) in <top (required)>' Finished in 0.02198 seconds (files took 4.91 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/sample/demo_spec.rb:8 # sample sample実行した場合 期待した結果が返ってくる Randomized with seed 100
5641で固定された。