UFO ET IT

RSpec의 주제와 let의 차이점은 무엇입니까?

ufoet 2020. 12. 3. 21:09
반응형

RSpec의 주제와 let의 차이점은 무엇입니까? 언제 사용해야합니까?


http://betterspecs.org/#subjectsubject에 대한 정보가 let있습니다. 그러나 나는 그들 사이의 차이점에 대해 여전히 불분명합니다. 또한, SO post RSpec 테스트에서 before, let 및 subject를 사용하는 것에 대한 주장은 무엇입니까? subject또는을 사용하지 않는 것이 좋습니다 let. 어디로 갈까요? 난 정말 혼란스러워.


요약 : RSpec의 주제는 테스트중인 개체를 참조하는 특수 변수입니다. 한 줄 예제를 지원하는 암시 적으로 기대치를 설정할 수 있습니다. 일부 관용적 인 경우 독자에게는 분명하지만 그렇지 않으면 이해하기 어렵고 피해야합니다. RSpec의 let변수는 단지 느리게 인스턴스화 된 (기억 된) 변수입니다. 주제만큼 어렵지는 않지만 여전히 테스트가 엉망이 될 수 있으므로 신중하게 사용해야합니다.

주제

작동 원리

주제는 테스트 대상입니다. RSpec은 주제에 대한 명확한 아이디어를 가지고 있습니다. 정의되거나 정의되지 않을 수 있습니다. 그렇다면 RSpec은 명시 적으로 참조하지 않고 메서드를 호출 할 수 있습니다.

기본적으로 가장 바깥 쪽 예제 그룹 ( describe또는 context블록) 의 첫 번째 인수가 클래스 인 경우 RSpec은 해당 클래스의 인스턴스를 만들고이를 주제에 할당합니다. 예를 들어, 다음 패스 :

class A
end

describe A do
  it "is instantiated by RSpec" do
    expect(subject).to be_an(A)
  end
end

다음을 사용하여 주제를 직접 정의 할 수 있습니다 subject.

describe "anonymous subject" do
  subject { A.new }
  it "has been instantiated" do
    expect(subject).to be_an(A)
  end
end

주제를 정의 할 때 이름을 지정할 수 있습니다.

describe "named subject" do
  subject(:a) { A.new }
  it "has been instantiated" do
    expect(a).to be_an(A)
  end
end

주제의 이름을 지정하더라도 익명으로 참조 할 수 있습니다.

describe "named subject" do
  subject(:a) { A.new }
  it "has been instantiated" do
    expect(subject).to be_an(A)
  end
end

둘 이상의 명명 된 주제를 정의 할 수 있습니다. 가장 최근에 정의 된 명명 된 주제는 anonymous subject입니다.

그러나 주제는 정의되어 있습니다.

  1. 느리게 인스턴스화됩니다. 즉, 설명 된 클래스의 암시 적 인스턴스화 또는 전달 된 블록의 실행은 예제에서 명명 된 주제가 참조 subject될 때까지 발생하지 않습니다 subject. 설명 주제를 열심히 인스턴스화하려면 (그룹의 예제가 실행되기 전에) subject!대신 라고 말하십시오 subject.

  2. 기대치를 암시 적으로 설정할 수 있습니다 (쓰기 subject또는 명명 된 주제의 이름 없이 ).

    describe A do
      it { is_expected.to be_an(A) }
    end
    

    제목은이 한 줄 구문을 지원하기 위해 존재합니다.

사용시기

암시 적 subject(예제 그룹에서 추론)은 이해하기 어렵습니다.

  • 뒤에서 인스턴스화됩니다.
  • 암시 적으로 ( is_expected명시 적 수신자없이 호출 하여) 사용하든 명시 적으로 (같이 subject) 사용하든 , 예상이 호출되는 객체의 역할이나 특성에 대한 정보를 독자에게 제공하지 않습니다.
  • 한 줄짜리 예제 구문에는 예제 설명 ( it일반 예제 구문 의 문자열 인수 )이 없으므로 독자가 예제의 목적에 대해 가지고있는 유일한 정보는 예상 자체입니다.

따라서 모든 독자가 컨텍스트를 잘 이해할 수 있고 실제로 예제 설명이 필요하지 않을 때 암시 적 주제를 사용하는 것이 도움이됩니다 . 표준 사례는 shoulda 매 처로 ActiveRecord 유효성 검사를 테스트하는 것입니다.

