Заполнение базы данных тестовыми данными при помощи seed-fu
декабря 24, 2011 | Published in Ruby on Rails, Тестирование | 6 Comments
Я отношусь к тойкасте людей, что не воспринимают интеграционные тесты. Программа не может оценить внешний вид приложения так, как то может сделать человек. По этой причине я предпочитаю сам смотреть на то, как выглядит приложение. Для того, чтобы это изучение приложения было максимально приближена к реальности — необходимо заполнять базу тестовыми данными, кроме того, тестовые данные необходимы для тестирования производительности приложения на «реальных» данных. В Rails имеется встроенный механизм seed-ирования базы данных, однако он мне не очень нравится и в этой статье я рассказывать о нем не буду. Вместо встроенного функционала я предпочитаю использовать seed-fu — отличное решение поставляемое в виде совсем обыкновенного gem’а, которое делает заполнение БД тестовыми данными более удобным.
Установка seed-fu
Rails 3.1:
#Gemfile gem 'seed-fu', '~> 2.1.0'
Поддержка Rails 3.x начиная с версии 2.0.
$ bundle install
Использование
По умолчанию файлы с фикстурами seed-fu хранятся в директории db/fixtures/. Файлы фикстур seed-fu являются файлами с обыкновенным Ruby кодом, вместо YAML используемого в стандартных Rails фикстурах. Соглашения по именованию файлов нет, по этому можете назвать их, например pechenka.rb, но я предпочитаю хранить фикстуры для каждой модели в отдельных файлах с именами моделей к которым те относятся, например vacancies_fixture.rb.
Для того, чтобы описанные фикстуры загрузились в БД достаточно просто выполнить Rake-задачу:
$ rake db:seed_fu
Давайте рассмотрим примеры создания фикстур.
Традиционный способ, знакомый нам из ActiveRecord — блочной формы использования методов new или create:
Post.seed do |post| post.id = 1 post.title = "Very intregant title" post.content = "Lorem ipsum dolor sit amet ..." post.user_id = 1 post.created_at = DateTime.now end User.seed do |user| user.id = 1 user.name = "Vladimir Melnick" user.login = "vladimir" user.password = "123456" user.created_at = DateTime.now end
Для создания нескольких записей выгоднее использовать следующий синтаксис:
Post.seed(:id, {:id => 1, :title => "title1", :content => 'content1', :user_id => 1, :created_at => DateTime.now } {:id => 2, :title => "title2", :content => 'content2', :user_id => 1, :created_at => DateTime.now } {:id => 3, :title => "title3", :content => 'content3', :user_id => 2, :created_at => DateTime.now } {:id => 4, :title => "title4", :content => 'content4', :user_id => 3, :created_at => DateTime.now } ) User.seed(:id, {:id => 1, :name => "Super User", :login => "blahblah", :password => "123456", :created_at => Datetime.now} {:id => 2, :name => "Super User", :login => "blahblah", :password => "123456", :created_at => Datetime.now} {:id => 3, :name => "Super User", :login => "blahblah", :password => "123456", :created_at => Datetime.now} )
Для создания нескольких сотен или тысяч «уникальных» записей я использую следующую технику:
post_contents = [...] post_titles = [...] user_names = [...] user_emails = [...] #... 100.times do Post.seed do |post| post.title = titles[rand(post_titles.size - 1)] post.content = contents[rand(post_contents.size - 1)] #... end User.seed do |user| #... end end
Ссылки
Приятного вам программирования!
декабря 24, 2011 at 14:55 (#)
А чем такой подход отличается от создания rake задачи с гемом Faker?
декабря 24, 2011 at 15:17 (#)
Жуткий синтаксис
Есть factory_girl, fabricator — там все изящнее
декабря 24, 2011 at 17:52 (#)
Михаил, FactoryGirl, если я не путаю исключительно для тестов годится, а с seed-fu я забиваю БД произвольным количеством записей.
декабря 24, 2011 at 17:54 (#)
tankard, да в принципе ни чем, Faker несколько удобней будет, ведь он, вроде как сам генерит данные, но у меня как-то не сложилось с ним поработать. Нужно будет попробовать.
декабря 24, 2011 at 19:57 (#)
Владимир, да им без разницы — в каком окружении запустишь, в таком и будут базу заполнять :)
июня 10, 2012 at 21:10 (#)
В синтаксисе создания нескольких записей забыта запятая.