当前位置: 首页 > 知识库问答 >
问题:

Rubocop 25 线块尺寸和 RSpec 测试

公良渝
2023-03-14

典型的 RSpec 单元测试广泛使用嵌套的 Ruby 块来构建代码,并利用 DSL 的“魔术”来使规范读起来像 BDD 语句:

describe Foo do
  context "with a bar" do
    before :each do
      subject { Foo.new().add_bar }
    end

    it "looks like a baz" do
      expect # etc

在理想的规格中,每个示例都可以相对简短和精确。然而,似乎通常将外部块增长到100行以上,因为RSpec结构以这种方式工作,并且不需要很多规范示例,每个示例可能只有几行特定的设置,以描述与所描述主题的代码大小相同或更大的块。

Rubocop最近的一次升级带来了一个新的规则,即块不能超过25行。我不确定它的基本原理,因为它没有在Ruby风格指南中列出。我明白为什么这是一件好事,并添加到默认规则集。然而,在升级之后,我们的Rubocop测试失败了多次,并显示类似于< code > tests/component _ spec . Rb:151:3:C:Block有太多行这样的消息。[68/25]

使用Rubocop等代码度量工具,我喜欢有一个“使用默认值,链接到样式指南,完成工作”的策略。(主要是因为辩论制表符与空格和其他细节是浪费时间,而IME永远不会得到解决)这显然是不可能的,我们的两个核心数据质量工具在代码布局方法上存在分歧 - 或者至少这就是我解释结果的方式,我没有看到我们编写规范的方式有任何本质上的错误。

作为响应,我们简单地将 Rubocop 块大小规则设置为高阈值。但这让我想知道 - 我错过了什么?RSpec 是否在代码布局中使用了一种现在不可信的方法,在 RSpec 测试中,我有哪些合理的选项来减小块大小?我可以看到重构代码以避免大块的方法,但它们无一例外都是丑陋的黑客,纯粹是为了满足Rubocop的规则,例如将所有块分解为帮助器函数:

def looks_like_a_baz
  it "looks like a baz" do
         expect # etc
  end
end

def bar_context
  context "with a bar" do
    before :each do
      subject { Foo.new().add_bar }
    end
    looks_like_a_baz
  end
end


describe Foo do
  bar_context
  # etc

…我的意思是,这是可以做到的,但以这种方式将一堆规范示例转换为辅助函数似乎与RSpec设计鼓励的可读方法相反。

除了想办法忽略它,我还能做什么?

关于这个话题,我能找到的最接近的问题是RSpec

共有2个答案

龙俊英
2023-03-14

最近对Rubocop的升级带来了一条新规则,即区块长度不得超过25行。我不确定它的原理,因为它没有在Ruby风格指南中列出。

过去,所有的Cop都是基于Ruby风格指南的,而RuboCop是一种遵循社区制定的实践的方式。

从那时起,方向发生了变化,RuboCop的范围已经扩大,以帮助开发人员确保其代码库的一致性。这导致了两件事:

  1. COP(即使是基于Ruby风格指南的COP)现在大部分都是可配置的
  2. 对于Ruby风格指南中没有提到的东西,有一些COP,但对于在项目中强制实现一致性仍然很有用

这个警察属于第二类。

RSpec是否使用了一种现在不可信的代码布局方法,以及在我们的RSpec测试中我有哪些合理的选项来减少块大小?

简短的回答是否定的。DSL仍然很酷。:-)

该cop针对命令式编程意义上的大型块。作为一般指南,它不适用于DSL,DSL通常是声明性的。例如具有长的路由。Rails中的rb文件是完全良性的。这只是大型应用程序的自然结果,而不是样式冲突。(进行大量测试简直太棒了。)

现在,RuboCop相当聪明,但是它不知道什么是DSL,所以我们不能自动忽略它们。有人可能会说我们可以排除流行框架的DSL入口方法,比如Rails routes和RSpec规范。不这样做的原因主要是:

  1. 假阴性。任何类都可以用相同的名称实现一个方法,取一个块
  2. RuboCop是一个Ruby分析工具,不应该真正了解外部库。(在我们拥有适当的扩展系统之前,排除/spec目录是一种礼貌,这可以由rubocop rspecgem处理。)

