เมื่อวานเขียนชุดทดสอบให้ฟอร์มลงทะเบียนคอร์สตัวหนึ่ง เกือบ 100 ข้อ ผ่านหมดทุกข้อ
วันนี้ไปเปิดดูทีละข้อ แล้วเจอข้อหนึ่งเขียนไว้ว่า ตารางคนสมัครในระบบจริงต้องมีศูนย์รายการ ตอนที่เขียนมันจริง เพราะยังไม่มีใครสมัคร ตอนนี้มีคนสมัครแล้ว 6 คน ข้อนี้จึงกลายเป็นเท็จไปเรียบร้อยโดยไม่มีใครรู้
ปัญหาไม่ใช่แค่มันผิด ปัญหาคือ วิธีที่ง่ายที่สุดในการทำให้มันกลับมาผ่าน คือลบคนทั้งหกคนนั้นทิ้ง ใครก็ตามที่มาเจอตอนมันขึ้นแดง คือตอนที่ระบบทดสอบรายงานว่ามีปัญหา แล้วไม่รู้ที่มา จะเห็นทางแก้ที่เร็วที่สุดอยู่ตรงหน้าพอดี
ช่วงที่ 1ทำไม 100 ข้อ ถึงมองไม่เห็น
สิ่งที่ทำให้เจอไม่ใช่การเขียนเพิ่มเป็นข้อที่ 101 แต่คือส่งให้ตัวรีวิวอีกตัวที่ไม่ได้เขียนโค้ดนั้นอ่าน มันกลับมาพร้อม 8 เรื่องที่ทั้งชุดมองไม่เห็น
สามเรื่องแรกเป็นแบบเดียวกันหมด คือของที่คนกรอกฟอร์มทำได้ แต่คนเขียนเทสต์ไม่ได้นึกถึง ส่งข้อมูลเปล่าเข้ามาแล้วเซิร์ฟเวอร์ล้ม ส่งค่าติ๊กถูกมาเป็นตัวหนังสือแทนที่จะเป็นค่าจริงเท็จ แล้วระบบดันรับแล้วบันทึกให้ กดปฏิเสธความยินยอมแล้วชื่อกับอีเมลยังค้างอยู่ในเครื่องคนนั้นถาวร
ทุกข้อในชุดทดสอบส่งข้อมูลที่ถูกรูปแบบเสมอ เพราะคนเขียนคิดว่าคนจะส่งมาแบบนั้น ไม่มีข้อไหนลองกดปฏิเสธ เพราะไม่มีใครนึกถึง คนเขียนเทสต์กับคนเขียนโค้ดเป็นคนเดียวกัน จุดบอดจึงเป็นชุดเดียวกัน เพิ่มข้อไปอีกเท่าไรก็คือตรวจสิ่งที่คิดถึงอยู่แล้วให้ละเอียดขึ้น ไม่ใช่ตรวจสิ่งที่ไม่ได้คิด
เรื่องนี้เป็นเหตุผลเดียวกับที่งานบัญชีแยกคนทำงบออกจากคนรีวิวงบ ซึ่งเขียนไว้แล้วในตอน professional skepticism (ความสงสัยแบบมืออาชีพ) ที่ AI แทนไม่ได้ คนทำถามว่าบันทึกครบไหม คนรีวิวถามว่าตัวเลขนี้สมเหตุสมผลไหม เป็นคนละคำถาม และคนเดียวถามทั้งสองข้อพร้อมกันไม่ได้
ส่วนข้อที่สั่งให้ลบข้อมูลคนจริงนั้น มีกฎสั้น ๆ ที่ได้มาแบบไม่อยากได้ คือ อย่าเขียนข้อทดสอบที่พูดถึงสภาพรวมของระบบจริง ตารางต้องว่าง ไม่มีข้อผิดพลาดในบันทึกการรัน คิวต้องโล่ง ทั้งหมดนี้เป็นคำที่จะกลายเป็นเท็จทันทีที่มีคนใช้งานจริง ให้ยืนยันเฉพาะข้อมูลที่ตัวเทสต์เองสร้างขึ้นมาเท่านั้น
ช่วงที่ 2ผ่านทั้งที่ ไม่ได้ตรวจอะไรเลย
เคสข้างบนยังนับว่าดี เพราะอย่างน้อยเทสต์ก็ทำงานของมัน แค่ถามคำถามผิด ที่หนักกว่านั้นคือเทสต์ที่รายงานว่าผ่าน ทั้งที่ไม่มีอะไรถูกตรวจเลยสักอย่าง วันเดียวกันนั้นเราเจอสองแบบ ตอนไล่เครื่องมือของบล็อกตัวเอง
แบบแรก มีสคริปต์คอยเช็คว่าโพสต์ทุกอันถูกลงในไฟล์ดัชนีแล้วหรือยัง มันรายงานว่าครบทั้ง 86 โพสต์ ไม่ขาดสักอัน ทั้งที่โพสต์ที่เพิ่งเขียนเสร็จไม่มีชื่ออยู่ในไฟล์นั้นเลย เหตุผลคือมันไปดึงรายชื่อโพสต์มาจากอีกไฟล์หนึ่งที่ยังไม่ได้อัปเดต โพสต์ใหม่จึงไม่เคยอยู่ในรายการที่ถูกเอาไปเทียบ และสิ่งที่ไม่อยู่ในรายการเปรียบเทียบ ก็ไม่มีทางถูกรายงานว่าขาด
ตัวเลข 86 ที่พิมพ์ออกมาก็ดูน่าเชื่อพอที่จะไม่มีใครนับ
แบบที่สอง ตัวกั้นก่อนปล่อยของขึ้นเว็บเรียกเครื่องมือตรวจอีกตัวมาช่วยดู วันหนึ่งมันเริ่มพิมพ์ว่าอ่านผลจากเครื่องมือนั้นไม่ได้ แล้วสรุปต่อว่าเรียบร้อย ผ่าน ผลคือครึ่งหนึ่งของตัวกั้นเลิกทำงานไปเงียบ ๆ โดยไฟล์ 203 ไฟล์ไม่ได้ถูกตรวจเลย
จุดที่อันตรายไม่ใช่ตรงที่มันพัง แต่ตรงที่มันพังแล้วยังบอกว่าผ่าน ถ้ามันหยุดแล้วบอกว่าตรวจไม่ได้ ก็คงมีคนไปแก้ตั้งนานแล้ว
ช่วงที่ 3คำอธิบายที่เข้ากับอาการ ไม่ใช่สาเหตุ
ตอนไล่หาว่าทำไมผลถึงอ่านไม่ได้ เราเดาผิดสองรอบ
รอบแรกเห็นว่าไฟล์ของเครื่องมือตัวนั้นมีขนาดแค่ 620 ไบต์ ก็สรุปทันทีว่าไฟล์เสียหรือติดตั้งไม่ครบ ความจริงมันเป็นไฟล์เล็ก ๆ ที่ทำหน้าที่เรียกตัวจริงอีกทอด ทำงานปกติทุกอย่าง รอบสองไปค้นหาคำสั่งที่ใช้บอกให้มันพิมพ์ผลในรูปแบบที่โปรแกรมอ่านได้ หาไม่เจอ ก็สรุปว่าเครื่องมือไม่รองรับ ความจริงคือเราเปิดผิดไฟล์ คำสั่งนั้นอยู่ในอีกไฟล์ที่ไม่ได้เปิด
ทั้งสองคำอธิบายเข้ากับอาการได้สนิท และทั้งสองผิด
สิ่งที่ปิดเรื่องได้ไม่ใช่การนั่งคิดให้ออก แต่คือสั่งรันซ้ำแบบเดียวกับที่ของจริงรัน แล้วให้มันพิมพ์ตัวเลขออกมาดูตรง ๆ พอเห็นว่าผลถูกตัดที่ 8192 ไบต์พอดี เรื่องก็จบทันที เพราะเลข 8192 ไม่ใช่เลขที่จะโผล่มาโดยบังเอิญ มันคือขนาดของท่อที่ใช้ส่งผลระหว่างสองโปรแกรม เครื่องมือเขียนผลลงท่อแล้วปิดตัวเองทันทีก่อนที่ผลจะไหลออกไปหมด
ที่เล่าการเดาผิดไว้ด้วย เพราะมันเป็นส่วนหนึ่งของงานจริง ถ้าเล่าแต่คำตอบสุดท้ายมันจะดูเหมือนไล่ทีเดียวเจอ ซึ่งไม่ใช่ และบทเรียนของช่วงนี้ก็เข้ากับช่วงแรกพอดี คือคนที่เขียนของขึ้นมามักมีคำอธิบายที่ฟังขึ้นอยู่แล้วในหัว การมีคนหรือตัวเลขจากข้างนอกมาค้าน จึงสำคัญกว่าการคิดให้หนักขึ้นคนเดียว
ช่วงที่ 4ทำให้มันพัง ให้เห็นก่อน
ทางกันที่ถูกที่สุดคือ อย่าเพิ่งเชื่อว่ามันผ่าน จนกว่าจะเคยเห็นมันไม่ผ่าน
ตอนแก้สคริปต์ตัวแรก สิ่งที่ทำคือสร้างโฟลเดอร์โพสต์ปลอมขึ้นมาหนึ่งอัน แล้วสั่งรัน ถ้ามันไม่ขึ้นแดงพร้อมชื่อโฟลเดอร์นั้น ก็แปลว่ามันยังไม่ได้ตรวจอะไร มันขึ้นแดง เราจึงลบโฟลเดอร์ปลอมออกแล้วดูให้มันกลับมาเขียว ใช้เวลาไม่ถึงสองนาที และนั่นคือครั้งแรกที่รู้ว่าสคริปต์ตัวนี้ตรวจจริง
วิธีนี้ในงานแล็บเรียกว่า positive control คือใส่ตัวอย่างที่รู้ผลอยู่แล้วเข้าไปวัด ถ้าเครื่องมือหาสิ่งที่รู้ว่ามีอยู่ไม่เจอ ผลที่มันบอกว่าไม่พบก็ไม่มีความหมาย
สามข้อ ที่ทำได้วันนี้
- ทำให้มันพังก่อนหนึ่งครั้ง ใส่ของผิดเข้าไปหนึ่งอย่างแบบตั้งใจ ต้องเห็นมันขึ้นแดงและชี้จุดได้ถูก ถ้าใส่แล้วยังเขียว แปลว่ามันไม่ได้ตรวจสิ่งนั้น
- อ่านจำนวนที่มันบอกว่าตรวจไป ไม่ใช่แค่คำว่าผ่าน ผ่านโดยที่จำนวนเป็นศูนย์ หรือจำนวนไม่ขยับตอนเพิ่มของใหม่เข้าไป คือสัญญาณว่ารายการที่เอาไปเทียบมันว่าง
- อย่าอ่านแค่บรรทัดสรุป เปิดไฟล์ผลจริง ไม่พบข้อผิดพลาด กับ ไม่ได้ตรวจ พิมพ์ออกมาหน้าตาเหมือนกัน
สิ่งที่เปลี่ยนวิธีทำงานเราคือเลิกอ่านคำว่าผ่านเป็นคำตอบ แล้วเริ่มอ่านมันเป็นคำถามว่า ผ่านเพราะของมันดี หรือผ่านเพราะไม่มีอะไรถูกตรวจ ซึ่งจะรู้ก็ต่อเมื่อเคยเห็นมันไม่ผ่านมาก่อน
อ่านต่อได้ที่ mutation testing วิธีที่จงใจแก้โค้ดให้ผิดแล้วดูว่าเทสต์จับได้ไหม ซึ่งตอบคำถามถัดไปว่าเทสต์ที่ตรวจจริงแล้วนั้น แข็งพอหรือยัง
- เคสฟอร์มลงทะเบียน ชุดทดสอบเกือบ 100 ข้อ กับ 8 เรื่องที่หลุด มาจากงานของเราเอง 29 ก.ค. 2026
- เคสสคริปต์ตรวจดัชนีที่รายงานครบทั้งที่ไม่ครบ และเคสตัวกั้นที่ผลถูกตัดที่ 8192 ไบต์ เจอและแก้เอง 30 ก.ค. 2026
- positive control เป็นวิธีมาตรฐานในการออกแบบการทดลอง คือต้องมีตัวอย่างที่รู้ผลอยู่แล้วมายืนยันว่าเครื่องมือวัดตอบสนอง ก่อนที่ผลว่าไม่พบจะมีความหมาย