12

我有一个返回 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)

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

从错误中,我怀疑 CircleCI 正在四舍五入时间戳值,但我没有足够的信息。有什么建议么?

4

2 回答 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 实例上检查吗?

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

我还没有尝试过他们的建议来确认,但这似乎确实提供了一个解释以及一个不需要timecop.

于 2015-08-26T20:44:39.710 回答
1

您还可以在架构中定义时间列的精度,这样 ActiveRecord 将在类型转换时处理精度截断。

https://github.com/rails/rails/blob/39de1156970d52b441ff944862ebe16a47de784f/activemodel/lib/active_model/type/date_time.rb#L18

于 2020-05-21T19:38:52.763 回答