我的意思是,这是可以做到的,但以这种方式将一堆规范示例转换为辅助函数似乎与RSpec设计鼓励的可读方法相反。

底线是:RuboCop可以帮助我们编写更好的代码。如果我们的应用程序设计在其他方面是合理的,并且我们发现自己只是为了取悦RuboCop而使事情变得不那么可读,那么我们应该过滤,配置或禁用警察。

作为响应,我们简单地将 Rubocop 块大小规则设置为高阈值。但这让我想知道 - 我错过了什么?

这是一个相当直率的工具,正如你所暗示的,你可能会因此而有一些假阴性。此cop有两种类型的误报:

  1. 包含纯声明性 DSL 的文件,例如 Rails 路由、RSpec 规范。
  2. 将声明性 DSL 混合到大多数命令性代码中的文件,例如 Rails 模型中的 aasm 状态机声明。

在第一种情况下,最好的解决方案是排除文件或目录,而在第二种情况下使用内联禁用。

在您的情况下,您应该使用以下内容更新您的< code>.rubocop.yml:

Metrics/BlockLength:
  Exclude:
    - 'Rakefile'
    - '**/*.rake'
    - 'test/**/*.rb'

(请注意,您需要从默认配置中重新迭代基本排除,因为该列表将被覆盖。

弓泰
2023-03-14

如果一个特定的块通常太长,我指定它而不是文件

Metrics/BlockLength:
  IgnoredMethods: ['describe', 'context']
 类似资料:
  • 问题内容: 我目前正在尝试学习Numpy和Python。给定以下数组: 是否有一个函数返回尺寸(ega是一个2 x 2数组)的函数? 返回4并没有太大帮助。 问题答案: 是: ndarray。 数组尺寸的 形状 元组。 从而:

  • 这是我的家庭activity代码,当我运行它,它只是一个小尺寸的方框图,所有的内容都压缩在一个ver小图表。请帮助我如何使我的图表更大

  • 主要内容:jQuery 尺寸方法,jQuery 尺寸,jQuery width() 和 height() 方法,实例,jQuery innerWidth() 和 innerHeight() 方法,实例,jQuery outerWidth() 和 outerHeight() 方法,实例通过 jQuery,很容易处理元素和浏览器窗口的尺寸。 jQuery 尺寸方法 jQuery 提供多个处理尺寸的重要方法: width() height() innerWidth() innerHeight() ou

  • 问题内容: 我想切片一个numpy数组以获得最后一个维度中的第i个索引。对于3D阵列,这将是: 但是我正在编写一个函数,可以获取任意维度的数组,因此对于4D数组,我需要,依此类推。有没有一种方法可以获取任何数组的切片,而无需显式编写数组维? 问题答案: 存在或,它正是这样做的: 如果您想在方括号符号之外使用Ellipsis,则它是python对象。

  • 注意: Adobe Muse 不再添加新增功能,并将于 2020 年 3 月 26 日停止支持。有关详细信息和帮助,请参阅 Adobe Muse 服务结束页面。 使用参考线设置页眉、页脚和内容区域 主页包含五根可移动的水平参考线。顶部和底部的参考线确定整体页面大小。中间的两根参考线定义页面内容的主要部分:页眉下边缘与页脚区域上边缘之间的区域。在“设计”视图中将鼠标悬停在每根参考线上方以查看说明性工

  • 在CSS中,通过 width 和 height 属性来定义一个盒子的宽度和高度,可以用长度值或百分比来设置,不允许负值。使用百分比时,根据父元素的宽度进行计算盒子的宽度,根据父元素的高度进行计算盒子的高度。 如果一个盒子没有显式定义 width 属性,则宽度的计算结果跟定位类型相关:静态定位或相对定位的盒子,其宽度为父元素宽度的100%;绝对定位和浮动的盒子,其宽度根据所包含内容自动扩展,最大宽度