การทดสอบที่ไม่สม่ำเสมอ: การกำจัดฝันร้ายที่มีชีวิตในการทดสอบ

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

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

คุณธรรมของเรื่องราวนั้นสรุปได้ดีที่สุดโดยผู้เขียนเอง:

“คนโกหกจะไม่ถูกเชื่อ แม้ว่าเขาจะพูดความจริงก็ตาม”

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

การทดสอบ Front-End: ทำไมต้องกังวล?

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

คุณควรระลึกว่าการทดสอบส่วนหน้าหมายถึงอะไร โดยพื้นฐานแล้ว การทดสอบส่วนหน้าคือชุดแนวทางปฏิบัติสำหรับการทดสอบ UI ของเว็บแอปพลิเคชัน รวมถึงฟังก์ชันการทำงาน

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

ศาสตร์แห่งการทดสอบที่ไม่สม่ำเสมอ

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

เมื่อฉันจำฝันร้ายในการทดสอบของฉันได้ มีกรณีหนึ่งที่เข้ามาในหัวของฉันโดยเฉพาะ มันอยู่ในการทดสอบ UI เราได้สร้างกล่องคำสั่งผสมแบบกำหนดเอง (เช่น รายการที่เลือกได้พร้อมช่องป้อนข้อมูล):

ตัวอย่างตัวเลือกแบบกำหนดเอง
ตัวเลือกที่กำหนดเองในโครงการที่ฉันทำงานทุกวัน (ตัวอย่างขนาดใหญ่)

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

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

สกรีนช็อตจากการดำเนินการ CI พร้อมการทดสอบที่ไม่สม่ำเสมอ
การทดสอบที่ไม่สม่ำเสมอ: เหตุใดจึงล้มเหลวเพียงบางครั้งและไม่เสมอไป (ตัวอย่างขนาดใหญ่)

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

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

ปัญหาสำคัญอีกประการหนึ่งเกี่ยวกับการทดสอบที่ผิดพลาดคือทัศนคติที่พวกเขาปลูกฝังให้กับนักพัฒนาของเรา เมื่อฉันเริ่มทำงานในการทดสอบอัตโนมัติ ฉันมักจะได้ยินนักพัฒนาพูดสิ่งนี้เพื่อตอบสนองต่อการทดสอบที่ล้มเหลว:

“อ่า ตึกนั้น ไม่เป็นไร เดี๋ยวเตะใหม่ สักวันมันก็จะผ่านไป”

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

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

สาเหตุ

ดังนั้นการทดสอบที่เป็นขุยจึงเป็นปัญหา เราควรทำอย่างไรกับพวกเขา? ถ้าเรารู้ปัญหา เราสามารถออกแบบกลยุทธ์ตอบโต้ได้

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

ในส่วนต่อไปนี้ เราจะพูดถึงส่วนที่พบบ่อยที่สุดที่ฉันพบ

1. สาเหตุด้านการทดสอบ

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

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

 { "id": "f1d2554b0ce847cd82f3ac9bd1c0dfca", "name": "Variant product", }

ข้อผิดพลาดข้อที่สองคือการค้นหา ตัวเลือกที่ไม่ซ้ำกัน เพื่อใช้ในการทดสอบ UI และคิดว่า “โอเค ID นี้ดูไม่เหมือนใคร ฉันจะใช้มัน”

 <!-- This is a text field I took from a project I worked on --> <input type="text" />

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

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

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

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

ตัวอย่างหนึ่งคือการใช้เวลารอที่ไม่ถูกต้อง โดยเฉพาะอย่างยิ่งในการทดสอบ UI ตัวอย่างเช่น โดยใช้ เวลารอคงที่ บรรทัดต่อไปนี้นำมาจากการทดสอบ Nightwatch.js

 // Please never do that unless you have a very good reason! // Waits for 1 second browser.pause(1000);

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

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

องค์ประกอบรายการแบบกำหนดเองที่ใช้ในโครงการของเรา
องค์ประกอบรายการแบบกำหนดเองที่ใช้ในโครงการของเรา (ตัวอย่างขนาดใหญ่)

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

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

2. สาเหตุด้านสิ่งแวดล้อม

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

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

ความไม่ลงรอยกันระหว่างการพึ่งพาอาศัยกันทำให้ฉันฝันร้ายเป็นพิเศษ ฝันร้ายอย่างหนึ่งเกิดขึ้นเมื่อฉันทำงานกับ Nightwatch.js สำหรับการทดสอบ UI Nightwatch.js ใช้ WebDriver ซึ่งแน่นอนว่าขึ้นอยู่กับ Chrome เมื่อ Chrome เร่งความเร็วไปข้างหน้าด้วยการอัปเดต เกิดปัญหากับความเข้ากันได้: Chrome, WebDriver และ Nightwatch.js เองไม่ทำงานร่วมกันอีกต่อไป ซึ่งทำให้งานสร้างของเราล้มเหลวในบางครั้ง

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

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

