ruby – RSPEC让vs实例创建昂贵的对象

ruby – RSPEC让vs实例创建昂贵的对象,第1张

概述在RSPEC中,Let的行为是通过单个示例(它阻止)进行记忆,但在某些情况下,这可能会导致一些潜在的令人讨厌的副作用. 我注意到如果你设法尝试创建任何被认为是昂贵的东西,比如一个大型的模拟器,整个对象的创建将重复它所调用的每一个例子. 对此进行故障排除的第一步是将模拟数据下载到大小,这将大部分运行时间从约30秒减少到~0.08秒.通过将一个没有任何形式的突变被调用3次的let变量传递给实例,速度可 在RSPEC中,Let的行为是通过单个示例(它阻止)进行记忆,但在某些情况下,这可能会导致一些潜在的令人讨厌的副作用.

我注意到如果你设法尝试创建任何被认为是昂贵的东西,比如一个大型的模拟器,整个对象的创建将重复它所调用的每一个例子.

对此进行故障排除的第一步是将模拟数据下载到大小,这将大部分运行时间从约30秒减少到~0.08秒.通过将一个没有任何形式的突变被调用3次的let变量传递给实例,速度可以进一步提高(在这种情况下为-0.02到-0.04).

通常情况下,可以推测懒惰的评估是可取的,并且在某些情况下这样的事情是安全的代价.在大型测试套件(3000次测试)的背景下,甚至0.01-0.02秒的差异通常足以导致20-30秒的膨胀.当然,在某些情况下,这是任意编号,但您可以看到为什么这是不合需要的并且会产生复合问题.

我的问题是:

>在什么情况下不再是一个可行的选择?
>有没有办法在块上下文而不是示例上下文中扩展其’memoization? ……或者这是一个可怕的想法?
>是否有有效的方法来生成非常大量的模拟数据,这些数据可能需要7秒才能加载?我已经看到了对Factory Girl的模糊引用,但是在那个音符上有足够的战斗,我不知道在当前的背景下该怎么想.

感谢您的时间!

解决方法 正如您似乎意识到的那样,除了您使用它的示例之外,基本上只是让您不要评估变量.如果你在十个例子中使用它,那么你确实会在昂贵的 *** 作中获得十次点击.

所以对于你的第一个问题,我不知道我能提供一个有用的答案.这是非常情境化的,但是如果你经常使用变量并且这是一个昂贵的 *** 作,我会说让它不可行.但根据您的需求,它可能仍然是最佳选择 – 也许您必须在大多数示例中重置状态,但不是全部.在这种情况下, *** 作的费用可能不值得尝试在少数情况下分享它的痛苦.

对于你的第二个问题,我想说尝试让我们在一个街区内工作可能不是一个好主意.这是一个before(:all)块和一个实例变量的情况.

你的第三个问题是我认为真正的肉在哪里,所以请耐心等待.

FactoryGirl真的不会改变你的问题.它将构建并可选地保存对象,但您仍需要决定在何处以及如何使用它.如果你开始将它d出到之前(:每个)块,或者在大多数示例中调用构建器,你仍然会有性能命中.

根据您的需要,您可以在before(:all)块甚至before(:suite)块中执行昂贵的 *** 作(例如,在spec_helper.rb中配置).这样做的好处是可以减少对昂贵 *** 作的点击次数,但缺点是如果您正在修改数据,则会对所有其他测试进行修改.这显然会导致许多难以调试的问题.如果您的数据需要通过多个示例进行更改,然后重置为原始状态,那么您将遇到某种性能损失或自己设计的自定义逻辑.

如果您的数据主要位于ActiveRecord对象中,并且您并不热衷于存根/模拟以防止访问数据库,那么您可能会遇到缓慢的测试问题. Fixtures可以与事务一起使用,并且可以比工厂更快,但根据您的数据库架构,关系等可能很难维护.我相信您可以在before(:suite)块中使用工厂,然后交易仍然有效,但这并不一定比固定装置更容易维护.

如果您的数据只是cpu数据库而不是数据库记录,则可以设置一组对象并通过Marshal模块对其进行序列化.然后你可以在一个let块中预加载它们,只需一个磁盘命中(或者内存,如果你将Marshalled字符串存储在内存中):

# In irb or pry or even spec_helper.rbobject = SomeComplexThing.newobject.prepare_it_with_expensive_method_call_funMarshal.dump(object) # Store the output of this somewhere# In some_spec.rblet(:thing) { Marshal.load(IO.read("serialized_thing")) }

这样做的好处是可以完全序列化对象的状态,并在不重新计算昂贵数据的情况下完全恢复它.对于像ActiveRecord模型这样的非常复杂的对象,这可能不会有效,但它对于您自己设计的更简单的数据结构非常方便.您甚至可以通过实现marshal_dump和marshal_load方法来实现自己的转储/加载逻辑(请参阅上面链接的Marshal文档),这可以在测试之外使用.

如果您的数据足够简单,您甚至可以使用以下设置:

# In spec_helper.rbRSpec.configure do |config|  config.before(:suite) do    @object = SomeComplexThing.new    @object.prepare_it_with_expensive_method_call_fun  endend# In a testlet(:thing) { @object.dup }

这并不一定适用于所有情况,因为dup是一个浅层副本(有关详细信息,请参阅the Ruby docs),但是您可以理解 – 您正在构建副本而不是重新计算任何昂贵的东西会伤害您.

我希望这些信息有所帮助,因为我不确定我完全理解你需要什么.

总结

以上是内存溢出为你收集整理的ruby – RSPEC让vs实例创建昂贵的对象全部内容,希望文章能够帮你解决ruby – RSPEC让vs实例创建昂贵的对象所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1275689.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存