From Preproduction to In-Production Testing (จาก Preproduction สู่ In-Production Testing)
ในอดีต จุดโฟกัสส่วนใหญ่ ของการทดสอบอยู่ที่การทดสอบระบบของเรา ก่อน ที่เราจะไปถึง production ด้วยเทสต์ของเรา เรากำลังกำหนดชุดของโมเดลที่เราหวังว่าจะพิสูจน์ได้ว่าระบบของเราทำงานและมีพฤติกรรมตามที่เราต้องการหรือไม่ ทั้งในแง่ functional และ nonfunctional แต่ถ้าโมเดลของเราไม่สมบูรณ์แบบ เราก็จะเจอปัญหาเมื่อระบบของเราถูกใช้งานจริง บั๊กหลุดเข้าไปใน production รูปแบบความล้มเหลวใหม่ๆ ถูกค้นพบ และผู้ใช้ของเราใช้ระบบในแบบที่เราไม่มีวันคาดคิดได้
ปฏิกิริยาหนึ่งต่อเรื่องนี้มักจะเป็นการกำหนดเทสต์เพิ่มขึ้นเรื่อยๆ และปรับปรุงโมเดลของเรา เพื่อจับปัญหาได้เร็วขึ้นและลดจำนวนปัญหาที่เราเจอกับระบบ production ที่กำลังรันอยู่ อย่างไรก็ตาม ณ จุดหนึ่งเราต้องยอมรับว่าเราถึงจุด diminishing returns กับแนวทางนี้ ด้วยการทดสอบก่อนการ deploy เราไม่สามารถลดโอกาสของความล้มเหลวให้เป็นศูนย์ได้
ความซับซ้อนของระบบแบบ distributed นั้นถึงขนาดที่การจับปัญหาที่อาจเกิดขึ้นได้ทั้งหมดก่อนที่เราจะไปถึง production เองอาจเป็นไปไม่ได้เลย
โดยทั่วไปแล้ว จุดประสงค์ของเทสต์คือให้ feedback แก่เราว่าซอฟต์แวร์ของเรามีคุณภาพเพียงพอหรือไม่ โดยหลักการแล้ว เราต้องการ feedback นั้นให้เร็วที่สุดเท่าที่จะทำได้ และเราอยากจะสามารถสังเกตเห็นได้ว่ามีปัญหาอะไรกับซอฟต์แวร์ของเราก่อนที่ผู้ใช้ปลายทางจะเจอปัญหานั้น นี่คือเหตุผลที่การทดสอบจำนวนมากถูกทำก่อนที่เราจะ release ซอฟต์แวร์ของเรา
อย่างไรก็ตาม การจำกัดตัวเองให้ทดสอบแค่ใน preproduction environment เท่านั้นเป็นการตัดขาข้อได้เปรียบของเราเอง เรากำลังลดจำนวนจุดที่เราสามารถจับปัญหาได้ และเรายังกำจัดความเป็นไปได้ในการทดสอบคุณภาพของซอฟต์แวร์ของเราในสถานที่ที่สำคัญที่สุด นั่นคือที่ที่มันจะถูกใช้งานจริง
เราสามารถและควรมองหาวิธีนำการทดสอบไปใช้ใน production environment ด้วย สิ่งนี้สามารถทำได้อย่างปลอดภัย และสามารถให้ feedback ที่มีคุณภาพสูงกว่าการทดสอบแบบ preproduction ได้ และอย่างที่เราจะเห็น มันน่าจะเป็นสิ่งที่คุณทำอยู่แล้ว ไม่ว่าคุณจะรู้ตัวหรือไม่ก็ตาม
Types of In-Production Testing (ประเภทของการทดสอบใน Production)
มี รายการเทสต์ที่แตกต่างกันยาวเหยียดที่เราสามารถทำใน production ได้ ตั้งแต่แบบง่ายไปจนถึงแบบซับซ้อน เริ่มต้นด้วยการลองคิดถึงอะไรง่ายๆ อย่างการ ping check เพื่อให้แน่ใจว่า microservice นั้น live อยู่ การตรวจสอบง่ายๆ ว่า microservice instance กำลังรันอยู่หรือไม่ก็เป็นเทสต์ประเภทหนึ่ง เราแค่ไม่ได้มองว่ามันเป็นแบบนั้น เพราะมันเป็นกิจกรรมที่มักถูกจัดการโดยคน "operations" แต่โดยพื้นฐานแล้ว สิ่งง่ายๆ อย่างการพิจารณาว่า microservice นั้นทำงานอยู่หรือไม่ก็สามารถมองได้ว่าเป็นเทสต์ ซึ่งเป็นเทสต์ที่เรารันบ่อยๆ กับซอฟต์แวร์ของเรา
Smoke test เป็นอีกตัวอย่างหนึ่งของการทดสอบใน production โดยทั่วไปทำเป็นส่วนหนึ่งของกิจกรรมการ deploy smoke test ช่วยยืนยันว่าซอฟต์แวร์ที่ deploy ไปแล้วทำงานได้ถูกต้อง smoke test เหล่านี้มักจะทำกับซอฟต์แวร์จริงที่กำลังรันอยู่ ก่อนที่มันจะถูก release ให้ผู้ใช้ (จะพูดถึงเพิ่มเติมในไม่ช้า)
Canary release ซึ่งเราครอบคลุมไปแล้วใน Chapter 8 ก็เป็นกลไกที่อาจกล่าวได้ว่าเกี่ยวกับการทดสอบเช่นกัน เรา release ซอฟต์แวร์เวอร์ชันใหม่ให้กับผู้ใช้ส่วนน้อยเพื่อ "ทดสอบ" ว่ามันทำงานถูกต้องหรือไม่ ถ้ามันทำงานได้ เราก็สามารถ roll out ซอฟต์แวร์ไปสู่ผู้ใช้ส่วนใหญ่กว่าได้ อาจในรูปแบบที่เป็นอัตโนมัติเต็มรูปแบบ
อีกตัวอย่างหนึ่งของการทดสอบใน production คือการฉีดพฤติกรรมผู้ใช้ปลอมเข้าไปในระบบ เพื่อให้แน่ใจว่ามันทำงานตามที่คาดหวัง ตัวอย่างเช่น การสั่งซื้อสำหรับลูกค้าปลอม หรือการลงทะเบียนผู้ใช้ใหม่ (ปลอม) ในระบบ production จริง การทดสอบประเภทนี้บางครั้งอาจถูกต่อต้าน เพราะคนกังวลเกี่ยวกับผลกระทบที่มันอาจมีต่อระบบ production ดังนั้นถ้าคุณสร้างเทสต์แบบนี้ ต้องแน่ใจว่าคุณทำให้มันปลอดภัย
Making Testing in Production Safe (การทำให้การทดสอบใน Production ปลอดภัย)
ถ้าคุณตัดสินใจทำการทดสอบใน production (และคุณควรทำ!) สิ่งสำคัญคือเทสต์เหล่านั้นต้องไม่ก่อให้เกิดปัญหาใน production ไม่ว่าจะโดยการทำให้ระบบไม่เสถียร หรือการทำให้ข้อมูล production เสียหาย สิ่งง่ายๆ อย่างการ ping microservice instance เพื่อให้แน่ใจว่ามัน live อยู่นั้นน่าจะเป็นการดำเนินการที่ปลอดภัย ถ้าสิ่งนี้ทำให้ระบบไม่เสถียร คุณก็น่าจะมีปัญหาที่ค่อนข้างร้ายแรงที่ต้องแก้ไข เว้นแต่คุณจะทำให้ระบบ health check ของคุณกลายเป็น internal denial of service attack โดยไม่ได้ตั้งใจ
smoke test โดยทั่วไปปลอดภัย เพราะการดำเนินการที่พวกมันทำมักจะทำกับซอฟต์แวร์ก่อนที่มันจะถูก release อย่างที่เราสำรวจใน “Separating Deployment from Release” การแยกแนวคิดของการ deploy ออกจากการ release สามารถมีประโยชน์อย่างมาก เมื่อพูดถึงการทดสอบใน production เทสต์ที่ทำกับซอฟต์แวร์ที่ deploy เข้าสู่ production แล้ว แต่ยังไม่ได้ release ควรจะปลอดภัย
คนมักจะกังวลมากที่สุดเกี่ยวกับความปลอดภัยของสิ่งต่างๆ เช่น การฉีดพฤติกรรมผู้ใช้ปลอมเข้าไปในระบบ เราไม่ต้องการให้คำสั่งซื้อถูกจัดส่งจริง หรือให้มีการชำระเงินจริง นี่เป็นสิ่งที่ต้องการความระมัดระวังและความใส่ใจอย่างเหมาะสม และแม้จะมีความท้าทาย การทดสอบประเภทนี้ก็สามารถมีประโยชน์อย่างมหาศาลได้ เราจะกลับมาที่เรื่องนี้ใน “Semantic Monitoring”
Mean Time to Repair over Mean Time Between Failures? (Mean Time to Repair เหนือกว่า Mean Time Between Failures หรือไม่)
ดังนั้น ด้วยการมองเทคนิคอย่าง blue-green deployment หรือ canary releasing เราพบวิธีทดสอบที่ใกล้ชิด (หรือแม้แต่ใน) production มากขึ้น และเรายังสร้างเครื่องมือเพื่อช่วยจัดการความล้มเหลวเมื่อมันเกิดขึ้นด้วย การใช้แนวทางเหล่านี้คือการยอมรับโดยปริยายว่าเราไม่สามารถสังเกตและจับปัญหาทั้งหมดได้ก่อนที่เราจะ release ซอฟต์แวร์ของเราจริงๆ
บางครั้งการใช้ความพยายามแบบเดียวกันในการทำให้ดีขึ้นในการแก้ปัญหาเมื่อมันเกิดขึ้น อาจมีประโยชน์มากกว่าการเพิ่ม automated functional test อย่างมีนัยสำคัญ ในโลกของ web operations เรื่องนี้มักถูกเรียกว่าการแลกเปลี่ยนระหว่างการ optimize สำหรับ mean time between failures (MTBF) กับการ optimize สำหรับ mean time to repair (MTTR)
เทคนิคในการลดเวลาในการกู้คืนสามารถง่ายๆ ได้เพียงแค่การ rollback ที่รวดเร็วมาก ควบคู่ไปกับ monitoring ที่ดี (ซึ่งเราจะพูดถึงใน Chapter 10 ) ถ้าเราสามารถสังเกตเห็นปัญหาใน production ได้เร็วและ rollback ได้เร็ว เราก็จะลดผลกระทบต่อลูกค้าของเรา
สำหรับองค์กรที่แตกต่างกัน การแลกเปลี่ยนระหว่าง MTBF และ MTTR จะแตกต่างกันไป และส่วนใหญ่ขึ้นอยู่กับการเข้าใจผลกระทบที่แท้จริงของความล้มเหลวใน production environment อย่างไรก็ตาม องค์กรส่วนใหญ่ที่ผมเห็นใช้เวลาสร้าง functional test suite มักจะใช้ความพยายามเพียงเล็กน้อยหรือไม่ใช้เลยกับการปรับปรุง monitoring หรือการกู้คืนจากความล้มเหลว ดังนั้นแม้ว่าพวกเขาอาจลดจำนวนข้อบกพร่องที่เกิดขึ้นตั้งแต่แรก พวกเขาก็ไม่สามารถกำจัดมันได้ทั้งหมด และไม่พร้อมรับมือกับมัน ถ้ามันเกิดขึ้นใน production
การแลกเปลี่ยนอื่นๆ นอกเหนือจากระหว่าง MTBF และ MTTR ก็มีอยู่เช่นกัน ตัวอย่างเช่น ถ้าคุณกำลังพยายามหาคำตอบว่าจะมีใครใช้ซอฟต์แวร์ของคุณจริงๆ หรือไม่ อาจสมเหตุสมผลกว่ามากที่จะปล่อยอะไรบางอย่างออกไปตอนนี้ เพื่อพิสูจน์แนวคิดหรือ business model ก่อนที่จะสร้างซอฟต์แวร์ที่แข็งแกร่ง ใน environment ที่เป็นแบบนี้ การทดสอบอาจมากเกินความจำเป็น เพราะผลกระทบของการไม่รู้ว่าแนวคิดของคุณทำงานได้หรือไม่นั้นสูงกว่ามากเมื่อเทียบกับ การมี ข้อบกพร่องใน production ในสถานการณ์แบบนี้ การหลีกเลี่ยงการทดสอบก่อน production ไปเลยก็ค่อนข้างสมเหตุสมผล