วิธีทดสอบโค้ดที่ขึ้นอยู่กับ API ที่ซับซ้อน (เช่น Amazon S3)


13

ฉันกำลังดิ้นรนกับการทดสอบวิธีการอัปโหลดเอกสารไปยัง Amazon S3 แต่ฉันคิดว่าคำถามนี้ใช้กับ API / การพึ่งพาภายนอกที่ไม่สำคัญใด ๆ ฉันเพิ่งได้วิธีแก้ปัญหาที่อาจเกิดขึ้นสามข้อ แต่ก็ไม่น่าพอใจ:

  1. ทำการเรียกใช้รหัสอัปโหลดเอกสารตรวจสอบกับ API ของ AWS ว่ามีการอัปโหลดแล้วและลบออกเมื่อสิ้นสุดการทดสอบ สิ่งนี้จะทำให้การทดสอบช้ามากจะเสียค่าใช้จ่ายทุกครั้งที่ทำการทดสอบและจะไม่ส่งคืนผลลัพธ์เดียวกัน

  2. จำลอง S3 มันมีขนดกมากเพราะฉันไม่รู้ว่าภายในของวัตถุนั้นและรู้สึกผิดเพราะมันซับซ้อนเกินไป

  3. เพียงตรวจสอบให้แน่ใจว่า MyObject.upload () ถูกเรียกด้วยอาร์กิวเมนต์ที่ถูกต้องและมั่นใจว่าฉันใช้วัตถุ S3 อย่างถูกต้อง ทำให้ฉันรำคาญใจเพราะไม่มีทางรู้แน่ว่าฉันใช้ S3 API อย่างถูกต้องจากการทดสอบเพียงอย่างเดียว

ฉันตรวจสอบว่า Amazon ทดสอบ SDK ของตัวเองอย่างไรและพวกเขาทำทุกอย่างเยาะเย้ย พวกเขามีผู้ช่วย 200 สายที่ทำหน้าที่เยาะเย้ย ฉันไม่รู้สึกว่ามันเป็นเรื่องจริงสำหรับฉันที่จะทำเช่นเดียวกัน

ฉันจะแก้ปัญหานี้ได้อย่างไร


ไม่ใช่คำตอบ แต่ในทางปฏิบัติเราใช้สามวิธีที่คุณเปิดเผย
jlhonora

คำตอบ:


28

มีสองประเด็นที่เราต้องดูที่นี่

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

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

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

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

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

คนหนึ่งได้พบแนวทางที่มีค่าเกี่ยว mocks คือการไม่ได้เยาะเย้ยประเภทคุณทำไม่ได้เอง Amazon เป็นเจ้าของ API ถึง S3 ดังนั้นพวกเขาจึงมั่นใจได้ว่าจะไม่มีการเปลี่ยนแปลงด้านล่าง ในทางกลับกันคุณไม่มีการรับรองเหล่านี้ ดังนั้นหากคุณจำลอง S3 API ในการทดสอบของคุณมันอาจเปลี่ยนและทำลายรหัสของคุณในขณะที่การทดสอบของคุณทั้งหมดแสดงสีเขียว ดังนั้นเราจะทดสอบรหัสหน่วยที่ใช้ไลบรารีบุคคลที่สามได้อย่างไร

เราทำไม่ได้ ถ้าเราทำตามคำแนะนำเราไม่สามารถเยาะเย้ยวัตถุที่เราไม่ได้เป็นเจ้าของ แต่…ถ้าเราเป็นเจ้าของการพึ่งพาโดยตรงของเราเราสามารถเยาะเย้ยพวกเขาออกมา แต่อย่างไร เราสร้าง wrapper ของเราเองสำหรับ S3 API เราสามารถทำให้มันดูเหมือน S3 API หรือเราสามารถทำให้มันเหมาะกับความต้องการของเราอย่างใกล้ชิด (ต้องการ) เรายังสามารถทำให้มันเล็ก ๆ น้อย ๆ ที่เป็นนามธรรมมากขึ้นพูดมากกว่าPersistenceService จะเป็นอินเทอร์เฟซที่มีเมธอดเช่นและประเภทของวิธีที่เราอาจต้องการดู (นี่คือตัวอย่างคุณอาจต้องการวิธีการที่แตกต่างกัน) ตอนนี้เราสามารถใช้S3 API (พูดก), encapsulating มันออกไปจากรหัสโทรศัพท์ของเราAmazonS3BucketPersistenceService#save(Thing)#fetch(ThingId)PersistenceServiceS3PersistenceService

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

