典型的RSpec单元测试广泛使用嵌套的Ruby块来构造代码并利用DSL" magic"将规范读作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结构以这种方式工作,并且没有采用许多规范示例,每个示例可能具有几行特定设置,以到达{{ 1}}与所描述的主题的代码相同或更大的块。
最近Rubocop的升级带来了新的规则,块不应超过25行。我不确定它的基本原理,因为它没有在Ruby style guide中列出。我可以看到为什么它可能是一件好事,并添加到默认规则集。但是,升级后,我们的Rubocop测试会多次出现describe
使用Rubocop等代码指标工具,我喜欢的策略是"使用默认值,链接到样式指南,完成工作。" (主要是因为辩论选项卡与空格和其他细节是浪费时间,并且IME 从未得到解决)这显然是不可能的,我们的两个核心数据质量工具不同意代码布局方法 - 或者至少这就是我如何解释结果,我没有看到我们如何编写规范本质上有任何错误。
作为回应,我们只是将Rubocop块大小规则设置为高阈值。但这让我想知道 - 我错过了什么? RSpec是否使用了现在已经失去信誉的代码布局方法,以及我在RSpec测试中减少块大小的合理的选项是什么?我可以看到重构代码的方法,以避免大块,但它们毫无例外地纯粹是为了满足Rubocop的规则,例如将所有块分解为辅助函数:
tests/component_spec.rb:151:3: C: Block has too many lines. [68/25]
。 。 。我的意思是,这是可行的,但以这种方式将一系列规范示例转换为辅助函数似乎与RSpec设计所鼓励的可读方法相反。
除了找到忽视它的方法之外,还有什么我可以做的吗?
我在这里找到的关于此主题的最接近的问题是RSpec & Rubocop / Ruby Style Guide,这看起来可以通过编辑测试模板来解决。
答案 0 :(得分:76)
如果特定块通常太长,我指定它而不是文件
Metrics/BlockLength:
ExcludedMethods: ['describe', 'context']
答案 1 :(得分:68)
最近Rubocop的升级带来了新的规则,块不应超过25行。我不确定它的基本原理,因为它没有在Ruby样式指南中列出。
过去所有的警察都是基于“红宝石风格指南”,而RuboCop是一种遵循社区规定的做法的方式。
从那时起,方向发生了变化,RuboCop的范围已经扩展到帮助开发人员确保其代码库的一致性。这导致了两件事:
此警察属于第二类。
RSpec是否使用了现在已经失去信誉的代码布局方法,以及在RSpec测试中我有哪些合理的选项来减少块大小?
简短的回答是否定的。 DSL仍然很酷。 : - )
这个警察针对命令式编程意义上的大块。作为一般指南,它不适用于通常是声明性的DSL。例如,在Rails中拥有一个很长的routes.rb
文件是完全良性的。它只是大型应用程序的自然结果,而不是样式违规。 (并且进行了大量测试非常棒。)
现在,RuboCop非常聪明,但它并不知道什么是DSL而不是,所以我们不能自动忽略它们。有人可能会说我们可以排除流行框架的DSL入口方法,比如Rails路由和RSpec规范。不这样做的原因主要是:
/spec
目录是礼貌的,直到我们有一个适当的扩展系统,这可以由rubocop-rspec
gem处理。)我的意思是,这是可行的,但以这种方式将一系列规范示例转换为辅助函数似乎与RSpec设计所鼓励的可读方法相反。
底线是:RuboCop可以帮助我们编写更好的代码。如果我们的应用程序设计是合理的,并且我们发现自己只是为了取悦RuboCop而不那么可读,那么我们应该过滤,配置或禁用警察。 : - )
作为回应,我们只是将Rubocop块大小规则设置为高阈值。但这让我想知道 - 我错过了什么?
这是一个相当生硬的工具,正如你所暗示的那样,你可能会因此而产生一些误报。这个警察有两种类型的误报:
aasm
状态机声明。在第一种情况下,最好的解决方案是排除文件或目录,在第二种情况下使用内联禁用。
在您的情况下,您应该使用以下内容更新.rubocop.yml
Metrics/BlockLength:
Exclude:
- 'Rakefile'
- '**/*.rake'
- 'test/**/*.rb'
(请注意,您需要从默认配置中重新排除基本排除,因为列表将被覆盖。)