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테스트 주제를 선언 한 다음 나중에 다음 테스트 케이스에 재사용 할 수 있습니다. 이렇게하면 코드 반복이 줄어 듭니다 (코드 건조).
Letbefore: each테스트 데이터를 인스턴스 변수에 할당 하는 블록 의 대안 입니다. Let몇 가지 장점이 있습니다. 첫째, 인스턴스 변수에 할당하지 않고 값을 캐시합니다. 둘째, 게으르게 평가됩니다. 즉, 사양에서 요청할 때까지 평가되지 않습니다. 따라서 let테스트 속도를 높일 수 있습니다. let읽기도 쉽다고 생각합니다
subject테스트 대상이며 일반적으로 인스턴스 또는 클래스입니다. let테스트에서 변수를 할당하기위한 것으로 인스턴스 변수를 사용하는 것과 비교하여 느리게 평가됩니다. 이 스레드에는 몇 가지 좋은 예가 있습니다.