Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การทดสอบบริการเครือข่ายใน Ruby ง่ายกว่าที่คุณคิด

คุณได้เริ่มโครงการใหม่และถึงเวลาที่รหัสของคุณต้องพึ่งพาบริการของบุคคลที่สาม อาจเป็นบางอย่างเช่นElasticSearch, Resque, ผู้ให้บริการเรียกเก็บเงิน หรือ HTTP API โดยพลการ คุณเป็นนักพัฒนาที่ดี ดังนั้นคุณต้องการให้โค้ดนี้ได้รับการทดสอบอย่างดี แต่คุณจะทดสอบโค้ดที่ส่งคำขอไปยังบริการที่อยู่นอกเหนือการควบคุมของคุณได้อย่างไร

คุณสามารถข้ามการทดสอบได้ แต่ในไม่ช้าคุณจะซ้อนโค้ดเพิ่มเติมบนรากฐานที่สั่นคลอน โค้ดที่ยังไม่ได้ทดสอบมีแนวโน้มที่จะดึงดูดโค้ดที่ซับซ้อนมากขึ้น และในที่สุดคุณจะรู้สึกว่าโค้ดเป็นตัวสร้าง torefactor ที่อันตรายเกินไป เนื่องจากคุณไม่มีขอบเขตการทดสอบที่คุณต้องการเพื่อให้รู้สึกปลอดภัย คุณต้องการสร้างรากฐานที่มั่นคงสำหรับงานในอนาคตของคุณ แต่กลับกลายเป็นว่าคุณต้องพบกับความยุ่งเหยิงที่รักษาไม่หาย

การหลีกเลี่ยงสถานการณ์นี้ง่ายกว่ามาก! ด้วยเครื่องมือเพียงเล็กน้อยและความพยายามเพียงเล็กน้อย คุณสามารถแยกการทดสอบออกจากบริการที่โค้ดของคุณพึ่งพา เขียนโค้ดที่ง่ายกว่า และมีความมั่นใจในการปรับปรุงโค้ดที่คุณเขียนโดยไม่ต้องแนะนำบั๊ก แทนที่จะผัดวันประกันพรุ่งเพราะคุณไม่รู้ว่าจะเขียนแบบทดสอบต่อไปอย่างไร คุณสามารถดูการโต้ตอบระหว่างโค้ดของคุณกับโลกภายนอก และรู้วิธีที่จะพุ่งเข้าใส่ตรงกลางของโค้ดนั้นได้อย่างแม่นยำ

มอคค่า:วิธีที่รวดเร็วและสกปรก

มอคค่าเป็นวิธีที่ง่ายที่สุดในการเข้าร่วมระหว่างโค้ดของคุณกับโลกภายนอก

ตัวอย่างเช่น สมมติว่าคุณมี Cart วัตถุที่เรียกการเรียกเก็บเงินจากบัตรเครดิตเมื่อได้รับการชำระเงิน คุณต้องการให้แน่ใจว่ารถเข็นมีข้อความแสดงข้อผิดพลาดแนบมาด้วยหากการเรียกเก็บเงินล้มเหลว

คุณอาจไม่ต้องการให้การทดสอบของคุณ ตี ระบบการเรียกเก็บเงินทุกครั้งที่ทำการทดสอบ แม้ว่าคุณจะทำเช่นนั้น อาจเป็นเรื่องยากที่จะบังคับให้บริการนั้นส่งคืนความล้มเหลว นี่คือสิ่งที่จะดูเหมือนกับมอคค่า:

def test_error_message_set_on_charge_failure
  cart = Cart.new(items)
  cart.stubs(:charge!).returns(false) # mocha in action
  cart.checkout!
  assert_equal "The credit card could not be charged", cart.credit_card_error
end

มอคค่าอาจล้มเหลวในการทดสอบของคุณได้เช่นกัน หากวิธีการไม่ได้ถูกเรียกในแบบที่คุณคาดหวัง:

