การทดสอบพร้อมกันในการทดสอบซอฟต์แวร์คืออะไร?

⚡ สรุปอย่างชาญฉลาด

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

  • 👥 เรียกอีกอย่างว่า: การทดสอบแบบหลายผู้ใช้ เนื่องจากตัวกระตุ้นคือการเข้าถึงพร้อมกัน ไม่ใช่ปริมาณการใช้งานที่มากเพียงอย่างเดียว
  • 🎯 เป้าหมาย: ข้อมูลในฐานข้อมูลที่ใช้ร่วมกัน โมดูลที่ใช้ร่วมกัน และโค้ดแอปพลิเคชันที่ใช้ร่วมกันซึ่งเข้าถึงได้โดยเซสชันมากกว่าหนึ่งเซสชัน
  • 🔒 มันวัดอะไร: ระดับของการติดตาย การล็อก โค้ดแบบเธรดเดียว และการเข้าถึงทรัพยากรที่ใช้ร่วมกันอย่างจำกัด
  • 🧭 วิธีการทำงาน: ระบุขั้นตอนการทำงานที่มีแนวโน้มที่จะเกิดการทำงานพร้อมกัน กำหนดเป้าหมายการทำงานพร้อมกัน เขียนสคริปต์สำหรับการดำเนินการจริง จากนั้นค่อยๆ เพิ่มจำนวนผู้ใช้ทีละน้อย
  • 🐞 ประเภทของข้อบกพร่อง: ปัญหาที่อาจเกิดขึ้น ได้แก่ สภาวะการแข่งขัน (Race conditions), การติดขัด (Deadlocks), การอัปเดตที่สูญหาย (Lost updates), ความเสียหายของข้อมูล (Data corruption) และการขาดแคลนเธรด (Thread starvation)
  • ⚠️ ขีดจำกัดที่ซื่อสัตย์: ความไม่แน่นอน การเรียกกลับแบบอะซิงโครนัส และสแต็กการเรียกที่ไม่ให้ข้อมูล ทำให้การจำลองความล้มเหลวทำได้ยาก

การทดสอบการทำงานพร้อมกัน (Concurrency testing) ในการทดสอบซอฟต์แวร์ที่มีผู้ใช้งานพร้อมกันหลายคนคืออะไร

การทดสอบพร้อมกันคืออะไร?

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

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

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

แผนภาพการทดสอบการทำงานพร้อมกัน แสดงให้เห็นผู้ใช้หลายคนเข้าถึงทรัพยากรแอปพลิเคชันเดียวกันพร้อมกัน

เหตุใดจึงต้องทดสอบการทำงานพร้อมกัน

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

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

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

วิธีการดำเนินการทดสอบการทำงานพร้อมกัน

การทดสอบการทำงานพร้อมกันเป็นไปตามลำดับที่ทำซ้ำได้ ขั้นตอนด้านล่างเริ่มจากขอบเขตที่กำหนดping เพื่อให้ได้ผลลัพธ์ที่ต้องการ

  • ขั้นตอนที่ 1) ระบุโฟลว์ที่มีแนวโน้มที่จะเกิดการทำงานพร้อมกัน มองหาสถานะที่ใช้ร่วมกัน: การเข้าสู่ระบบพร้อมกัน การจองที่นั่งหรือหุ้น การอัปเดตยอดคงเหลือ งานแบบแบตช์ที่เขียนข้อมูลลงในตารางเดียวกัน และส่วนประกอบแบบเธรดเดียวใดๆ ในเส้นทางการทำงาน
  • ขั้นตอนที่ 2) กำหนดเป้าหมายการทำงานพร้อมกัน กำหนดจำนวนผู้ใช้ที่ต้องดำเนินการพร้อมกัน โดยอิงจากช่วงเวลาที่มีการใช้งานสูงสุดจริง แทนที่จะเป็นตัวเลขกลมๆ
  • ขั้นตอนที่ 3) ออกแบบกรณีทดสอบ แต่ละ กรณีทดสอบ เป็นการจับคู่ทรัพยากรที่ใช้ร่วมกัน การกระทำที่แข่งขันกัน และสถานะสุดท้ายที่คาดหวังไว้ — ตัวอย่างเช่น การถอนเงินจากบัญชีเดียวกันสองครั้งไม่จำเป็นต้องสำเร็จทั้งคู่
  • ขั้นตอนที่ 4) เขียนสคริปต์และเลือกเครื่องมือ จำเป็นต้องมีตัวสร้างโหลดที่สามารถสร้างผู้ใช้เสมือนที่กำหนดค่าได้ JMeter เป็นตัวเลือกโอเพนซอร์สที่นิยมใช้กันทั่วไป และการตั้งค่ากลุ่มเธรดของมันจะสอดคล้องกับสถานการณ์การทำงานพร้อมกันโดยตรง
  • ขั้นตอน 5) Ramp ทีละน้อย เพิ่มจำนวนผู้ใช้งานพร้อมกันทีละน้อยแทนที่จะเพิ่มแบบกระโดดทีเดียวping ไปยังเป้าหมาย เพื่อให้เห็นระดับที่ความขัดแย้งเริ่มต้นขึ้น
  • ขั้นตอนที่ 6) ติดตามและวิเคราะห์ สังเกตการรอการล็อก การกระจายเวลาตอบสนอง อัตราข้อผิดพลาด และการบล็อกฐานข้อมูลไปพร้อมกัน — ข้อบกพร่องในการทำงานพร้อมกันมักแสดงออกมาในรูปของความผิดปกติทางเวลา ก่อนที่จะแสดงออกมาในรูปของข้อผิดพลาด
  • ขั้นตอนที่ 7) แก้ไขปัญหาและเรียกใช้งานใหม่อีกครั้ง แก้ไขสาเหตุของการซิงโครไนซ์ การจัดทำดัชนี หรือการล็อก จากนั้นทำซ้ำขั้นตอนเดิมเพื่อยืนยันว่าพฤติกรรมเปลี่ยนไป ไม่ใช่แค่การเคลื่อนย้ายตำแหน่ง

ข้อบกพร่องทั่วไปของการทำงานพร้อมกัน

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

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

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

ตัวอย่างการทดสอบการทำงานพร้อมกัน

ลองนึกภาพร้านค้าออนไลน์ที่มีสินค้าชิ้นสุดท้ายอยู่ในสต็อก ลูกค้าสองคนเปิดสินค้าในเวลาเดียวกันและกดปุ่มเดียวกัน ซื้อ.

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

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

ข้อดีของการทดสอบการทำงานพร้อมกัน

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

ข้อเสียของการทดสอบการทำงานพร้อมกัน

ข้อเสียที่ระบุไว้ด้านล่างนี้ มักเป็นสิ่งที่ผู้ทดสอบพบเจอขณะทำการทดสอบการทำงานพร้อมกัน (concurrency testing)

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

คำถามที่พบบ่อย

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

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

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

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

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

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

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

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

สรุปโพสต์นี้ด้วย: