RSpec에서 인스턴스 변수보다 `let`을 선택하는 이유
테스트하려고 했던 간단한 Rails 모델이 있습니다.
class Task < ApplicationRecord
def toggle(task_completed:)
update(completed: task_completed)
end
def complete
update(completed: true)
end
end
두 가지 방법에 해당하는 두 가지 테스트를 추가했습니다.
RSpec.describe Task, type: :model do
it "toggles a task" do
task = Task.create(description: "Do Something", completed: false)
expect(task.completed).to be false
task.toggle(task_completed: true)
expect(task.completed).to be true
end
it "completes a task" do
task = Task.create(description: "Do Something", completed: false)
expect(task.completed).to be false
task.complete
expect(task.completed).to be true
end
end
이러한 테스트는 잘 실행되지만 각 메서드에서 작업 생성 코드를 반복하고 있습니다. 우리는 각 테스트에 대해 수동으로 작업을 생성하고 싶지 않습니다. 그것은 지루할 것입니다. 이러한 중복으로 인해 테스트를 리팩토링하기가 어렵습니다. 또한 설정 세부 정보로 테스트하려는 비즈니스 논리에서 초점을 분산시키고 전환합니다.
이제 이 중복을 줄이는 세 가지 다른 방법을 찾았습니다. RSpec에서 제공하는 후크를 사용하거나 헬퍼 메서드를 사용하거나
let
구문을 사용하십시오. 하나씩 살펴보겠습니다.before
후크 사용before { @task = Task.create(description: "Do Something", completed: false) }
인스턴스 변수 사용에는 몇 가지 단점이 있습니다.
nil
로 초기화합니다. 따라서 @task
를 @tasky
로 잘못 입력하면 Ruby는 즉시 실패하는 대신 @tasky
인 새 인스턴스 변수 nil
를 반환합니다. 따라서 혼란스러운 오류 메시지와 함께 테스트가 실패하거나 미묘한 버그가 발생할 수도 있습니다. task
항목을 @task
로 변경해야 합니다. 도우미 메서드 사용
def task
@task ||= Task.create(description: "Do Something", completed: false)
end
여기에서는 사양이
@task
메서드를 처음 호출할 때만 task
를 생성합니다. 그때부터 모든 사양은 인스턴스 변수를 사용합니다. 이 접근 방식은 위의 모든 단점을 해결합니다. 그러나 오른쪽 작업이 잘못된 값을 반환하면 캐싱이 작동하지 않습니다. 메서드는 메서드가 호출될 때마다 해당 작업을 호출합니다.let
구문 사용let(:task) { Task.create(description: "Do Something", completed: false) }
let
는 메모화된 도우미 메서드를 정의합니다. 평이한 영어로 let
가 지연 평가됨을 의미합니다. RSpec은 테스트가 처음으로 let
메서드를 호출하려고 시도할 때만 task
블록을 실행합니다. Ruby가 task
를 던질 것이기 때문에 NameError
철자가 틀릴 가능성이 없습니다.그러나
let
는 모든 사양에서 결과를 캐시하지 않는다는 점을 명심해야 합니다. 각 사양은 블록 실행에서 해당 값을 가져옵니다. 예를 들어, 첫 번째 사양이 완료된 것으로 표시하더라도 두 번째 사양의 완료되지 않은 작업에서 시작한다는 점에 유의하십시오.RSpec.describe Task, type: :model do
let(:task) { Task.create(description: "Do Something", completed: false) }
it "toggles a task" do
expect(tasky.completed).to be false
task.toggle(task_completed: true)
expect(task.completed).to be true # complete the task
end
it "completes a task" do
expect(task.completed).to be false # task is incomplete, as it's a new task
task.complete
expect(task.completed).to be true
end
end
이 게시물이 테스트에서 중복 설정 코드를 줄일 수 있는 다양한 방법을 이해하는 데 도움이 되었기를 바랍니다. 다른 접근 방식을 알고 있거나 위의 다른 장단점을 알고 있다면 알려주십시오.
Reference
이 문제에 관하여(RSpec에서 인스턴스 변수보다 `let`을 선택하는 이유), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/software_writer/why-choose-let-over-instance-variables-in-rspec-3f2p텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)