【问题标题】:Should we be using Faker in Rails Factories?我们应该在 Rails 工厂中使用 Faker 吗?
【发布时间】:2023-03-20 04:32:01
【问题描述】:

我喜欢Faker,我一直在我的seeds.rb 中使用它来用看起来真实的数据填充我的开发环境。

我也刚开始使用Factory Girl,这也节省了很多时间 - 但是当我在网上搜索代码示例时,我没有看到太多证据表明人们将两者结合起来。

问。人们为什么不在工厂使用faker有充分的理由吗?

我的感觉是,这样做可以通过每次随机播种(但可预测的)数据来提高测试的稳健性,这有望增加出现错误的机会。

但也许这是不正确的,要么对工厂进行硬编码没有任何好处,要么我没有看到潜在的陷阱。这两种宝石应该或不应该结合有充分的理由吗?

【问题讨论】:

  • 为什么要在每次创建测试模型时动态生成数据?这只是开销
  • 同意,测试性能会受到影响 - 但在复杂的应用程序上这样做不值得,尤其是一个有大量验证的应用程序,以检查我没有写一些愚蠢的东西,允许firstName: Michal 但不是 firstName: Huw,Faker 的多样性肯定会带来更稳健的测试吗?
  • 这称为边缘案例测试。仍然不需要随机数据
  • 但是您不需要提前知道所有可能要测试的边缘情况吗?
  • 当然可以!但看。假设您使用随机数据进行测试,并且想要比较分配给 Person 模型实例的名称是否正确。如果名字是Faker生成的,你想怎么做?将模型与自身进行比较?这是没有意义的。单元测试的重点是将代码输出与已知值进行比较!

标签: ruby-on-rails ruby factory-bot faker


【解决方案1】:

有些人反对它,如here

不要使用随机属性值

一种常见的模式是使用假数据库(如 Faker 或 Forgery)在 苍蝇。这对于姓名、电子邮件地址或 电话号码,但它没有任何实际用途。创造独一无二 values 对于序列来说很简单:

FactoryGirl.define do   
  sequence(:title) { |n| "Example title #{n}" }

  factory :post do
    title
  end 
end

FactoryGirl.create(:post).title # => 'Example title 1' 

您的随机 数据可能会在某个阶段触发测试中的意外结果, 让您的工厂难以合作。任何可能的值 以某种方式影响您的测试结果必须被覆盖, 意思:

随着时间的推移,您会发​​现新的属性会导致您的测试 有时会失败。这是一个令人沮丧的过程,因为测试可能会失败 每十或一百次运行只有一次——取决于有多少 存在的属性和可能的​​值,以及哪些组合 触发错误。您将不得不列出每个这样的随机属性 每个测试都覆盖它,这很愚蠢。所以,你创建非随机的 工厂,从而否定了原始随机性的任何好处。 有人可能会争辩说,正如 Henrik Nyh 所做的那样,随机值对你有帮助 发现错误。虽然可能,但这显然意味着你有一个更大的 问题:测试套件中的漏洞。在最坏的情况下,错误 仍然未被发现;在最好的情况下,你会得到一个神秘的 下次运行测试时消失的错误消息,使 很难调试。诚然,一个隐秘的错误总比没有错误好,但是 随机工厂仍然不能很好地替代适当的单元测试, 代码审查和 TDD 以防止这些问题。

因此,随机化工厂不仅不值得努力,而且 甚至让你对自己的测试产生错误的信心,这比 根本没有测试。

但是,如果您愿意,没有什么能阻止您这样做,那就去做吧。

哦,在最近的 FactoryGirl 中有一种更简单的内联序列的方法,该引用是为旧版本编写的。

【讨论】:

  • 谢谢 Jrochkind,也非常感谢这个链接,有趣的是,他列出了指向 Henrik Nyh post 的链接,我发现自己对这种方法和 Aef 的上述贡献深感兴趣。但我认为 Arjan van der Gaag 提出了一个很好的例子,即使用 faker “不能很好地替代适当的单元测试、代码审查和 TDD 来防止这些问题”。感谢大家的观点。
  • 在某些时候,在不断增长的项目中会出现如此多的组合复杂性,以至于您在测试覆盖率方面总是会出现差距,即使它在纸上是 100%。正如我在回答中所说,您建造工厂的努力通常不会产生额外费用,因为如果您希望能够通过一些体面的、非个性化的演示数据轻松地向客户展示功能,那么您无论如何都可以这样做。跨度>
【解决方案2】:

这取决于你。

在我看来,在测试中使用随机数据是一个非常好的主意,它总能帮助我发现我没有考虑过的错误和极端情况。

我从不后悔拥有随机数据。 @jrochkind 描述的所有观点都是正确的(你应该在阅读这个答案之前阅读另一个答案),但你可以(并且应该)在你的 spec_helper.rb 中写下它也是正确的

config.before(:all)  { Faker::Config.random = Random.new(config.seed) }

这将使您也可以使用可重复的数据进行可重复的测试。如果您不这样做,那么您将遇到其他答案中描述的所有问题。

【讨论】:

  • 我特别喜欢这个答案,最初让我有足够的随机性,以确保我可以测试我最初的期望,但在我需要时可重复性,谢谢@coorasse :)
【解决方案3】:

我喜欢使用 Faker,并且通常在处理更大的代码库时这样做。在使用 Faker 和 Factory Girl 时,我看到以下优点和缺点:

可能的缺点:

  • 重现完全相同的测试场景有点困难(至少 RSpec 通过每次显示随机数生成器种子来解决这个问题,并允许您使用它重现完全相同的测试)
  • 生成数据会浪费一点性能

可能的优势:

  • 使显示的数据通常更易于理解。在手动创建测试数据时,人们倾向于使用各种捷径来避免繁琐。
  • 同时使用 Faker 构建工厂进行测试为您提供了为演示生成漂亮的演示数据的方法。
  • 大量运行测试时,您可能会随机发现边缘情况错误

【讨论】:

  • 谢谢 Aef,这是一个很好的总结——你能谈谈上面 Michal 的观点吗?您认为这是否违反了使用已知值进行测试的基础?另外,当您说它为演示提供了很好的测试数据时,我猜您是在谈论种子文件吗?这个因素如何影响使用工厂进行测试?你在种子文件中使用工厂吗?
  • 我在编写测试时经常遇到的是,实际值是什么通常并不重要,但更多的是它与在某处给出的相同值遍历一些代码并返回要么完全相同,要么以特定方式修改。在这里,值是固定的还是随机的都没有关系。 Faker 数据提供了进一步的用途,因为它试图更接近真实数据,以便人类在调试测试时可以更好地理解它。当值的内容对测试很重要时,通常你不会使用 Faker。
  • 我通常将工厂定义为(可能是可选的)主代码库的一部分,而不是将其与测试代码捆绑在一起。然后我可以在任何地方创建演示数据,无论是在种子文件中,还是在实时控制台中,或者真的在我希望的任何其他上下文中。
猜你喜欢
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
  • 1970-01-01
  • 2017-06-13
相关资源
最近更新 更多