Rubocop 25行块大小和RSpec测试

一个典型的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结构以这种方式工作,并且不需要很多规范示例,其中每个示例可能具有几行特定设置,以便describe块与所描述主题的代码相同或更大。

最近Rubocop的升级带来了一个新规则,即块应该不超过25行。 我不确定它的基本原理,因为它没有在Ruby风格指南中列出。 我可以看到它为什么会是一件好事,并添加到默认规则集中。 但是,在升级之后,我们的Rubocop测试多次尝试失败,并显示诸如tests/component_spec.rb:151:3: C: Block has too many lines. [68/25] tests/component_spec.rb:151:3: C: Block has too many lines. [68/25]

通过Rubocop等代码度量工具,我喜欢有一个“使用默认值,链接到样式指南,完成工作”的策略。 (主要是因为辩论制表符vs空间和其他细节是在浪费时间,而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&Rubocop / Ruby Style Guide,通过编辑测试模板可以解决这个问题。


最近Rubocop的升级带来了一个新规则,即块应该不超过25行。 我不确定它的基本原理,因为它没有在Ruby风格指南中列出。

过去,所有的警察都是以Ruby风格指南为基础的,而RuboCop是一种坚持社区规定的做法。

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

  • 警察(即使是基于Ruby风格指南的警察)现在大都可以配置。
  • 有些警察在Ruby风格指南中没有提到,但对于在项目中强化一致性仍然很有用。
  • 这个警察属于第二类。

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

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

    这个警察在命令式编程意义上是针对大块的。 作为一般指南,它不适用于通常是声明式的DSL。 例如,在Rails中有一个很长的routes.rb文件是非常好的。 这只是大型应用程序的自然结果,而不是风格违规。 (并且有很多测试纯粹是太棒了。)

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

  • 假阴性。 任何类都可以实现一个方法,取一个块,名称相同。
  • RuboCop是一个Ruby分析工具,不应该真正了解外部库。 (不包括/spec目录是礼貌的,直到我们有一个适当的扩展系统,这可以通过rubocop-rspec gem来处理。)
  • 我的意思是,这是可行的,但以这种方式将一堆规范示例转换为辅助函数似乎与RSpec设计鼓励的可读方法相反。

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

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

    这是一个相当直率的工具,正如你暗示的那样,你可能会因为它而产生一些误报。 该警察有两种误报:

  • 包含纯粹声明式DSL的文件,例如Rails路线,RSpec规格。
  • 具有声明式DSL的文件大部分都是命令式的代码,例如Rails模型中的aasm状态机声明。
  • 在第一种情况下,最好的解决方案是排除文件或目录,并在第二种情况下使用内联禁用。

    在你的情况下,你应该更新你的.rubocop.yml

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

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


    免责声明:我是RuboCop的一位经常参与者,但不是维护者。 我从基础知识和基于以下许多问题的角度出发,充分了解了上述内容。


    我没有在rubocop的默认配置中看到Style / Blocklength选项,所以我在.rubocop.yml中使用了这个解决方案:

    Metrics/BlockLength:
      ExcludedMethods: ['describe', 'context']
    
    链接地址: http://www.djcxy.com/p/59307.html

    上一篇: Rubocop 25 line block size and RSpec tests

    下一篇: ruby