#ruby-on-rails #ruby #rspec #rake
#ruby-on-rails #ruby #rspec #rake
Вопрос:
Я работаю в проекте с использованием RoR и Rspect.
У меня есть задача rake, которая использует метод из другого вызываемого Gem When2top::iterate
. Этот метод повторяется в течение указанного времени.
task :log_stats, [:entity_name, :duration_limit] => [:environment] do |_, args|
include When2stop
entity_name = args[:entity_name]
duration = args[:duration_limit].to_i
index_data = (Wh2find::INDEXABLES.find entity_name: entity_name).first
entity_class = index_data[:entity]
iterate for: duration.minutes do
byebug
stats = entity_class.get_stats
values = Hash[stats.collect { |item| [item[:index_status], item[:count]] }]
values.each { |k, val| NewRelic::Agent.record_metric("Wh2find/#{entity_name}/#{k}", val) }
end
end
Итак, я хочу написать тест для задачи, которая использует этот метод, но я не использовал его на самом деле, потому что это подразумевает замедление теста (мне нужно подождать определенное время) и не знаю, сколько раз будет выполняться логика внутри блока.
У меня есть свои спецификации для этой задачи, но я не могу заглушить метод модуля.
require 'rails_helper'
Rails.application.load_tasks
include When2stop
describe :wh2find do
describe :log_stats do
it 'should log stats' do
task = Rake::Task['wh2find:log_stats']
entity_name = TestEntity.class
duration = "1"
stub_const "Wh2find::INDEXABLES", [
{
entity_name: 'entity',
entity: TestEntity,
fields_to_index: {
name: {
weight: 1
}
}
}
]
expect(task).stub_chain(:iterate) do |dur, amp;block|
byebug
expect(dur).to eq(duration.minutes)
expect(TestEntity).to receive(:get_stats).and_return(
[
{
_id: 0,
count: 10,
index_status: 'to_index'
},
{
_id: 1,
count: 5,
index_status: 'to_reindex'
},
{
_id: 2,
count: 1054,
index_status: 'indexed'
},
]
)
new_relic_agent = double('NewRelic::Agent').as_stubbed_const
expect(new_relic_agent).to receive(:record_metric).with("Wh2find/#{entity_name}/to_index", 10)
expect(new_relic_agent).to receive(:record_metric).with("Wh2find/#{entity_name}/to_reindex", 5)
expect(new_relic_agent).to receive(:record_metric).with("Wh2find/#{entity_name}/indexed", 1054)
block.call()
end
task.invoke(entity_name, duration)
end
end
end
Есть идеи о том, как я мог бы заглушить этот метод и утвердить итеративную логику?
Заранее спасибо!
Комментарии:
1. Вы могли бы рассмотреть возможность использования драгоценного камня Timecop, который позволяет вам перемещать и масштабировать время, но должна быть какая-то альтернатива этому драгоценному камню, который имеет встроенную поддержку для тестирования.
2. Что это за драгоценный камень? Этого нет в RubyGems. Если это ваш личный драгоценный камень, то вам следует добавить несколько помощников по тестированию в сам драгоценный камень.
3. @max спасибо, да, я мог бы использовать Timecop для быстрого завершения метода, но моя цель — не проверить, работает ли итерация, но она вызывается, так что это не реальное решение.
4. Как говорит @BroiSatse, когда 2stop — мой драгоценный камень, он приватный, но я мог бы сделать это общедоступным. Но я не понимаю, что я мог бы добавить в свой gem, чтобы сделать его более удобным для тестирования. Вот ссылка на репозиторий gem: github.com/wh-2/when2stop Вот мой проект: github.com/wh-2/wh2find
5. Это будет очень сложно протестировать, поскольку вам придется заглушить метод в экземпляре задачи rake. Но на самом деле это только верхушка айсберга — я бы беспокоился об использовании памяти при выполнении этого кода в течение N минут.