処理が速すぎてエラー?一時停止はsleepメソッド

f:id:endoakak:20200725102930j:plain

フリマアプリ製作の中で一番詰まったところだったのと、原因がなかなかに予想外だったので、記録に残しておこうと思いました。

空のテストコードでMySQLエラー

下のようなテストコードを作成しました。DealShipmentはActiveModel::Modelを使って作成したフォームオブジェクトです。

RSpec.describe DealShipment, type: :model do
  describe "購入情報の保存" do
    before do
      user = FactoryBot.create(:user)
      item = FactoryBot.build(:item)
      item.image = fixture_file_upload("public/images/test_image.png")
      item.save
      @deal_shipment = FactoryBot.build(:deal_shipment, user_id: user.id, item_id: item.id)
    end

    it "全ての値が正しく入力されていれば保存できる" do
      expect(@deal_shipment).to be_valid
    end

    it "郵便番号にハイフンがないと保存できない" do
    end

    it "郵便番号が空だと保存できない" do
    end

    it "都道府県が空だと保存できない" do
    end

    it "市区町村が空だと保存できない" do
    end

    it "市区町村に半角文字が入っていると保存できない" do
    end

    it "番地が空だと保存できない" do
    end

    it "電話番号が空だと保存できない" do
    end

    it "電話番号が12桁以上だと保存できない" do
    end
  end
end

exampleの中身を記述する前にテストコードを実行してみたら、次のようなエラーが出ました。

f:id:endoakak:20200810191019p:plain

5つ目からエラー?2つ目以降は全て空なのに?

エラーの内容を見てみると、

「Lost connection to MySQL server」

とあります。

before do ~ endの部分で色々と処理をしているため、MySQLとやり取りするデータの容量が大きすぎるのではないか、通信に時間がかかりすぎているのではないか、など考えつつメンターさんと相談しました。

原因と解決策

メンターさんもすぐには原因がわからず色々と調べてもらった結果、最終的な結論は

PCの処理速度にrspecがついていけていないから

です。PCがどんどん処理を進めようとして、rspecの方が追いつけなくて途中で止めてしまうんだそう。そんなことあるのか。

解決法としては、sleepメソッドを使います。sleepは処理を一時停止するメソッドで、sleep 1と記述すると、その時点で1秒止まってから処理を再開します。

今回は以下のようにbefore do ~ endのなかにsleepを追加しました。

before do
  user = FactoryBot.create(:user)
  item = FactoryBot.build(:item)
  item.image = fixture_file_upload("public/images/test_image.png")
  item.save
  sleep 0.5
  @deal_shipment = FactoryBot.build(:deal_shipment, user_id: user.id, item_id: item.id)
end

rspecがついてこられるように待っていてあげる感じですね。これで無事テストが通るようになりました。

まとめ

  • 処理が速すぎてエラーになることもある
  • sleepは処理を一時停止するメソッド