4

我听说这是避免its, let, let!, specify, before,subject在 RSpec 中的最佳实践。

关于let, let!before,如果不使用这些,我该如何执行设置任务?

4

6 回答 6

8

编写这些最佳实践的人实际上只想说“不要使用 RSpec”。避免使用核心功能并仍然认为你可以把事情做好是很疯狂的。你能链接到这些最佳实践吗?我很想阅读它们,看看它们是否合理,或者只是一些 j-random-guy 的意见。

避免beforelet?什么?真的吗?

避免specify,我猜,这只是it.

避免特定subject呼叫?我想,如果你的代码生活在一个理想主义的幻想世界里。努力将其最小化并使用隐式主题?当然。

避免its?这很棒!为什么要避免呢?自我记录的单行规范?多么可怕。

于 2013-09-12T15:48:19.643 回答
6

来源:有些人询问所有这些的来源。我认为这来自thoughtbot 最佳实践指南

答案:阅读该指南后,我也几乎吓坏了,但在做了一些研究之后,我发现了来自同一个人的这篇解释得很好的帖子Let's Not。是一本非常好的读物,其中包含很多关于测试和一般良好实践的有见地的建议。

对该指南存在一些普遍的误解。只是说“避免”而不是“不要使用”。结果代码将更清晰,更易于维护。我将引用帖子反映的一些观点:

  • (...) RSpec 的 DSL 的一些特性经常被过度使用,导致测试维护的增加和测试可读性的下降。
  • 除非您需要像共享示例那样打破大枪,否则请避免使用诸如 subject、let、its 和 before 之类的 DSL 构造。坚持你的老朋友:变量、方法和类。

这对我来说很有意义。希望这可以帮助。

于 2014-03-12T06:47:29.003 回答
2

因为这里的答案都没有解决实际问题,而是给出了他们对提到的做法的意见,所以我觉得有必要添加另一个答案,即使它被问到已经 7 6 年了:

所有“有问题的”DSL 方法都可以用普通的旧 Ruby 方法代替。您仍然可以保持 DRY,而不必使用将注意力转移到代码不同部分的方法。

以下代码直接摘自 Noel Rappin 的 Rails 5 Test Prescriptions 一书

describe "estimates" do
  let(:project) { Project.new }
  let(:done) { Task.new(size: 2, completed: true) }
  let(:small_not_done) { Task.new(size: 1) }
  let(:large_not_done) { Task.new(size: 4) }

  before(:example) do
    project.tasks = [done, small_not_done, large_not_done]
  end

  it "can calculate total size" do
    expect(project.total_size).to eq(7)
  end

  it "can calculate remaining size" do
    expect(project.remaining_size).to eq(5)
  end
end

用普通的 Ruby 方法替换

describe "estimates" do

  it "can calculate total size" do
    project = build_new_project
    project.tasks = build_done_small_and_large_tasks

    expect(project.total_size).to eq(7)
  end

  it "can calculate remaining size" do
    project = build_new_project
    project.tasks = build_done_small_and_large_tasks

    expect(project.remaining_size).to eq(5)
  end

  def build_new_project
    Project.new
  end

  def build_new_task(size=1, completed=false)
    Task.new(size: size, completed: completed)
  end

  def build_done_small_and_large_tasks
    tasks = []
    tasks << build_task(2, true)
    tasks << build_task(1, false)
    tasks << build_task(4, false)
    tasks
  end
end

在我和 Thoughtbot 看来,这种方法有以下优点:

  • 每个测试都讲述了一个关于如何使用稍后编写的代码的故事
  • 每个测试都是自包含和描述性的,理想情况下,您不必浏览整个文件即可立即了解每个测试中发生的情况(但这也取决于您编写良好测试的能力)
  • 示例之间没有依赖关系
  • 没有“神秘客人”反模式

另一方面,重点是在每个测试中尽可能明确地显示测试的每个阶段

  • 设置 - 获得正确的测试条件
  • 练习——执行你正在测试的东西
  • 验证 - 验证练习是否符合您的预期
  • 拆解 - 撤消任何不应在测试后持续存在的条件(这应该由 Rspec 自动完成,但任何明确的内容都可以在后块中进行)

例子:

it "can calculate total size" do
  # Setup
  project = build_new_project
  project.tasks = build_done_small_and_large_tasks

  # Exercise and verification 
  # Exercise is the "total_size" method, because that is what we are testing
  # Verification is the expectations of what should happen after the exercise
  expect(project.total_size).to eq(7)
end
# Teardown is performed by Rspec, you may also perform it yourself in   after blocks

总而言之,一家公司的风格指南永远不会适合所有目的或其他公司。据我所知,这种方法对于测试驱动开发特别有用,其中代码需要由每个失败的测试建议修复测试的内容来驱动。所以说你不应该遵循这种方法是相当主观的。它有很好的论据,但也有一些缺点,你应该一如既往地权衡它们并坚持最适合你的东西。就我而言,我发现这些测试更容易阅读,并且对于理解应用程序的每个模块更有用,而不是简单地在出现故障时通知您,我喜欢拥有记录自身的代码。这种方法将让您清楚地看到您未来的代码将如何使用以及每个条件的期望。RSpec 不仅仅是 DSL 方法。

有关 TDD 以及如何遵循这种测试方法的更多信息,请查看如何用测试讲述故事

于 2019-05-22T23:01:56.547 回答
1

我听说这是最佳实践

如果您可以引用一些来源,那将会很有帮助。我相信你听到的陈述是非常不准确的。

避免its

我个人不使用its,但这是一个偏好问题。由于its是一种速记方法,因此您可以正常使用扩展版本。

避免letlet!

没有理由避免它们。官方文档并没有阻止他们,事实上他们正在积极宣传。

从技术上讲,您可以通过定义方法来替换它们。

let(:foo) { 1 }

是“等价于”

def foo
  @foo ||= 1
end

但如您所见,使用let起来更方便有效。

避免specify

specify是 的别名it

避免before

这没有意义。before如果需要,没有办法避免,官方文档也没有弃用它。

避免subject

绝对错误。该文档鼓励使用它。


底线。我坚信你所听到的都是假的。查看文档以了解如何有效地使用 RSpec。

于 2013-12-30T12:11:21.537 回答
1

如果您真的想研究 rspec 的最佳实践,我使用的一些资源是:

于 2013-09-12T15:50:52.587 回答
1

我绝对同意尼克的观点,不应该遵循这些准则。

我最近写了一篇关于以正确方式构建规范的博客文章。它对采用“糟糕”的书面测试套件并使其大放异彩进行了彻底的演练。

你可以在这里阅读。

于 2013-12-30T12:08:19.000 回答