Загрузка базы данных приборов в Rails - PullRequest
0 голосов
/ 03 сентября 2018

Я создаю приложение Rails (я новичок в этом, так что простите, если некоторые формулировки неуклюжи). Я пытаюсь написать тесты (с RSpec), которые рисуют и используют данные из базы данных, и у меня возникают проблемы с написанием тестов в сжатой форме.

Некоторые из тестов (например, регистрация пользователя или создание контента) лучше всего подходят для создания новой базы данных, в то время как для некоторых требуются заполненные базой данных приспособления.

В данный момент я использую gem очистителя базы данных со следующей конфигурацией:

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.strategy = :truncation   end

  # start the transaction strategy as examples are run    
   config.around(:each) do |example|
     DatabaseCleaner.cleaning do
       example.run
     end    
   end

Причина, по которой я использую truncation для обеих стратегий, заключается в том, что я предпочитаю, чтобы значения id полностью обновлялись между примерами (чтобы при I create в одном тесте, а затем create во втором тесте второй пример должен иметь идентификатор 1, а не 2). Я не уверен, что именно означают различные стратегии - я нашел этот вопрос , который объясняет их с точки зрения синтаксиса SQL, но я не очень знаком с , что , поэтому мой понимание все еще довольно расплывчато. Я считаю, что база данных Я работал с PostgreSQL, но мне редко приходится взаимодействовать с ним напрямую, так что я не особенно опытен.

Таким образом, моя база данных полностью отбрасывается и создается с нуля между каждым примером - если я хочу чистую базу данных, то это идеально, но если я хочу просто загрузить приборы, тогда может потребоваться время для создания всех моделей. Такое ощущение, что у меня должна быть «кэшированная» версия приборов, которую я могу загрузить для тех примеров, для которых она подходит. Но я понятия не имею, как это сделать, если это вообще возможно. Есть ли способ?

Редактировать: После обсуждения в комментариях я подозреваю, что, возможно, захочу удалить Database Cleaner и вместо этого использовать стандартные Rails-светильники. Я попробовал это, и единственная проблема, с которой я столкнулся, это та же самая, что у меня была со стратегией transaction, описанной выше. То есть: при откате записей, созданных тестом, id не откатывается, и это неловкое поведение. Если я создаю user с целью запуска теста, удобно ссылаться на него как User.find(1), что невозможно, если id не сбрасывается.

Возможно, это какой-то красный флаг, и я не должен этого делать (я открыт для других действий). Я также понимаю, что мог бы просто сказать User.first, чтобы получить то же самое поведение, и это могло бы быть лучше. Я не уверен, что подходит.

1 Ответ

0 голосов
/ 03 сентября 2018

DatabaseCleaner не предназначен для использования с приборами. Он предназначен для использования с фабриками. ActiveRecord::Fixtures имеет собственный механизм отката.

Существует действительно большая концептуальная разница.

Fixtures подобны этому огромному набору статических фиктивных данных, которые выбрасываются в базу данных для каждого примера, а затем сбрасываются с помощью транзакции. Большой недостаток приборов состоит в том, что чем больше у вас приборов, тем сложнее начальное состояние приложения, и это стимулирует тесную связь между тестами и самими приборами.

Это пример, который показывает, как значение "Marko Anastasov" волшебным образом появляется где-то за пределами кода:

RSpec.describe User do
  fixtures :all

  describe "#full_name" do
    it "is composed of first and last name" do
      user = users(:marko)
      expect(user.full_name).to eql "Marko Anastasov"
    end
  end
end

Несмотря на то, что у светильников в последнее время появилось возрождение из-за кажущейся простоты (наряду с Minitest).

Фабрики - это объектные фабрики, которые производят уникальные записи. Вместо того, чтобы собирать кучу мусора, вы начинаете каждый пример с пустым состоянием, а затем используете фабрики, чтобы заполнить базу данных точным состоянием для воспроизведения сценария, который вы тестируете. Если все сделано правильно, это сводит к минимуму проблемы с порядком испытаний, испытаниями на взмахи и испытаниями на смену приспособлений.

RSpec.describe User do
  describe "#full_name" do
    it "is composed of first and last name" do
      user = FactoryBot.create(:user)
      expect(user.full_name).to eql "#{user.first_name} #{user.last_name}"
    end
  end
end

Это пример хорошей фабрики, которая генерирует псевдослучайные значения:

require 'ffaker'

FactoryBot.define do
  factory :user do
    first_name { FFaker::Name.first_name }
    last_name { FFaker::Name.last_name }
  end
end
...