CircleCI:涉及时间戳的规范出现错误

14

我有一个方法规范,用于返回ActiveRecord对象的时间戳。

此规范在本地通过,但每当在CircleCI上运行时,预期结果与实际结果略有不同。

该规范大致如下:

describe '#my_method' do
  it 'returns created_at' do
    object = FactoryGirl.create(:something)
    expect(foo.bar(object)).to eq object.created_at
  end
end
尽管在本地运行正常,但在CircleCI上,我一直收到类似的错误信息。
以下是示例:
(1)
expected: 2015-05-09 10:42:59.752192641 +0000
got: 2015-05-09 10:42:59.752192000 +0000

(2)

-->

(2)

expected: 2015-05-08 10:16:36.777541226 +0000
got: 2015-05-08 10:16:36.777541000 +0000

从错误来看,我怀疑 CircleCI 对时间戳的值进行了四舍五入,但是我没有足够的信息。有任何建议吗?


最好向Circle CI支持人员报告此问题;他们可能更有能力解释正在发生的事情。 - Prakash Murthy
2个回答

9

我遇到了同样的问题,目前正在向CircleCI提交工单以获取更多信息。如果我获得更多信息,我会更新这个答案。

与此同时,一个解决方法是确保你在这样的测试中使用的时间戳通过模拟时间的库(比如 timecop)进行四舍五入处理,以确保这些测试能够通过。

describe '#my_method' do
  it 'returns created_at' do
    # CircleCI seems to round milliseconds, which can result in 
    # slight differences when serializing times.
    # To work around this, ensure the millseconds end in 000.

    Timecop.freeze(Time.local(2015)) do
      object = FactoryGirl.create(:something)
      expect(foo.bar(object)).to eq object.created_at
    end
  end
end
更新: 根据CircleCI的初步回应,上述方法实际上是他们推荐的方法。但是他们还没有能够解释为什么会发生四舍五入的情况。 更新2: 看起来这与不同系统之间的精度差异有关。我个人在OS X上遇到了这个问题。以下是来自Circle的回复:

据我所知,Time.now在OS X和Linux机器上精度实际上是不同的。我想你可能会在其他Linux主机上得到完全相同的结果,但所有OS X主机都会给出没有四舍五入的结果。我可能错了,但我记得和另一位客户讨论过这个问题。请在运行Linux的VM或EC2实例上检查一下?

在Time参考中,您可以在页面上搜索精度——round方法实际上可以为您调整精度。您是否可以选择在测试中对断言进行时间舍入?

我还没有尝试他们的建议来进行确认,但这确实提供了一个解释以及一个额外的解决方法(在测试中对断言进行舍入)而不需要使用timecop

2
将时间冻结到微秒级对我没起作用。最终我转而使用了 RSpec 匹配器“be_within”。 - Jed Schneider
我能够让我的规格在CI上通过的唯一方法是使用round方法,例如:let(:now) { Time.current.round(3) }(在Timecop.freeze之上)。感谢这篇文章的作者:https://www.toptal.com/ruby-on-rails/timestamp-truncation-rails-activerecord-tale - undefined

1

这是自6.0以来的Rails默认设置(针对新创建的迁移),并且解决了这个问题,而不使用Timecop或使用be_within。我最终为所有日期时间列添加了明确的精度,从而一劳永逸地解决了这个问题。 - fabi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接