ทดสอบไคลเอ็นต์ REST กับเซิร์ฟเวอร์ REST ติดตั้งอย่างไร?


10

เมื่อเขียนการทดสอบหน่วยเป็นเรื่องปกติที่จะใช้อุปกรณ์ติดตั้ง: ข้อมูลที่ทดสอบได้เพียงเล็กน้อยดังนั้นเราจึงสามารถพูดได้: 1. รับลูกค้าทั้งหมดควรรวม Willy Wonka 2. ลบไคลเอนต์ 3 และตอนนี้รับไคลเอนต์ไม่ควรรวมวิลลี่วองก้าอีกต่อไป

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

แต่จะเกิดอะไรขึ้นเมื่อเราแยกเซิร์ฟเวอร์ REST ออกจากไคลเอนต์ REST

เราต้องการตรวจสอบให้แน่ใจว่าลูกค้า REST ของเราไม่เพียง แต่อ่านอย่างถูกต้อง แต่สร้างอัปเดตและลบอย่างถูกต้อง

ฉันไม่สามารถค้นหาตัวอย่างหรือคำแนะนำสำหรับวิธีการนี้กับเซิร์ฟเวอร์ REST ทดสอบระยะไกล

สมมติว่าฉันได้ทดสอบเซิร์ฟเวอร์ REST ที่ให้บริการติดตั้งเท่านั้น ลักษณะไร้สัญชาติทั้งหมดของ HTTP หมายความว่าเป็นการยากที่จะส่ง "BEGIN TRANSACTION" และ "ROLLBACK TRANSACTION" หรือ "RELOAD FIXTURES" ประเภทข้อความใช่ไหม

ฉันไม่สามารถเป็นคนแรกที่ต้องการทำสิ่งนี้ดังนั้นฉันจึงรู้สึกว่าฉันต้องการวิธีคิดที่แตกต่างออกไป

ข้อเสนอแนะใด ๆ


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

หากปัญหาหลักของคุณคือการนำเซิร์ฟเวอร์ทดสอบของคุณกลับสู่สถานะที่กำหนดไว้ล่วงหน้าทำไมคุณไม่เพิ่มฟังก์ชั่นการทดสอบพิเศษบางอย่างเช่น "RELOAD TESTDATA" ลงใน API ส่วนที่เหลือของคุณเพื่อทำสิ่งที่คุณต้องการ? แน่นอนคุณควรตรวจสอบให้แน่ใจว่าการเรียก API ไม่สามารถใช้งานได้
Doc Brown

คำตอบ:


7

ระบบซอฟต์แวร์มีขอบเขตของระบบและส่วนต่อประสานที่กำหนดไว้อย่างดี บริการ REST เป็นตัวอย่างที่ดีของเรื่องนี้

ไปสิ้นสุดที่ผมจะแนะนำให้กับการทำสิ่งที่คุณกำลังพยายามที่จะทำ

โดยเฉพาะ:

เราต้องการตรวจสอบให้แน่ใจว่าลูกค้า REST ของเราไม่เพียง แต่อ่านอย่างถูกต้อง แต่สร้างอัปเดตและลบอย่างถูกต้อง

สิ่งที่ฉันอยากจะแนะนำคือ:

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

  • สร้างการทดสอบสำหรับเซอร์วิส REST ของคุณ (ถ้าคุณควบคุมนั่นคือ) เพื่อทำงานตามฟังก์ชันที่ต้องการ

  • ทำการทดสอบใกล้กับโดเมนปัญหาของตนเองเพื่อให้สามารถช่วยแนะนำการออกแบบและพัฒนาสิ่งที่สำคัญในบริบทนั้น


3
คุณยกเลิกแนวคิดทั้งหมดของการทดสอบการรวมที่นี่ค่อนข้างเป็นทางการ ฉันไม่คิดว่าวิธีการนี้ได้รับแจ้งจากการปฏิบัติ
febeling

ขอบคุณสำหรับคำแนะนำที่เป็นประโยชน์ทั้งหมด นอกจากนี้โดย Twitter ฉันได้รับคำแนะนำที่ดีในการลอง Ruby gem "webmock" และคล้ายกับจำลองการตอบสนองของเซิร์ฟเวอร์ REST API ฉันเห็นด้วยกับ "ความรู้สึกขุ่นเคือง" ว่าสิ่งที่ฉันกำลังอธิบายดูเหมือนจะเป็นการทดสอบการรวมกันมากกว่าดังนั้นฉันจะดูแยกกัน ขอบคุณทุกคนอีกครั้ง - Derek
sivers

