0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

systemテストを落とさないようにするコツ2つ

0
Last updated at Posted at 2022-01-26

Railsのsystemテストは、ランダムに落ちたり落ちなかったりすることがあります。ここでは、ランダムに落ちるテストをどうにかするためのコツを2つ紹介します。

基本

systemテスト(ブラウザーを使ったE2Eテスト)では、次の3つのアプリケーション(プロセスまたはスレッド)がバラバラに動いていると考えてください。
image.png
テストがランダムに落ちる原因でよくあるのは、テストが進行するに従って、テストプログラムがほかを置いて先走ったり、ブラウザーが先走ったりすることです。

systemテストでこの3つの進み具合を揃え、ランダムに落ちないようにする基本は、何か動作を起こすたびに、画面のチェックを入れることです。

click_link '製品一覧'
expect(page).to have_css('h1', text: '製品一覧') # これを省略しない!
click_link '石けん'
expect(page).to have_css('h1', text: '石けん')

「製品一覧」などのテキストが出るまでCapybaraがうまいこと待機してくれるので、sleepを入れる必要はありません。たいていはこれでうまく行きますが、それでもランダムに落ちるケースでは、次の2つの原因を疑ってみてください。

1. Ajax読み込みを確認してから次へ行く(フラッシュ対策)

「製品を登録しました」のようなフラッシュのテキストをチェックしているときに、フラッシュが画面に出なくてテストがランダムに落ちる、というケースです。この場合、フォームの送信中にAjax通信が来て、フラッシュがAjaxに取られている可能性があります。

例えば、フォームを表示するときにAjaxで追加のデータを取っているようなときは、Ajaxの読み込みが完了したことを確認したうえで、送信ボタンをクリックします。次の例は、カテゴリー一覧をAjaxで取ってリストに入れているときの書き方です。

click_link '新規登録'
expect(page).to have_css('h1', text: '製品の登録')
expect(page).to have_css('#category option', count: 5) # Ajax読み込み待ち
fill_in '製品名', with: '石けん'
click_button '登録する'
expect(page).to have_text('製品を登録しました。')

2. DBにデータをすべて用意してからテストを始める

似たようなテストを並べて、データをちょっとだけ変えたいというときに、systemテストの進行中にDBを操作すると(クリック、クリック、DB更新、クリック……)、テストがランダムに落ちることがあります。ブラウザーが画面を取得したときにDB更新が間に合っていないせいです。ローカルでは起きなくてもCI環境で起こることがあります。

この場合は、テスト全体を始める前に必要なデータを作るようにします。次の「添付品あり」の例のように途中でデータを作っているテストがあるとします。

describe "製品の登録" do
  before do
    login
    click_link '製品一覧'
    expect(page).to have_css('h1', text: '製品一覧')
  end

  it "通常の場合" do
    click_link '新規登録'
    fill_in '製品名', with: 'スペシャル石けん'
    click_button '登録する'
    expect(page).to have_text('製品を更新しました。')
  end

  it "添付品あり" do
    create(:attached_product, name: 'おまけ') # ここでレコード作らない!
    click_link '新規登録'
    fill_in '製品名', with: 'スペシャル石けん'
    check 'おまけ'
    click_button '登録する'
    expect(page).to have_text('製品を登録しました。')
  end
end

こういうテストが落ちるときは、多少コードが長くなっても、次のような修正を入れます(テストコードをきれいにしたかったら、この後で考えます)。

describe "製品の登録" do
  before do
    login
    click_link '製品一覧'
    expect(page).to have_css('h1', text: '製品一覧')
  end

  it "通常の場合" do
    click_link '新規登録'
    fill_in '製品名', with: '石けん'
    click_button '登録する'
    expect(page).to have_text('製品を更新しました。')
  end
end

describe "添付品あり製品の登録" do
  before do
    create(:attached_product, name: 'おまけ') # 始めに移動
    login
    click_link '製品一覧'
    expect(page).to have_css('h1', text: '製品一覧')
  end

  it "添付品あり" do
    click_link '新規登録'
    fill_in '製品名', with: '石けん'
    check 'おまけ'
    click_button '登録する'
    expect(page).to have_text('製品を登録しました。')
  end
end

なお、systemテスト以外では、テストの途中でデータをいじるのはアリだと思っています(美しさにこだわる人は嫌がるかもしれません)。

3. アニメーションで落ちる(研究中)

jQueryやBootstrap、そのほかCSSやJavaScriptのアニメーションで落ちることがあります。この対策についてはまたあとで。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?