3. สาเหตุด้านผลิตภัณฑ์

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

วิธีในการต่อสู้กับความไม่แน่นอน

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

โฟกัสที่ทีมของคุณ

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

ในช่วงหลายปีที่ฉันทำงานด้านเทคโนโลยี ฉันพบกลยุทธ์สี่ประการที่ทีมใช้เพื่อรับมือกับความไม่แน่นอน:

  1. ไม่ทำอะไรเลยและยอมรับผลการทดสอบที่ไม่สม่ำเสมอ
    แน่นอนว่ากลยุทธ์นี้ไม่ใช่วิธีแก้ปัญหาเลย การทดสอบจะไม่ให้ค่าใดๆ เพราะคุณไม่สามารถไว้วางใจได้อีกต่อไป แม้ว่าคุณจะยอมรับความเปราะบางก็ตาม ดังนั้นเราจึงสามารถข้ามสิ่งนี้ได้อย่างรวดเร็ว
  2. ลองทดสอบอีกครั้งจนกว่าจะผ่าน
    กลยุทธ์นี้เป็นเรื่องปกติในช่วงเริ่มต้นอาชีพการงาน ส่งผลให้ได้รับคำตอบตามที่กล่าวไว้ก่อนหน้านี้ มีการยอมรับด้วยการทดสอบซ้ำจนกว่าจะผ่าน กลยุทธ์นี้ไม่ต้องการการดีบัก แต่มันขี้เกียจ นอกจากการซ่อนอาการของปัญหาแล้ว ยังทำให้ชุดทดสอบของคุณช้าลงอีก ซึ่งทำให้วิธีแก้ปัญหาไม่สามารถทำงานได้ อย่างไรก็ตาม อาจมีข้อยกเว้นสำหรับกฎนี้ ซึ่งฉันจะอธิบายในภายหลัง
  3. ลบและลืมเกี่ยวกับการทดสอบ
    นี่เป็นคำอธิบายที่ชัดเจน: เพียงแค่ลบการทดสอบที่ไม่สม่ำเสมอ เพื่อไม่ให้รบกวนชุดทดสอบของคุณอีกต่อไป แน่นอนว่ามันจะช่วยคุณประหยัดเงินเพราะคุณไม่จำเป็นต้องแก้จุดบกพร่องและแก้ไขการทดสอบอีกต่อไป แต่มันมาพร้อมกับการสูญเสียพื้นที่ทดสอบเล็กน้อยและสูญเสียการแก้ไขข้อผิดพลาดที่อาจเกิดขึ้น การทดสอบมีอยู่ด้วยเหตุผล! อย่ายิงผู้ส่งสารด้วยการลบการทดสอบ
  4. กักกันและแก้ไข
    ฉันประสบความสำเร็จมากที่สุดกับกลยุทธ์นี้ ในกรณีนี้ เราจะข้ามการทดสอบชั่วคราว และให้ชุดทดสอบเตือนเราตลอดเวลาว่าข้ามการทดสอบไปแล้ว เพื่อให้แน่ใจว่าการแก้ไขจะไม่ถูกมองข้าม เราจะกำหนดเวลาตั๋วสำหรับการวิ่งครั้งต่อไป ตัวเตือนบอทยังทำงานได้ดี เมื่อแก้ไขปัญหาที่ก่อให้เกิดความไม่แน่นอนแล้ว เราจะผสานรวม (เช่น ยกเลิกการข้าม) การทดสอบอีกครั้ง ขออภัย เราจะสูญเสียความคุ้มครองชั่วคราว แต่จะกลับมาพร้อมการแก้ไข ซึ่งจะใช้เวลาไม่นาน
ข้ามการทดสอบ นำมาจากรายงานจาก CI . ของเรา
ข้ามการทดสอบ นำมาจากรายงานจาก CI ของเรา (ตัวอย่างขนาดใหญ่)

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

แยกการทดสอบออก

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

ตัวอย่างด้านล่างนำมาจากการทดสอบ UI ของแพลตฟอร์มอีคอมเมิร์ซ และเกี่ยวข้องกับการเข้าสู่ระบบของลูกค้าในหน้าร้านของร้านค้า (การทดสอบเขียนด้วย JavaScript โดยใช้เฟรมเวิร์ก Cypress)

 // File: customer-login.spec.js let customer = {}; beforeEach(() => { // Set application to clean state cy.setInitialState() .then(() => { // Create test data for the test specifically return cy.setFixture('customer'); }) }):

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