รหัสทั้งหมดที่ใช้ในการใช้ S3 API ตอนนี้ใช้ของเราโดยตรงPersistenceServiceและS3PersistenceServiceตอนนี้เราทำการโทรไปยัง S3 API ในการทดสอบของเราเราสามารถเยาะเย้ยPersistenceServiceเพราะเราเป็นเจ้าของและใช้จำลองเพื่อให้แน่ใจว่ารหัสของเราทำการโทรที่ถูกต้อง S3PersistenceServiceแต่ตอนนี้ที่ใบวิธีการทดสอบ มีปัญหาเช่นเดียวกับก่อนหน้านี้: เราไม่สามารถทดสอบหน่วยโดยไม่เรียกใช้บริการภายนอก ดังนั้น…เราไม่ได้ทำการทดสอบ เราสามารถเยาะเย้ยการพึ่งพา S3 API แต่สิ่งนี้จะทำให้เรามีความมั่นใจเพิ่มขึ้นเล็กน้อย แต่เราต้องทดสอบในระดับที่สูงกว่า: การทดสอบการรวมระบบ

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

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


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

@ Yerken ในขณะที่ฉันกำลังคิดเกี่ยวกับมันฉันค่อนข้างมั่นใจว่าฉันสามารถตอบคำถามอีกต่อไปได้นาน นั่นอาจคุ้มค่าสำหรับคุณเพราะคุณอาจได้รับมากกว่าแค่คำตอบของฉัน
cbojar

4

คุณต้องทำทั้งสองอย่าง

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

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

การทดสอบครั้งแรกตรวจสอบว่ารหัสของคุณใช้งานได้จริงกับ S3 การทดสอบครั้งที่สองที่รหัสของคุณเรียกรหัสที่พูดถึง S3 อย่างถูกต้อง


2

ฉันจะบอกว่ามันขึ้นอยู่กับความซับซ้อนของการใช้ API ของคุณ

  1. คุณต้องทำการทดสอบอย่างน้อยที่สุดที่เรียกใช้ S3 API และยืนยันว่าได้ผลตั้งแต่ต้นจนจบ

  2. นอกจากนี้คุณยังต้องทำการทดสอบเพิ่มเติมที่ไม่ได้เรียก API จริงๆเพื่อให้คุณสามารถทดสอบซอฟต์แวร์ของคุณเองอย่างเพียงพอโดยไม่ต้องเรียกใช้ API ตลอดเวลา

คำถามที่ยังคงมีอยู่: คุณต้องจำลอง API หรือไม่

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

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


1

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

แทนที่จะเป็นการเยาะเย้ยคำตอบ S3 แต่ละรายการด้วยตนเองคุณสามารถใช้ประโยชน์จากกรอบการเยาะเย้ยที่มีความซับซ้อนมาก เช่นmotoมีฟังก์ชันการทำงานที่คล้ายกับ S3 API จริง

นอกจากนี้คุณยังสามารถดูLocalStackซึ่งเป็นกรอบซึ่งรวมเครื่องมือที่มีอยู่และจัดเตรียมสภาพแวดล้อมระบบคลาวด์ในท้องถิ่นที่ทำงานได้อย่างสมบูรณ์ (รวมถึง S3) ที่อำนวยความสะดวกในการทดสอบการรวมระบบ

แม้ว่าเครื่องมือเหล่านี้บางส่วนจะเขียนด้วยภาษาอื่น (Python) แต่ควรง่ายต่อการหมุนสภาพแวดล้อมการทดสอบในกระบวนการภายนอกจากการทดสอบของคุณใน Java / JUnit

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.