def test_only_bill_once_per_cart
  cart = Cart.new(items)
  cart.expects(:charge!).once # Don't double-bill, no matter how many times we check out
  cart.checkout!
  cart.checkout!
end

มอคค่าใช้งานง่าย แต่มีประโยชน์อย่างเหลือเชื่อ คุณต้องระวังว่าคุณกำลังเยาะเย้ย เท่านั้น พฤติกรรมที่คุณไม่ต้องการให้เกิดขึ้น เป็นการง่ายที่จะล้อเลียนและซ่อนข้อบกพร่องที่แท้จริง คุณไม่ต้องการที่จะลงน้ำด้วยวิธีนี้:การทดสอบเต็มไปด้วยexpects และ stubs อ่านแล้วคิดยาก

ทดสอบของปลอม:แนวทางที่ฉันชอบ

หากคุณล้อเลียนหรือนำวิธีการเดิมๆ มาวางบนวัตถุเดียวกันตลอดเวลา คุณสามารถส่งเสริมการล้อเลียนของคุณให้เป็นวัตถุที่เต็มเปี่ยมได้ (บางครั้งเรียกว่า ทดสอบของปลอม ) ดังนี้:

def test_billed_full_amount_minus_discount
  test_payment_provider = TestPaymentProvider.new # A fake payment provider
  cart = Cart.new(items, discount: 30, provider: test_payment_provider)
  cart.checkout!

  assert_equal items.sum(:&price) * 0.7, test_payment_provider.total_charges
end

ของปลอมนั้นยอดเยี่ยม:

  • ของปลอมสามารถติดตามสถานะภายในได้

    ของปลอมอาจมีข้อความยืนยันที่กำหนดเองและฟังก์ชันตัวช่วยที่ทำให้การเขียนการทดสอบของคุณง่ายขึ้น เช่น total_charges วิธีการตามตัวอย่างข้างต้น

  • ในฐานะที่เป็นออบเจ็กต์เต็มรูปแบบ คุณจะได้รับตัวแก้ไขเพิ่มเติมและการสนับสนุนด้านภาษา

    หากคุณกำลังใช้ตัวแก้ไขที่สนับสนุน คุณสามารถรับการเติมข้อความอัตโนมัติ เอกสารอินไลน์ และสิ่งอื่น ๆ ที่คุณไม่สามารถทำได้โดยใช้ Mocha อธิบายแต่ละวิธี คุณจะได้รับการตรวจสอบที่ดีขึ้น การจัดการข้อยกเว้น และสิ่งอื่น ๆ ที่คุณต้องการสร้างเป็นของปลอม

  • หากคุณใช้ของปลอมในโหมดการพัฒนา คุณไม่จำเป็นต้องเชื่อมต่อกับบริการจริง

    คุณสามารถเขียนแอปของคุณบนรถบัส คุณไม่จำเป็นต้องมีบริการมากมายจนแบตเตอรี่แล็ปท็อปของคุณหมด และคุณสามารถตั้งค่าบริการปลอมเหล่านี้เพื่อส่งคืนข้อมูลที่คุณต้องการเพื่อดำเนินการผ่านเคส Edge โดยไม่ต้องใช้อะไรมาก ตั้งค่า

  • วัตถุเหล่านี้สามารถใช้นอกการทดสอบของคุณ

    นี่อาจเป็นส่วนที่ฉันชอบที่สุดของของปลอม คุณสามารถมีบันทึกไคลเอ็นต์การบันทึกสำหรับทั้งบริการของบุคคลที่สามและของปลอม ซึ่งได้รับการสนับสนุนโดยอาร์เรย์ในหน่วยความจำ จากนั้นคุณสามารถดัมพ์เนื้อหาของอาร์เรย์นี้ในมุมมองผู้ดูแลระบบบนไซต์ของคุณ ทำให้ง่ายต่อการตรวจสอบว่าคุณกำลังบันทึกสิ่งที่คุณคิดว่ากำลังบันทึกอยู่

