Как ждать определенное время, например, полночь, прежде чем продолжить - PullRequest
0 голосов
/ 09 апреля 2020

Мы пытаемся пройти тест, чтобы подождать ровно до полуночи, прежде чем продолжить.

В настоящее время он проверяет каждую секунду на полночь, что заполняет консоль кучей сообщений "ожидание полуночи".

Есть ли способ заставить его просто проверить время и подождать до полуночи?

def wait_if_almost_midnight max_minutes_needed, utc: false
    seconds_waited = 0
    now = utc ? Time.now.utc : DateTime.now
    now_hour = now.strftime('%k').to_i
    now_minute = now.strftime('%M').to_i
    while now_hour == 23 && max_minutes_needed > (59 - now_minute)
      sleep 1
      seconds_waited += 1
       p "Waiting for midnight, seconds: #{seconds_waited}"
       now_hour = now.strftime('%k').to_i
      now_minute = now.strftime('%M').to_i
    end
  end

Ответы [ 3 ]

1 голос
/ 09 апреля 2020

Ты делаешь это слишком сложно. Просто выясните, сколько секунд осталось до полуночи, затем sleep.

Я использовал что-то подобное в прошлом:

require 'date'

def seconds_until_midnight
  Date.today.next_day.to_time.to_i - Time.now.to_i
end

Тестирование:

5.times do
  puts '%i seconds until midnight' % seconds_until_midnight()
  sleep 1
end

# >> 35142 seconds until midnight
# >> 35141 seconds until midnight
# >> 35140 seconds until midnight
# >> 35139 seconds until midnight
# >> 35138 seconds until midnight

Просто используйте:

sleep seconds_until_midnight()

или измените код на:

require 'date'

def sleep_until_midnight
  midnight = Date.today.next_day.to_time.to_i - Time.now.to_i
  sleep midnight
end

и позвоните sleep_until_midnight().

Магическая часть:

Date.today                  # => #<Date: 2020-04-09 ((2458949j,0s,0n),+0s,2299161j)>
Date.today.next_day         # => #<Date: 2020-04-10 ((2458950j,0s,0n),+0s,2299161j)>
Date.today.next_day.to_time # => 2020-04-10 00:00:00 -0700

Даты не содержат компонент времени, поэтому Ruby выдумывает и добавляет «полночь», AKA 00:00:00, при преобразовании в объект Time.

Если вы хотите уменьшите или увеличьте время ожидания n секунд, вычтите или добавьте это значение к midnight и измените сигнатуру метода:

def sleep_until_midnight(offset)
:
:
  sleep midnight + offset
end

и вызовите его следующим образом:

sleep_until_midnight(-5)
sleep_until_midnight(+1)

Хотя По аналогии с тем, что говорит Тодд Джейкобс в своем ответе, почему? Тесты должны выполняться немедленно, а не в определенное время c, чтобы вы могли получать результаты и реагировать на них по мере разработки. Если нужно проверить, существует ли страница или проанализировать ли ее в указанное c время, используйте cron или что-то подобное.

1 голос
/ 09 апреля 2020

Удалить запрос к ядру # p

Чтобы ответить на ваш актуальный вопрос, просто удалите вызов Kernel # p, чтобы прекратить заполнять вашу консоль:

# This is what's printing to your console.
p "Waiting for midnight, seconds: #{seconds_waited}"

Однако, циклы сна вот так на самом деле не очень эффективны. Возможно, вам лучше использовать cron для запуска процесса в полночь, либо использовать Sidekiq или аналогичные задачи постановки в очередь и обработки в любое время.

Предостережения

Поскольку я понятия не имею, почему это это полезный тест для вас, я не скажу вам не тестировать этот путь. Тем не менее, я подозреваю, что у вас есть некий чувствительный ко времени краевой случай, который вы хотите обработать. Как правило, лучше заглушить / смоделировать любой метод, чувствительный ко времени, а не ждать в течение длительных периодов времени или настроить фактические системные часы вашего веб-сервера, чтобы ваши тесты могли выполняться только около полуночи.

Плотное сцепление с внешними условиями обычно кодовый запах. Подумайте, действительно ли вам нужно тестировать этот путь перед принятием решения X / Y, потому что этот тип подхода часто приводит к медленным тестам или «гейзенбагам». Ваш пробег может отличаться.

0 голосов
/ 09 апреля 2020

Я отвечу на это без отвлечения аргумента utc.

require 'date'

def wait_if_almost_midnight(secs_left_to_begin_reporting = 3600)
  time_now = DateTime.now.to_time
  time_at_midnight = time_now.to_date.next.to_time
  secs_to_midnight = time_at_midnight.to_i - time_now.to_i
  puts "#{secs_to_midnight} seconds until midnight"
  secs_left = secs_to_midnight
  if secs_left > secs_left_to_begin_reporting
    sleep_time = secs_left - secs_left_to_begin_reporting
    secs_left -= sleep_time
    puts "I'm off to sleep for #{sleep_time} seconds, then I'll report "
    puts "every second for the last #{secs_left_to_begin_reporting-1} seconds"
    puts "zzzzzzzzzzzz"
    sleep(sleep_time)
  end
  (secs_left-1).downto(1) do |i|
    p "Waiting for midnight, seconds waited so far: #{secs_to_midnight-i}"
    sleep(1)
  end
end

Давайте попробуем это:

wait_if_almost_midnight(10)
# 37965 seconds until midnight
# I'm off to sleep for 37779 seconds, then I'll report 
# every second for the last 9 seconds
# zzzzzzzzzzzz

(позже ...)

# "Waiting for midnight, seconds waited so far: 37780"
# "Waiting for midnight, seconds waited so far: 37781"
# "Waiting for midnight, seconds waited so far: 37782"
# "Waiting for midnight, seconds waited so far: 37783"
# "Waiting for midnight, seconds waited so far: 37784"
# "Waiting for midnight, seconds waited so far: 37785"
# "Waiting for midnight, seconds waited so far: 37786"
# "Waiting for midnight, seconds waited so far: 37787"
# "Waiting for midnight, seconds waited so far: 37788"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...