Ruby 애플리케이션이 모든 종류의 외부 API를 사용하는 경우 느린 테스트 및 API 속도 제한 문제에 직면했을 것입니다. .
해결책은 무엇입니까?
클라이언트 라이브러리에서 HTTP 메서드를 수동으로 스텁하고 미리 결정된 응답을 반환할 수 있습니다.
하지만 그것은 많은 작업과 추한 코드입니다!
더 나은 솔루션은 Webmock + VCR과 같은 강력한 보석 조합을 사용하는 것입니다. .
WebMock은 다음과 같은 일반적인 HTTP 라이브러리의 HTTP 요청을 가로챕니다.
- net/http
- 패러데이
- 레스트클라이언트
- … 더 많이!
이것만으로도 유용하지만 응답 데이터를 제공해야 합니다.
여기에서 VCR이 등장합니다...
VCR은 WebMock과 함께 작동하여 코드로 작성된 HTTP 응답을 기록합니다. .
이러한 녹음을 "카세트"라고 합니다.
테스트를 실행할 때 :
VCR은 카세트 파일을 로드하고 녹음된 응답을 반환합니다. 실제 API를 요청할 필요가 없기 때문에 더 빠른 응답을 받을 수 있습니다.
몇 가지 코드 예제를 살펴보겠습니다!
VCR 코드 예
이 예에서는 다음 섹션에서 볼 수 있듯이 VCR과 더 잘 통합되기 때문에 RSpec을 사용할 것입니다.
테스트할 코드는 다음과 같습니다. :
require "faraday" require "json" class Github def self.user(name) url = "https://api.github.com/users/#{name}" data = Faraday.get(url).body JSON.parse(data, symbolize_names: true) end end
특정 사용자에 대한 정보를 얻기 위해 Github API에 요청합니다. 매우 간단하지만 VCR 작동 방식을 배우는 데 도움이 됩니다.
이 코드에 대한 테스트는 다음과 같습니다. :
require "rspec/autorun" require_relative "github_api_example" describe Github do let(:user_response) { Github.user("ruby") } it "can fetch & parse user data" do expect(user_response).to be_kind_of(Hash) expect(user_response).to have_key(:id) expect(user_response).to have_key(:type) end end
이것은 실제 API에 도달하고 통과하지만 완료하는 데 0.5초 정도 걸립니다.
한 번의 테스트에 0.5초!
별 것 아닌 것 같지만 100개의 테스트가 있다고 상상해 보세요. 모든 테스트를 실행하는 데 50초가 소요됩니다.
문제를 해결할 시간입니다...
이 코드를 추가하여 VCR을 소개하겠습니다. :
require "vcr" VCR.configure do |c| c.cassette_library_dir = "spec/vcr" c.hook_into :webmock end<블록 인용>
test_helper
에 이 코드를 추가할 수 있습니다. 파일이므로 모든 테스트에서 사용할 수 있습니다.
이 configure
으로 VCR에 카세트 파일을 저장할 위치를 알려주고 WebMock 통합을 활성화하는 것을 차단합니다.
Faraday 또는 Excon을 사용하는 경우 VCR에서 직접 연결할 수 있습니다.
:webmock
만 바꾸세요. :faraday
사용 또는 :excon
.
다음 :
VCR에 카세트의 이름과 이 아래에서 실행해야 하는 코드를 알려야 합니다.
방법은 다음과 같습니다. :
let(:user_response) do VCR.use_cassette("github/user") { Github.user("ruby") } end
테스트를 실행할 때 VCR은 cassette_library_dir
아래에 파일을 생성합니다. , 이 경우 파일 이름은 spec/vcr/github/user.yaml
입니다. , 팔로우하고 계시다면 한 번 보시는 것도 좋을 것 같습니다.
지금 테스트를 실행하면 훨씬 빨라집니다 .
사실...
완료하는 데 0.01초밖에 걸리지 않습니다!
"VCR이 처리 방법을 모르는 HTTP 요청이 생성되었습니다."
이 오류 메시지가 나타나면 다음 두 가지 중 하나를 의미합니다.
1. VCR이 활성화된 상태에서 HTTP 호출을 시도하고 있지만 VCR.use_cassette
외부에 있습니다. 차단합니다.
해결책 :기본적으로 VCR + WebMock은 모든 HTTP 요청을 차단합니다. 구성 옵션으로 이를 변경하거나 누락된 VCR 블록을 추가하거나 RSpec 메타데이터(다음 섹션)를 사용할 수 있습니다.
2. 다른 요청을 하고 이 URL과 일치하지 않는 카세트를 사용하려고 합니다. 예를 들어 테스트 /users/ruby
에서 요청하는 경우 , 테스트를 /users/apple
로 변경하면 이 URL에 대해 특별히 카세트가 생성됩니다. 카세트가 다른 URL용이기 때문에 이 오류가 표시됩니다.
해결책 :다른 URL에 대해 다른 카세트를 사용하고 new_episodes
를 활성화합니다. 녹화 모드(vcr: { record: :new_episodes }
) 또는 요청 URL을 업데이트한 후 이전 카세트를 삭제하십시오.
RSpec 메타데이터를 사용하는 방법
VCR.use_cassette
방법은 이 보석을 사용하는 좋은 방법입니다.
하지만...
VCR이 자동으로 카세트를 생성하도록 할 수도 있습니다.
어떻게?
VCR.configure
안에 이것을 추가하십시오. 차단:
c.configure_rspec_metadata!
이제 특정 테스트에 대해 VCR을 활성화할 수 있습니다(it
블록) 또는 테스트 그룹(describe
) ).
좋아요 :
describe Github, :vcr do # ... end
이렇게 하면 테스트 설명의 이름을 따서 명명된 카세트 파일이 생성됩니다. :
spec/vcr/ └── Github ├── can_parse_user_data.yml └── can_test_vcr.yml
이렇게 하면 테스트당 하나의 카세트가 생성됩니다.
두 개의 테스트가 동일한 요청을 하고 동일한 데이터를 사용하더라도. VCR에서 별도의 카세트를 만듭니다.
유용한 VCR 옵션 및 팁
카세트에 문제가 있거나 데이터의 새로운 버전이 필요한 경우 카세트 파일을 삭제할 수 있습니다 .
VCR은 새로운 API 응답을 기록하고 문제를 해결할 수 있습니다.
하지만 그렇지 않다면 어떻게 될까요?
디버그 모드를 활성화할 수 있습니다. VCR.configure
에서 :
VCR.configure do |c| # ... c.debug_logger = $stderr end
이렇게 하면 많은 출력이 생성될 수 있으므로 관심 있는 항목으로만 테스트를 제한하세요.
다음 :
API 응답의 일부로 API 키 또는 기타 민감한 데이터가 있다고 가정해 보겠습니다.
녹음에서 해당 데이터를 필터링할 수 있습니다.
방법은 다음과 같습니다. :
VCR.configure do |c| # ... c.define_cassette_placeholder("<API_KEY>", ENV["API_KEY"]) end
요약
WebMock 및 VCR gem을 사용하는 방법을 배웠으므로 외부 API 응답을 기다릴 필요 없이 Ruby 앱에 대한 테스트를 작성할 수 있습니다!
마음에 드시면 이 기사를 공유하여 더 많은 사람들이 즐길 수 있도록 하는 것을 잊지 마세요.
읽어주셔서 감사합니다 🙂