http://betterspecs.org/#subject 에 subject
및 에 대한 정보가 let
있습니다. 그러나 나는 그들 사이의 차이점에 대해 여전히 불분명합니다. 또한, SO 포스트 RSpec 테스트에서 before, let 및 subject를 사용하는 것에 대한 주장은 무엇입니까? subject
또는을 사용하지 않는 것이 좋습니다 let
. 어디로 갈까요? 난 정말 혼란스러워.
http://betterspecs.org/#subject 에 subject
및 에 대한 정보가 let
있습니다. 그러나 나는 그들 사이의 차이점에 대해 여전히 불분명합니다. 또한, SO 포스트 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
변수는 두 가지 차이점을 제외하고 명명 된 주제와 같습니다.
let
/ let!
대신 subject
/subject!
subject
암시 적으로 기대할 수 있도록 허용 하지 않습니다 .let
예제 간의 중복을 줄이기 위해 사용 하는 것은 완전히 합법적 입니다. 그러나 테스트 명확성을 희생하지 않는 경우에만 그렇게하십시오. 사용하기에 가장 안전한시기 let
는 let
변수의 목적이 이름에서 완전히 명확하고 (따라서 독자가 각 예제를 이해하기 위해 여러 줄이있을 수있는 정의를 찾을 필요가 없도록) 동일한 방식으로 사용되는 경우입니다. 모든 예에서. 그 중 하나라도 사실이 아니라면, 평범한 오래된 지역 변수에 객체를 정의하거나 예제에서 바로 팩토리 메소드를 호출하는 것을 고려하십시오.
let!
게으르지 않기 때문에 위험합니다. 누군가가 포함 된 예제 그룹에 예제를 추가 let!
했지만 예제에 let!
변수 가 필요하지 않은 경우
let!
변수 를보고 그것이 예에 어떤 영향을 미치는지 궁금 할 것이기 때문입니다.let!
변수 를 만드는 데 걸리는 시간 때문에 예제는 필요한 것보다 느립니다.따라서 let!
미래의 예제 작성자가 그 함정에 빠질 가능성이 적은 작고 단순한 예제 그룹에서만을 사용하십시오.
let
별도로 논의 할 가치가있는 주제 또는 변수 의 일반적인 남용이 있습니다. 어떤 사람들은 다음과 같이 사용하고 싶어합니다.
describe 'Calculator' do
describe '#calculate' do
subject { Calculator.calculate }
it { is_expected.to be >= 0 }
it { is_expected.to be <= 9 }
end
end
(이것은 우리가 두 가지 기대치를 필요로하는 숫자를 반환하는 메서드의 간단한 예입니다. 그러나 메서드가 많은 기대치를 필요로하는 더 복잡한 값을 반환하고 / 또는 많은 부작용이있는 경우이 스타일은 더 많은 예 / 기대치를 가질 수 있습니다. 모두 기대가 필요합니다.)
사람들은 예제 당 하나의 기대 값 만 가져야한다고 들었 기 때문에 (예제 당 하나의 메서드 호출 만 테스트해야한다는 유효한 규칙과 섞여 있음) 또는 RSpec 까다로운 것을 좋아하기 때문에 이렇게합니다. 익명, 명명 된 주체 또는 let
변수로 하지 마십시오 ! 이 스타일에는 몇 가지 문제가 있습니다.
대신 단일 예를 작성하십시오.
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
:aggregate_failures
과 같은 행 에서 태그를 사용할 수 있습니다 it "marks a task complete", :aggregate_failures do
(Rails 5 Test Prescriptions 책에서 가져옴)
expect(result).to be_between(0, 9)
.
expect(result.to_s).to match(/^[0-9]$/)
추악하다는 것을 알고 있지만 실제로 말하는 내용을 테스트하거나 between
+를 사용 is_a? Integer
하지만 여기서는 테스트 중입니다. 유형도. 그리고 단지 let
.. 그것은 관심 대상이되어서는 안되며, 실제로는 예제 사이의 값을 재평가하는 것이 더 나을 수 있습니다. 그렇지 않으면 게시물 +1
let!
하고 내 팀원을 스스로 설득하지 못했습니다. 이 답변을 보내 드리겠습니다.
Subject
그리고 let
당신의 검사 결과까지 당신이 정돈 도움과 속도 단지 도구입니다. rspec 커뮤니티의 사람들은 그것들을 사용하기 때문에 그것들을 사용해도 괜찮은지는 걱정하지 않을 것입니다. 유사하게 사용할 수 있지만 용도가 약간 다릅니다.
Subject
테스트 주제를 선언 한 다음 나중에 다음 테스트 케이스에 재사용 할 수 있습니다. 이렇게하면 코드 반복이 줄어 듭니다 (코드 건조).
Let
before: each
테스트 데이터를 인스턴스 변수에 할당 하는 블록 의 대안 입니다. Let
몇 가지 장점이 있습니다. 첫째, 인스턴스 변수에 할당하지 않고 값을 캐시합니다. 둘째, 게으르게 평가됩니다. 즉, 사양에서 요청할 때까지 평가되지 않습니다. 따라서 let
테스트 속도를 높일 수 있습니다. let
읽기도 쉽다고 생각합니다
subject
테스트 대상이며 일반적으로 인스턴스 또는 클래스입니다. let
테스트에서 변수를 할당하기위한 것으로 인스턴스 변수를 사용하는 것과 비교하여 느리게 평가됩니다. 이 스레드에는 몇 가지 좋은 예가 있습니다.