Bagaimana cara memuat db: data seed ke dalam database uji secara otomatis?

122

Saya mencoba menggunakan cara standar baru untuk memuat data seed di Rails 2.3.4+, db:seedtugas rake.

Saya memuat data konstan, yang diperlukan agar aplikasi saya benar-benar berfungsi dengan benar.

Apa cara terbaik db:seeduntuk menjalankan tugas sebelum pengujian, sehingga datanya sudah terisi sebelumnya?

Luke Francl
sumber

Jawaban:

120

The db:seedtugas menyapu terutama hanya memuat db/seeds.rbnaskah. Oleh karena itu jalankan saja file itu untuk memuat data.

load "#{Rails.root}/db/seeds.rb"

# or

Rails.application.load_seed

Tempat meletakkannya bergantung pada framework pengujian yang Anda gunakan dan apakah Anda ingin memuatnya sebelum setiap pengujian atau hanya sekali di awal. Anda bisa memasukkannya ke dalam setuppanggilan atau test_helper.rbfile.

ryanb.dll
sumber
4
Saya suka kesederhanaan, tetapi untuk beberapa alasan menambahkan baris ini ke saya test_helper.rbtidak berhasil untuk saya meskipun stackoverflow.com/a/1998520/68210 melakukannya.
Daniel X Moore
37
Di versi rel yang lebih baru, Anda dapat melakukannya: Rails.application.load_seed
Steve
@Steve terima kasih - apakah Anda tahu di mana harus meletakkan Rails.application.load_seed jika seseorang menggunakan rspec / capybarra, misalnya?
BKSpurgeon
1
@BKSpurgeon Saya memuat cukup banyak data seed di aplikasi saya karena memerlukan data khusus untuk dijalankan dan pabrik terlalu rumit. Saya letakkan Rails.application.load_seedtepat require 'rspec/rails' di bawah file rails_helper saya. Jika Anda menggunakan permata database_cleaner - ini akan memerlukan sedikit penyesuaian untuk memastikan Anda tidak kehilangan data benih setelah setiap pengujian dan Anda dapat menemukannya dalam dokumentasi permata itu sendiri
MageeWorld
Di Rails 5.x saya menambahkan ini ke test/test_helper.rbsetelah require 'rails/test_help'baris yang ada
Andrew
87

Menurutku seharusnya begitu

namespace :db do
  namespace :test do
    task :prepare => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end

Karena db: test: load tidak dijalankan jika Anda memiliki config.active_record.schema_format =: sql (db: test: clone_structure is)

Eugene Bolshakov
sumber
4
Menjalankan rake dengan --tracemembantu saya memahami cara kerjanya.
Jared Beck
4
@BookOfGreg Saya memilikinya di lib / tugas / test_seed.rake yang saya buat sendiri
Eugene Bolshakov
6
Mengapa tidak hanya ini? task 'db:test:prepare' => 'db:seed'
Carson Reinke
3
Untuk Rails 4.0.0 final tambahkan ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])sebelumRake::Task["db:seed"].invoke
janic_
3
@CarsonReinke - karena lingkungan saat db:seeddijalankan adalah development... aneh.
denishaskin
17

Menempatkan sesuatu seperti ini di lib / task / test_seed.rake harus menjalankan tugas seed setelah db: test: load:

namespace :db do
  namespace :test do
    task :load => :environment do
      Rake::Task["db:seed"].invoke
    end
  end
end
Nick M.
sumber
15

Saya yakin komentar Steve di atas seharusnya menjadi jawaban yang benar. Anda dapat menggunakan Rails.application.load_seeduntuk memuat data benih ke dalam lingkungan pengujian Anda. Namun, kapan dan seberapa sering data ini dimuat bergantung pada beberapa hal:

Menggunakan Minitest

Tidak ada cara mudah untuk menjalankan file ini satu kali sebelum semua tes (lihat masalah Github ini ). Anda harus memuat data satu kali sebelum setiap pengujian, kemungkinan besar dalam metode penyiapan file pengujian Anda:

# test/models/my_model_test.rb
class LevelTest < ActiveSupport::TestCase

  def setup
    Rails.application.load_seed
  end

  # tests here...

end

Menggunakan RSpec

Gunakan before(:all)metode RSpec untuk memuat data benih untuk semua pengujian untuk model ini:

describe MyModel do
  before(:all) do
  Rails.application.load_seed
end

describe "my model..." do
  # your tests here
end

Semoga ini membantu.

Matt
sumber
2
Jawaban terbaik sejauh ini
Yuri Ghensev
Saya melakukan sesuatu yang serupa, hanya saja saya memanggilnya before(:suite)bukan before(:all). Memposting jawaban terpisah untuk menyertakan kode yang diformat.
Mark Schneider
3

Kami memanggil db: seed sebagai bagian dari db: test: persiapkan, dengan:

Rake::Task["db:seed"].invoke

Dengan begitu, data seed dimuat satu kali untuk keseluruhan pengujian yang dijalankan, dan tidak sekali per kelas pengujian.

jondahl.dll
sumber
4
Apakah Anda membuat db: test: persiapkan tugas baru untuk melakukan itu? Bisakah Anda memposting kode?
Luke Francl
3

Bagi mereka yang menggunakan bank benih, ini mengubah cara pemuatan benih, jadi Anda mungkin tidak dapat / tidak ingin menggunakan load ...solusi yang disediakan di sini.

Dan hanya dengan memasukkan Rake::Task['db:seed'].invoketest_helper menghasilkan:

Don't know how to build task 'db:seed' (RuntimeError)

Tetapi ketika kami menambahkan load_tasks sebelum itu, itu berhasil:

MyApp::Application.load_tasks
Rake::Task['db:seed'].invoke
Gary S. Weaver
sumber
2

Menambahkan Rake::Task["db:seed"].invokeke db:test:preparetugas menyapu tidak berhasil untuk saya. Jika saya menyiapkan database dengan rake db:test:prepare, dan kemudian memasuki konsol dalam lingkungan pengujian, semua benih saya ada di sana. Namun, benih tidak bertahan di antara pengujian saya.

Menambahkan load "#{Rails.root}/db/seeds.rb"ke metode penyiapan saya berfungsi dengan baik.

Saya ingin agar benih ini dimuat secara otomatis dan bertahan, tetapi saya belum menemukan cara untuk melakukannya!

alexpls
sumber
0

Berdasarkan jawaban Matt, jika mengambil rute semacam itu, saya sarankan menelepon Rails.application.load_seeddi before(:suite)blok rspec_helper.rbdaripada dibefore(:all) blok di file apa pun. Dengan cara itu, kode penyemaian hanya dipanggil sekali untuk seluruh rangkaian pengujian, bukan sekali untuk setiap grup pengujian.

rspec_helper.rb:

RSpec.configure do |config|
  ...
  config.before(:suite) do
    Rails.application.load_seed
  end
  ...
end
Mark Schneider
sumber