การเยาะเย้ย API เป็นวิธีที่ดีในการแก้ปัญหา แต่คุณจะแน่ใจได้อย่างไรว่า API จำลอง == API จริง
FrEaKmAn

4

สองมุมที่ต้องจำไว้ที่นี่:

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

2

ฉันคิดว่าการแกล้งตอบสนองเซิร์ฟเวอร์ REST เป็นวิธีที่ดีที่สุดในการทดสอบลูกค้า

สำหรับ Ruby มีอัญมณี FakeWeb ซึ่งคุณสามารถใช้ในการปล่อยการตอบสนองของปลอม - https://github.com/chrisk/fakeweb

นอกจากนี้ใน JavaScript คุณสามารถใช้สิ่งที่ต้องการ Sinon.JS ซึ่งช่วยให้คุณมีเซิร์ฟเวอร์ปลอม - http://sinonjs.org/docs/#fakeServer


1

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

ใช้ไคลเอนต์ Python แบบสมมุติที่ใช้urllib2สำหรับการร้องขอ คุณอาจจะมีวิธีการบางอย่างในลูกค้าที่ขอเรียกว่าget()ที่มีการเรียกร้องให้urllib2.Request()อยู่ในนั้น get()คุณต้องการจริงๆที่จะเยาะเย้ยการเรียกร้องให้ของชั้นเรียนของคุณเอง

@patch('your.Client.get')
def test_with_mock(self, your_mock):
    your_mock.return_value({'some': 'json'})
    test_obj = your.Client.get_object(5)
    your_mock.assert_called_with('/the/correct/endpoint/5')

ตัวอย่างที่ง่ายมากนี้ใช้ห้องสมุดจำลองของ Python เพื่อทดสอบyour.Clientคลาสสมมุติด้วยget_object()วิธีที่สร้าง URL ที่ถูกต้องเพื่อรับบางสิ่งบางอย่างจาก API บางตัว ในการร้องขอให้ไคลเอ็นต์เรียกget()ใช้เมธอดด้วย url นั้น ที่นี่วิธีการนั้นถูกเยาะเย้ย ( your.Client.getคือ "แพตช์" เพื่อให้มันอยู่ภายใต้การควบคุมของyour_mock) และการทดสอบจะตรวจสอบว่ามีการร้องขอปลายทางที่ถูกต้องหรือไม่

เมธอดที่เยาะเย้ยส่งคืนการตอบสนอง JSON ที่กำหนดค่าyour_mock.return_valueซึ่งไคลเอ็นต์ต้องจัดการและคุณจะทำการยืนยันเพิ่มเติมเพื่อทดสอบว่าจัดการข้อมูลที่คาดหวังในวิธีที่คาดหวังไว้


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

1

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

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

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

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

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


1

แพทช์ลิง

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

ประโยชน์ที่ได้รับ

  • ไม่ต้องซิงโครไนซ์กับการเริ่มต้นเซิร์ฟเวอร์ (เพราะไม่มีเซิร์ฟเวอร์)
  • ยกระดับการตั้งค่าหน่วยแบบคลาสสิกและวิธีการแยกส่วนเพื่อจัดการสิ่งต่าง ๆ เช่นการแข่งขัน
  • ความสามารถในการใช้ mocks / ต้นขั้วและแพทช์ลิงอื่น ๆ สำหรับการควบคุมที่ละเอียดยิ่งขึ้นของการทดสอบ
  • สามารถเขียนได้โดยใช้กรอบ xUnit

ความสมดุล

  • ไม่เปิดเผยการโต้ตอบ / ปัญหาหลายขั้นตอน (การล็อกการขาดทรัพยากร ฯลฯ )
  • ไม่เปิดเผยปัญหาเกี่ยวกับเซิร์ฟเวอร์หลายตัว (การจัดลำดับข้อมูลลักษณะการทำคลัสเตอร์)
  • ไม่เปิดเผยปัญหาเครือข่ายเนื่องจากเป็นการจำลอง (การเข้าถึงข้อผิดพลาดการหมดเวลา ฯลฯ )
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.