典型的な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
理想的な仕様では、各例は比較的短く正確です。ただし、RSpec構造はこのように機能し、describe
説明されているサブジェクトのコードと同じサイズまたはそれよりも大きいブロック。
最近のRubocopのアップグレードにより、ブロックが25行を超えてはならないという新しいルールが導入されました。 Rubyスタイルガイド に記載されていないため、その理由はわかりません。なぜそれが良いことなのかがわかり、デフォルトのルールセットに追加されました。ただし、アップグレード後、Rubocopテストはtests/component_spec.rb:151:3: C: Block has too many lines. [68/25]
のようなメッセージで複数回失敗します
Rubocopなどのコードメトリックツールでは、Ilikeのポリシーを使用して、「デフォルトを使用、スタイルガイドへのリンク、ジョブ完了」というポリシーを設定します。 (主にタブとスペースおよび他の特徴点の議論が時間を浪費し、IMEneverが解決されるため)これは明らかに不可能であり、2つのコアデータ品質ツールはコードレイアウトアプローチに同意しません-または、少なくともそれが結果の解釈方法です。仕様の記述方法に本質的に問題はありません。
それに応じて、Rubocopブロックサイズルールを高いしきい値に設定するだけです。しかし、それは私が不思議に思う-私は何が欠けていますか? RSpecは現在、コードレイアウトに信用されていないアプローチを使用していますか?また、RSpecテストでブロックサイズを削減するためにどのreasonableオプションが必要ですか?大きなブロックを回避するためにコードを再構築する方法を見ることができますが、それらは例外なく、Rubocopのルールを純粋に満たすことを意図したexceptionいハックです。すべてのブロックをヘルパー関数に分割します。
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 Style Guideに基づいていましたが、RuboCopはコミュニティによって設定された慣行に従う方法でした。
それ以来、方向が変わり、RuboCopの範囲が拡大して、開発者が一般にコードベースの一貫性を確保できるようになりました。これにより、次の2つのことが起こりました。
この警官は2番目のカテゴリに分類されます。
RSpecはコードレイアウトに信用を失ったアプローチを使用していますか?また、RSpecテストでブロックサイズを小さくするには、どのような合理的なオプションが必要ですか?
短い答えはノーです。 DSLはまだクールです。 :-)
この警官は、命令型プログラミングの意味での大きなブロックを対象としています。一般的なガイドとして、DSLには適用されません。DSLはしばしば宣言的です。たとえば、Railsに長いroutes.rb
ファイルがあるのは完全に無害です。スタイル違反ではなく、大規模なアプリケーションの自然な結果です。本当に素晴らしいです。)
現在、RuboCopはかなりスマートですが、DSLが何であるかがわからないため、自動的に無視することはできません。 RailsルートやRSpec仕様などの一般的なフレームワークのDSLエントリメソッドを除外できると主張することができます。そうしない理由は主に次のとおりです。
/spec
ディレクトリを除外することは、適切な拡張システムができるまでは礼儀です。 rubocop-rspec
gemによって処理されます。)つまり、これは実行可能ですが、このように仕様例の束をヘルパー関数に変換することは、RSpec設計で推奨される読みやすいアプローチの反対のようです。
肝心なのは、RuboCopはより良いコードを書くのに役立つことです。私たちのアプリケーションの設計がそれ以外の点で健全であり、RuboCopを喜ばせるためだけに物事を読みにくくしていることに気付いた場合、警官をフィルタリング、構成、または無効にする必要があります。 :-)
それに応じて、Rubocopブロックサイズルールを高いしきい値に設定するだけです。しかし、それは私が不思議に思う-私は何が欠けていますか?
これはかなり鈍いツールであり、あなたがほのめかしているように、おそらくあなたはそれのためにいくつかの偽陰性を持つでしょう。この警官には2種類の誤検知があります。
aasm
ステートマシン宣言。前者の場合、ファイルまたはディレクトリを除外するのが最善の解決策であり、後者ではインライン無効化を使用するのが最善の解決策です。
あなたの場合は、.rubocop.yml
を次のように更新する必要があります。
Metrics/BlockLength:
Exclude:
- 'Rakefile'
- '**/*.rake'
- 'test/**/*.rb'
(リストが上書きされるため、デフォルトの構成から基本的な除外を再度繰り返す必要があることに注意してください。)
特定のブロックが通常長すぎる場合、ファイルではなく指定します
Metrics/BlockLength:
ExcludedMethods: ['describe', 'context']