RSpec의 주제와 let의 차이점은 무엇입니까? 언제 사용해야합니까?
http://betterspecs.org/#subject 에 subject
및 에 대한 정보가 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
입니다.
그러나 주제는 정의되어 있습니다.
느리게 인스턴스화됩니다. 즉, 설명 된 클래스의 암시 적 인스턴스화 또는 전달 된 블록의 실행은 예제에서 명명 된 주제가 참조
subject
될 때까지 발생하지 않습니다subject
. 설명 주제를 열심히 인스턴스화하려면 (그룹의 예제가 실행되기 전에)subject!
대신 라고 말하십시오subject
.기대치를 암시 적으로 설정할 수 있습니다 (쓰기
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 ofsubject
/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.
'UFO ET IT' 카테고리의 다른 글
Swift에서 UILabel의 textColor를 설정하는 방법 (0) | 2020.12.03 |
---|---|
R에는 Python과 같은 startswith 또는 endswith 기능이 있습니까? (0) | 2020.12.03 |
이름이 'recipient'인 양식 컨트롤에 대한 값 접근자가 없습니다. (0) | 2020.12.03 |
속성 데코레이터를 사용하여 속성을 설정하는 방법은 무엇입니까? (0) | 2020.12.03 |
언제 save !, create!를 사용합니까? (0) | 2020.12.03 |