Ruby Time.zone.now и учет точности базы данных - PullRequest
0 голосов
/ 05 марта 2019

У меня есть тест в наборе тестов Rails 3, который делает ряд утверждений, которые сравнивают временные метки, которые проходят на моей локальной машине, но не выполняются в нашем конвейере CI.Этот тест сохраняет временную метку в поле временной метки базы данных Postgres с точностью до 6 и сравнивает сохраненное значение с исходной временной меткой, очень похоже на следующий пример:

tmp_time = Time.zone.now
u = User.find(1)
u.updated_at = tmp_time
u.save!
u.reload

assert_equal u.updated_at.to_i, tmp_time.to_i # passes...
assert_equal u.updated_at, tmp_time # fails...
assert_equal u.updated_at.to_f, tmp_time.to_f # fails...

Я полагаю, что проблема связана со временем Рубипредставление имеет более высокую точность, чем сохраненное значение.

Каков наилучший способ компенсации незначительной разницы в значениях из-за точности, помимо того, что он является менее точным при сравнении?Мы рассмотрели переопределение Time.zone.now, но считаем, что это приведет к проблемам в нисходящем направлении.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Вероятно, проблема не в точности в базе данных, а в том, что между определением tmp_time и сохранением проходит небольшое время.

Вы можете видеть, что .to_f представление времениизменяется мгновенно:

irb(main):011:0> 2.times.map { Time.now.to_f }
=> [1551755487.5737898, 1551755487.573792]

Эта разница обычно не видна при использовании .to_i, поскольку она округляется до ближайшей секунды.

Вы можете использовать Timecop , какдругой ответ упоминает, чтобы обойти это:

irb(main):013:0> Timecop.freeze { 2.times.map { Time.now.to_f } }
=> [1551755580.12368, 1551755580.12368]
0 голосов
/ 05 марта 2019

Я бы предложил использовать [Timecop] [1] для таких тестов.Я также добавил бы, что не рекомендуется вручную прикасаться к отметке времени, поэтому я даже не совсем уверен, что вы проверяете.Похоже, вы не доверяете меткам времени.Но если вам необходимо, здесь:

Timecop.freeze
tmp_time = Time.zone.now
u = User.find(1)
u.updated_at = tmp_time
u.save!
u.reload

#your tests should pass now

Если они этого не делают, [см. Этот открытый вопрос по основным рельсам] [2].Если это связано с вашей проблемой, Timecop должен предотвратить это.Но если этого не произойдет, то, поздравляю, вы нашли основной край рельсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...