Programing

Rubocop 25 라인 블록 크기 및 RSpec 테스트

lottogame 2020. 12. 27. 10:16
반응형

Rubocop 25 라인 블록 크기 및 RSpec 테스트


일반적인 RSpec 단위 테스트는 코드를 구조화하고 DSL "마법"을 사용하여 사양을 BDD 문처럼 읽도록하기 위해 중첩 된 Ruby 블록을 광범위하게 사용합니다.

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 구조가 이러한 방식으로 작동하고 각각 몇 줄의 특정 설정이있을 수있는 많은 사양 예제를 사용하지 않기 때문에 외부 블록이 100 줄 이상으로 증가하는 것이 일반적으로 보입니다 describe. 설명되는 주제의 코드와 동일하거나 더 큽니다.

최근 Rubocop의 업그레이드로 인해 블록이 25 줄을 넘지 않아야한다는 새로운 규칙이 적용되었습니다. Ruby 스타일 가이드에 나와 있지 않기 때문에 그 이유를 잘 모르겠습니다 . 왜 이것이 좋은지 알 수 있으며 기본 규칙 세트에 추가되었습니다. 그러나 업그레이드 후 Rubocop 테스트가 다음과 같은 메시지와 함께 여러 번 실패합니다.tests/component_spec.rb:151:3: C: Block has too many lines. [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 & Rubocop / Ruby Style Guide 였으며 테스트 템플릿을 편집하여 해결할 수있는 것처럼 보였습니다.


최근 Rubocop의 업그레이드로 인해 블록이 25 줄을 넘지 않아야한다는 새로운 규칙이 적용되었습니다. Ruby 스타일 가이드에 나와 있지 않기 때문에 그 이유를 잘 모르겠습니다.

예전에는 모든 경찰이 The Ruby Style Guide를 기반으로했고, RuboCop은 커뮤니티에서 정한 관행을 고수하는 방법이었습니다.

그 이후 방향이 바뀌었고 RuboCop의 범위가 확장되어 개발자가 일반적으로 코드베이스의 일관성을 보장 할 수 있습니다. 이로 인해 두 가지가 발생했습니다.

  1. 경찰 (루비 스타일 가이드에 기반한 경찰도 포함)은 이제 대부분 구성이 가능합니다.
  2. 루비 스타일 가이드에 언급되지 않았지만 여전히 프로젝트의 일관성을 유지하는 데 유용한 경찰이 있습니다.

이 경찰은 두 번째 범주에 속합니다.

RSpec은 코드 레이아웃에 대해 지금은 신뢰할 수없는 접근 방식을 사용하고 있습니까? RSpec 테스트에서 블록 크기를 줄이기 위해 어떤 합리적인 옵션이 필요합니까?

짧은 대답은 아니오입니다. DSL은 여전히 ​​멋지다. :-)

이 경찰은 명령형 프로그래밍 측면에서 큰 블록을 목표로합니다. 일반적인 가이드로서 종종 선언적인 DSL에는 적용되지 않습니다. 예를 들어, routes.rbRails에 파일이 있으면 완벽하게 무해합니다. 스타일 위반이 아니라 대규모 애플리케이션의 자연스러운 결과입니다. (그리고 많은 테스트를하는 것은 순전히 굉장합니다.)

이제 RuboCop은 꽤 똑똑하지만 DSL이 무엇인지 모르기 때문에 자동으로 무시할 수 없습니다. Rails 경로 및 RSpec 사양과 같은 인기있는 프레임 워크의 DSL 입력 방법을 제외 할 수 있다고 주장 할 수 있습니다. 그렇게하지 않는 이유는 주로 다음과 같습니다.

  1. 거짓 부정. 모든 클래스는 동일한 이름의 블록을 사용하여 메서드를 구현할 수 있습니다.
  2. RuboCop은 Ruby 분석 도구이며 외부 라이브러리에 대해 알면 안됩니다. ( /spec디렉토리를 제외하는 것은 우리가 적절한 확장 시스템을 가질 때까지 예의이며 이것은 rubocop-rspecgem에서 처리 할 수 ​​있습니다 .)

내 말은, 그것은 가능하지만, 이런 방식으로 많은 스펙 예제를 도우미 함수로 바꾸는 것은 RSpec 디자인에서 권장하는 읽기 쉬운 접근 방식과 반대 인 것 같습니다.

The bottom line is: RuboCop is there to help us write better code. If our application design is otherwise sound, and we find ourselves making things less readable merely to please RuboCop, then we should filter, configure, or disable the cop. :-)

In response, we have simply set the Rubocop block size rule to a high threshold. But that makes me wonder - what am I missing?

This is a rather blunt tool and, as you're hinting at, you will probably have some false negatives because of it. There are two types of false positives for this cop:

  1. Files that contain purely declarative DSLs, e.g. Rails routes, RSpec specs.
  2. Files that have a declarative DSL mixed into mostly imperative code, e.g. an aasm state machine declaration in a Rails model.

In the first case, the best solution is to exclude the file or directory, and in the second to use an inline disable.

In your case, you should update your .rubocop.yml with:

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

(Note that you need to re-iterate the basic excludes from the default configuration, since the list will be overwritten.)


If a specific block is usually too long, I specify it rather than the files

Metrics/BlockLength:
  ExcludedMethods: ['describe', 'context']

ReferenceURL : https://stackoverflow.com/questions/40934345/rubocop-25-line-block-size-and-rspec-tests

반응형