หากแอปพลิเคชัน Ruby ของคุณใช้ API ภายนอกใดๆ คุณอาจประสบปัญหา การทดสอบช้าและขีดจำกัดอัตรา API .
วิธีแก้ปัญหาคืออะไร?
คุณสามารถ stub วิธี HTTP ด้วยตนเองจากไลบรารีไคลเอนต์ของคุณ และส่งคืนการตอบกลับที่กำหนดไว้ล่วงหน้าบางส่วน
แต่นั่นเป็นงานและโค้ดที่น่าเกลียดมาก!
ทางออกที่ดีกว่าคือการใช้ ส่วนผสมอันทรงพลังของอัญมณี เช่น Webmock + VCR .
WebMock สกัดกั้นคำขอ HTTP จากไลบรารี HTTP ทั่วไป เช่น:
- เน็ต/http
- ฟาราเดย์
- RestClient
- …อีกมากมาย!
วิธีนี้มีประโยชน์เพียงอย่างเดียว แต่คุณยังต้องระบุข้อมูลการตอบกลับ
นี่คือที่มาของ VCR…
VCR ทำงานร่วมกับ WebMock เพื่อบันทึกการตอบกลับ HTTP ที่สร้างโดยโค้ดของคุณ .
การบันทึกเหล่านี้เรียกว่า “เทปคาสเซ็ท”
เมื่อคุณทำการทดสอบ :
VCR จะโหลดไฟล์เทปและส่งคืนคำตอบที่บันทึกไว้ คุณจะได้รับคำตอบเร็วขึ้นเพราะไม่ต้องถาม API จริง
มาดูตัวอย่างโค้ดกัน!
ตัวอย่างโค้ด VCR
สำหรับตัวอย่างนี้ เราจะใช้ RSpec เนื่องจากจะทำงานร่วมกับ VCR ได้ดีขึ้น ดังที่คุณเห็นในหัวข้อถัดไป
นี่คือรหัสที่เราต้องการทดสอบ :
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 จริง &ผ่าน แต่จะใช้เวลาประมาณครึ่งวินาทีในการดำเนินการ
ครึ่งวินาทีสำหรับการทดสอบ ONE!
อาจดูเหมือนไม่มาก แต่ลองนึกภาพว่าคุณมีการทดสอบเป็นร้อย ๆ ครั้ง ซึ่งเท่ากับ 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 วินาทีเท่านั้น!
“มีการร้องขอ HTTP ซึ่ง VCR ไม่ทราบวิธีจัดการ”
หากคุณพบข้อความแสดงข้อผิดพลาดนี้ หมายถึงหนึ่งในสองสิ่งต่อไปนี้:
1.คุณกำลังพยายามโทร HTTP โดยเปิดใช้ VCR แต่อยู่นอก VCR.use_cassette
บล็อก
วิธีแก้ปัญหา :โดยค่าเริ่มต้น VCR + WebMock จะบล็อกคำขอ HTTP ทั้งหมด คุณสามารถเปลี่ยนแปลงสิ่งนี้ได้ด้วยตัวเลือกการกำหนดค่า เพิ่มบล็อก VCR ที่ขาดหายไป หรือใช้ข้อมูลเมตา RSpec (ส่วนถัดไป)
2.คุณกำลังพยายามส่งคำขอที่แตกต่างออกไป &ใช้คาสเซ็ตต์ที่ไม่ตรงกับ URL นี้ ตัวอย่างเช่น หากคุณขอในการทดสอบของคุณ /users/ruby
เทปจะถูกสร้างขึ้นโดยเฉพาะสำหรับ URL นี้ หากคุณเปลี่ยนการทดสอบเป็น /users/apple
คุณจะเห็นข้อผิดพลาดนี้เนื่องจากเทปนั้นใช้สำหรับ 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 แล้ว คุณจึงเขียนการทดสอบสำหรับแอป Ruby ได้โดยไม่ต้องรอการตอบกลับ API ภายนอก!
หากคุณชอบบทความนี้ อย่าลืมแชร์บทความนี้เพื่อให้คนอื่นๆ ได้สนุกไปกับมัน
ขอบคุณที่อ่านนะคะ 🙂