คุณสามารถทำสิ่งนี้:

  fake_backend = FakeBackend.new
  LoggingService.backends = [RealBackend.new, fake_backend]
  LoggingService.debug("TEST MESSAGE PLEASE IGNORE")
  fake_backend.messages.first # => [:debug, "TEST MESSAGE PLEASE IGNORE"]

การเขียนของปลอมนั้นต้องใช้ความพยายามมากกว่าการคัดแยกวิธีการแต่ละอย่าง แต่ด้วยการฝึกฝน ไม่ควรใช้เวลามากกว่าหนึ่งหรือสองชั่วโมงในการสร้างของปลอมที่เป็นประโยชน์ หากคุณสร้างสิ่งที่จะเป็นประโยชน์ต่อผู้อื่น แบ่งปัน! ฉันสร้างหน่วยมานานแล้ว และผู้คนจำนวนมากยังคงใช้อยู่จนถึงทุกวันนี้

ฉันจะฉีดวัตถุเหล่านี้ได้อย่างไร

คุณจะต้องทดสอบวัตถุของคุณเพื่อพูดคุยกับของปลอมเหล่านี้ โชคดีที่ Ruby ละเมิดได้ง่ายจนการฉีดของปลอมไม่ใช่เรื่องยาก

หากคุณควบคุม API ของอ็อบเจ็กต์ที่กำลังทดสอบ เป็นการดีที่สุดที่จะเพิ่มพารามิเตอร์เริ่มต้น แอตทริบิวต์ หรือตัวเลือกตัวสร้างซึ่งคุณสามารถตั้งค่าของปลอมได้:

class Card
  attr_reader :provider
  def initialize(items, options={})
    @provider = options.fetch(:provider) { RealProvider.new }
  end
end

สิ่งนี้สะอาดเมื่อคุณพูดคุยกับบริการจริงและช่วยให้คุณเพิ่มความยืดหยุ่นได้ในภายหลัง

หากคุณไม่ได้ควบคุมอ็อบเจ็กต์หรือไม่ต้องการเพิ่มพารามิเตอร์พิเศษ คุณสามารถแก้ไขลิงได้เสมอ:

# if in test mode
Card.class_eval do
  def provider
    @provider ||= TestProvider.new
  end
end

การทดสอบนั้นน่าเกลียดกว่า แต่สะอาดกว่าในสภาพแวดล้อมที่ไม่ใช้ของปลอม

เริ่มสร้างของปลอมของคุณเองตอนนี้

การสร้างของปลอมจะง่ายขึ้นด้วยการฝึกฝน ดังนั้นคุณควรลองทำดู:

  • ค้นหาการทดสอบที่พูดคุยกับบริการภายนอก การทดสอบที่จะล้มเหลวหากคุณตัดการเชื่อมต่อจากอินเทอร์เน็ตถือเป็นตัวเลือกที่ดี
  • หาว่าอ็อบเจกต์ใดที่ทำการสื่อสารจริงๆ และโค้ดของคุณเรียกอะไรกับออบเจกต์นั้น
  • สร้างคลาสของอ็อบเจ็กต์ที่ว่างเปล่าเป็นส่วนใหญ่ และบันทึกการโทรที่คุณทำกับอาร์เรย์
  • เพิ่มวิธีการปลอมของคุณเพื่อส่งคืนรายการการโทร
  • สลับของจริงกับของปลอมใหม่ของคุณ และเขียนคำยืนยันต่อต้านการโทรที่โค้ดของคุณทำ

หากคุณได้ลองใช้แล้ว แจ้งให้เราทราบด้วยว่าผลจะเป็นอย่างไร!

ด้วยเทคนิคเหล่านี้ จะใช้เวลาไม่นานจนกว่าคุณจะสามารถควบคุมการโต้ตอบที่บ้าคลั่งที่สุดระหว่างแอปพลิเคชันของคุณกับโลกภายนอกได้ ต้นขั้วง่ายๆ ในที่ที่ถูกต้องจะช่วยให้คุณจัดส่งโค้ดที่ผ่านการทดสอบมาอย่างดีด้วยความมั่นใจ