web-dev-qa-db-ja.com

RSpecのフィクスチャ

Railsアプリケーションでテストを作成するためにRSpecを使用するのは初めてです。フィクスチャを定義し、スペックに次のようにロードしています。

before(:all) do
  fixtures :student
end

この宣言は、フィクスチャで定義されたデータをstudentテーブルに保存しますか、それとも、テストの実行中にデータをテーブルにロードし、すべてのテストの実行後にテーブルから削除しますか?

32
Kris

RSpecでフィクスチャを使用する場合は、beforeブロック内ではなく、describeブロックでフィクスチャを指定します。

describe StudentsController do
  fixtures :students

  before do
    # more test setup
  end
end

学生のフィクスチャは、studentsテーブルに読み込まれ、データベーストランザクションを使用して各テストの最後にロールバックされます。

22
infused

まず、_:all_/_:context_/_:suite hook_ではメソッドfixturesを使用できません。これらのフックでフィクスチャを使用しないでください(post(:my_post)など)。

Infuseが先に書いたように、記述/コンテキストブロックでのみフィクスチャを準備できます。

コール

_fixtures :students, :teachers
_

dBにデータをロードしないでください。ヘルパーメソッドstudentsteachersを準備するだけです。要求されたレコードは、あなたが最初にそれらにアクセスを試みた瞬間に遅延してロードされます。直前

_dan=students(:dan) 
_

これにより、生徒と教師が_delete all from table + insert fixtures_の方法で読み込まれます。

そのため、before(:context)フックでいくつかの学生を準備すると、それらは今ではなくなります!!

レコードの挿入は、テストスイートで一度だけ実行されます。

フィクスチャからのレコードは、テストスイートの最後に削除されません。それらは削除され、次のテストスイートの実行時に再挿入されます。

例:

_ #students.yml
   dan:
     name: Dan 
   paul:
     name: Paul

 #teachers.yml
    snape:
      name: Severus




describe Student do
  fixtures :students, :teachers

  before(:context) do
    @james=Student.create!(name: "James")
  end

  it "have name" do
   expect(Student.find(@james.id).to be_present
   expect(Student.count).to eq 1
   expect(Teacher.count).to eq 0

   students(:dan)

   expect(Student.find_by_name(@james.name).to be_blank
   expect(Student.count).to eq 2
   expect(Teacher.count).to eq 1

  end
end


#but when fixtures are in DB (after first call), all works as expected (by me)

describe Teacher do
  fixtures :teachers #was loade in previous tests

  before(:context) do
    @james=Student.create!(name: "James")
    @thomas=Teacher.create!(name: "Thomas")
  end

  it "have name" do
   expect(Teacher.find(@thomas.id).to be_present
   expect(Student.count).to eq 3 # :dan, :paul, @james
   expect(Teacher.count).to eq 2 # :snape, @thomas

   students(:dan)

   expect(Teacher.find_by_name(@thomas.name).to be_present
   expect(Student.count).to eq 3
   expect(Teacher.count).to eq 2

  end
end
_

上記のテストでのすべての期待はパスします

これらのテストが(次のスイートで)再度この順序で実行されると、予想よりも

_ expect(Student.count).to eq 1
_

満たされません! 3人の生徒がいます(:dan、:paul、新鮮な新しい@james)。これらはすべてstudents(:dan)の前に削除され、:paulと:danのみが再度挿入されます。

5
Foton

before(:all)は、一度ロード/作成されると、正確なデータを保持します。あなたはあなたのことをし、テストの終わりにそれは残ります。そのため、buiのリンクにはafter(:all)を使用して破棄するか、before(:each); @var.reload!;endを使用して以前のテストから最新のデータを取得します。ネストされたrspec記述ブロックでこのアプローチを使用しているのがわかります。

1
pjammer