describe Article do
  it { is_expected.to validate_presence_of(:title) }
end

익명 subject( subject이름없이 정의 됨 )은 독자가 인스턴스화 방법을 볼 수 있기 때문에 조금 더 좋습니다.

  • 여전히 주제의 인스턴스화를 사용 된 위치에서 멀리 떨어 뜨릴 수 있습니다 (예 :이를 사용하는 많은 예제가있는 예제 그룹의 맨 위에), 여전히 따르기 어렵습니다.
  • 암시 적 주체가하는 다른 문제가 있습니다.

명명 된 주체는 의도를 드러내는 이름을 제공하지만 let변수 대신 명명 된 주체를 사용하는 유일한 이유 는 익명의 주체를 언젠가 사용하려는 경우이며 익명 주체를 이해하기 어려운 이유를 방금 설명했습니다.

따라서 명시 적 익명 subject또는 명명 된 주체 의 합법적 인 사용 은 매우 드뭅니다 .

let 변수

작동 원리

let variables are just like named subjects except for two differences:

  • they're defined with let/let! instead of subject/subject!
  • they do not set the anonymous subject or allow expectations to be called on it implicitly.

When to use them

It's completely legitimate to use let to reduce duplication among examples. However, do so only when it doesn't sacrifice test clarity. The safest time to use let is when the let variable's purpose is completely clear from its name (so that the reader doesn't have to find the definition, which could be many lines away, to understand each example) and it is used in the same way in every example. If either of those things isn't true, consider defining the object in a plain old local variable or calling a factory method right in the example.

let! is risky, because it's not lazy. If someone adds an example to the example group that contains the let!, but the example doesn't need the let! variable,

  • that example will be hard to understand, because the reader will see the let! variable and wonder whether and how it affects the example
  • the example will be slower than it needs to be, because of the time taken to create the let! variablle

So use let!, if at all, only in small, simple example groups where it's less likely that future example writers will fall into that trap.

The single-expectation-per-example fetish

There is a common overuse of subjects or let variables that's worth discussing separately. Some people like to use them like this:

describe 'Calculator' do
  describe '#calculate' do
    subject { Calculator.calculate }
    it { is_expected.to be >= 0 }
    it { is_expected.to be <= 9 }
  end
end

(This is a simple example of a method that returns a number for which we need two expectations, but this style can have many more examples/expectations if the method returns a more complicated value that needs many expectations and/or has many side effects that all need expectations.)

People do this because they've heard that one should have only one expectation per example (which is mixed up with the valid rule that one should only test one method call per example) or because they're in love with RSpec trickiness. Don't do it, whether with an anonymous or named subject or a let variable! This style has several problems:

  • The anonymous subject isn't the subject of the examples — the method is the subject. Writing the test this way screws up the language, making it harder to think about.
  • As always with one-line examples, there isn't any room to explain the meaning of the expectations.
  • The subject has to be constructed for each example, which is slow.

Instead, write a single example:

describe 'Calculator' do
  describe '#calculate' do
    it "returns a single-digit number" do
      result = Calculator.calculate
      expect(result).to be >= 0
      expect(result).to be <= 9
    end
  end
end

Subject and let are just tools to help you tidy up and speed up your tests. People in the rspec community do use them so i wouldn't worry about whether it's ok to use them or not. They can be used similarly but serve slightly different purposes

Subject allows you to declare a test subject, and then reuse it for any number of following test cases afterward. This reduces code repetition (DRYing up your code)

Let is an alternative to before: each blocks, which assign test data to instance variables. Let gives you a couple of advantages. First, it caches the value without assigning it to an instance variable. Second, it is lazily evaluated, which means that it doesn't get evaluated until a spec calls for it. Thus let helps you speed up your tests. I also think let is easier to read


subject is what is under test, usually an instance or a class. let is for assigning variables in your tests, which are evaluated lazily vs. using instance variables. There are some nice examples in this thread.

https://github.com/reachlocal/rspec-style-guide/issues/6

참고URL : https://stackoverflow.com/questions/38437162/whats-the-difference-between-rspecs-subject-and-let-when-should-they-be-used

반응형