เพิ่มประสิทธิภาพโครงสร้างการทดสอบเพิ่มเติม

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

เมื่อพูดถึงการไม่ถือเอาลำดับของข้อมูล (เช่น เมื่อจัดการกับ ลำดับของรายการ ในรายการในการทดสอบ UI) เราสามารถออกแบบการทดสอบให้ทำงานโดยไม่ขึ้นกับลำดับใดๆ เพื่อนำตัวอย่างกริดที่มีข้อมูลกลับมา เราจะไม่ใช้ตัวเลือกหลอกหรือ CSS อื่นๆ ที่มีการพึ่งพาคำสั่งซื้ออย่างเข้มงวด แทนที่จะใช้ตัวเลือก nth-child(3) เราสามารถใช้ข้อความหรือสิ่งอื่น ๆ ที่ลำดับไม่สำคัญ ตัวอย่างเช่น เราสามารถใช้การยืนยันเช่น "Find me the element with this one text string in this table"

รอ! การทดสอบซ้ำในบางครั้งโอเคไหม

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

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

 test: script: rspec retry: max: 2 when: runner_system_failure

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

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

 { "retries": { // Configure retry attempts for 'cypress run` "runMode": 2, // Configure retry attempts for 'cypress open` "openMode": 2, } }

คุณสามารถเปิดใช้งานการทดสอบซ้ำในไฟล์กำหนดค่าของ Cypress cypress.json ที่นั่น คุณสามารถกำหนดความพยายามลองใหม่ในโหมดนักวิ่งทดสอบและโหมดหัวขาด

ใช้เวลารอแบบไดนามิก

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

ให้ใช้เวลารอแบบไดนามิกแทน มีหลายวิธีในการทำเช่นนั้น แต่ Cypress จัดการได้ดีเป็นพิเศษ

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

เวลารอคงที่ พบได้ในบันทึกการทดสอบของ Cypress
เวลารอคงที่ พบได้ในบันทึกการทดสอบของ Cypress (ตัวอย่างขนาดใหญ่)

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

 // Wait for changes in UI (until element is visible) cy.get(#element).should('be.visible');

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

 // File: checkout-info.spec.js // Define request to wait for cy.intercept({ url: '/widgets/customer/info', method: 'GET' }).as('checkoutAvailable'); // Imagine other test steps here... // Assert the response's status code of the request cy.wait('@checkoutAvailable').its('response.statusCode') .should('equal', 200);

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

การดีบักการทดสอบที่ไม่สม่ำเสมอ

ตอนนี้เรารู้วิธีป้องกันการทดสอบที่ไม่สม่ำเสมอด้วยการออกแบบแล้ว แต่ถ้าคุณกำลังเผชิญกับการทดสอบที่ไม่สม่ำเสมออยู่แล้วล่ะ คุณจะกำจัดมันได้อย่างไร?

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

 // Use in build Lodash to repeat the test 100 times Cypress._.times(100, (k) => { it(`typing hello ${k + 1} / 100`, () => { // Write your test steps in here }) })

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

 it('should be a Vue.JS component', () => { // Mock component by a method defined before const wrapper = createWrapper(); // Print out the component's html console.log(wrapper.html()); expect(wrapper.isVueInstance()).toBe(true); })

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

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

ต่อสู้กับฝันร้ายที่เปราะบาง!

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

พบธงแดง

การป้องกันการทดสอบที่ไม่สม่ำเสมอตั้งแต่แรกนั้นดีที่สุดแน่นอน เพื่อสรุปอย่างรวดเร็ว ต่อไปนี้คือธงสีแดงบางส่วน:

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

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

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

ฉันหวังว่าฉันจะสามารถบรรเทาความเจ็บปวดและความกังวลเกี่ยวกับความฟุ้งเฟ้อของคุณได้อย่างน้อย!

อ่านเพิ่มเติม

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

  • บทความเกี่ยวกับ “เกล็ด” Cypress.io
  • “การลองทดสอบอีกครั้งเป็นสิ่งที่ดีจริงๆ (หากแนวทางของคุณถูกต้อง)” Filip Hric, Cypress.io
  • “การทดสอบความไม่แน่นอน: วิธีการในการระบุและจัดการกับการทดสอบที่ไม่สม่ำเสมอ” Jason Palmer, Spotify R&D Engineering
  • “การทดสอบที่ไม่สม่ำเสมอของ Google และวิธีที่เราบรรเทาปัญหาเหล่านั้น” John Micco, Google Testing Blog