การทดสอบเป็นการประมวลผลโปรแกรมเพื่อหาข้อผิดพลาด โดยมีขั้นตอนคร่าวๆคือ (1) Reach : เราต้องสามารถกำหนดขอบเขตของการทดสอบได้รวมถึงสามารถสร้างชุดทดสอบที่เหมาะสมได้ (2) Trigger : เราจะต้องดีบัก (debug) โปรแกรมเพื่อหาข้อผิดพลาด รวมถึงต้องสร้างชุดทดสอบที่สามารถกระตุ้นให้เกิดข้อผิดพลาด (3) Propagate : ข้อผิดพลาดที่พบต้องสามารถเผยแพร่เพื่อการเฝ้าติดตามได้ โดยเฉพาะในระบบขนาดใหญ่ที่โปรแกรมมีความซับซ้อน เพราะจุดที่พบข้อผิดพลาดอาจจะไม่ใช่จุดที่เกิดข้อผิดพลาดจริงๆ (4) Observe : เราต้องสร้างจุดสำหรับสังเกตุความผิดปรกติที่อาจจะเกิดขึ้น (5) Interpret : จากผลลัพธ์หรือข้อสังเกตุที่ได้ เราต้องดูในรายละเอียดว่าเป็นข้อผิดพลาดจริงๆ ซึ่งโดยมากคือการกลับไปเทียบกับสเปก และสิ่งที่ต้องคำนึงถึงเสมอคือโดยทั่วไปเวลาที่เราสร้างโปรแกรมขึ้นมาเรามักจะนึกถึงแต่ฟังก์ชั่นหรือการทำงานของโปรแกรม แต่อย่าลืมว่ายังมีส่วนที่เป็นคุณสมบัติซึ่งมีผลต่อการยอมรับในประสิทธิภาพของโปรแกรมอีกด้วย
ดังนั้นโปรแกรมที่ดีควรจะเป็นมิตรต่อการทดสอบ (testability) ซึ่งการมิตรต่อการทดสอบเป็น
กระบวนการในการสร้างและปรับปรุงซอฟต์แวร์เพื่อให้ตอบโจทย์ทั้ง 5 ข้อข้างต้นที่กล่าวมาเพื่อให้เราทำความเข้าใจได้ว่าอะไรคือปัญหาหรืออะไรที่ไม่ใช่ปัญหา การสร้างโปรแกรมที่เป็นมิตรต่อการทดสอบจะเป็นกระบวนการปรับปรุงโครงสร้างของโปรแกรมขนานใหญ่ถ้านำไปใช้กับซอฟต์แวร์ที่มีอยู่แล้วและไม่ได้ออกแบบมาให้เป็นมิตรต่อการทดสอบตั้งแต่แรก แต่หากเป็นการพัฒนาซอฟต์แวร์ด้วยกระบวนการสมัยใหม่ เช่น test-driven developement หรือ TDD จะเป็นการสร้างซอฟต์แวร์ที่เป็นมิตรกับการทดสอบโดยธรรมชาติเพราะในกระบวนการพัฒนาแบบ TDD ชุดทดสอบได้ถูกสร้างขึ้นมาตั้งแต่การเริ่มต้นพัฒนาซอฟต์แวร์ทำให้เราพัฒนาซอฟต์แวร์ที่สอดคล้องกับชุดทดสอบ สามารถสังเกตุข้อผิดพลาดได้ง่ายเพราะเรากำหนดตัวอย่างผลลัพธ์ที่ต้องการตั้งแต่
ก่อนที่จะเริ่มเขียนโปรแกรมเสียอีก แนวทางในการพัฒนาโปรแกรมที่เป็นมิตรต่อการทดสอบเพื่อให้ตอบโจทย์ทั้ง 5 ข้อข้างต้นประกอบด้วยคุณสมบัติต่างๆดังนี้
ความสามารถในการควบคุม (controllability) : โปรแกรมจะต้องถูกเขียนให้รองรับการสร้างชุดทดสอบที่สั้นกระชับได้ง่าย ซึ่งจะช่วยให้โปรแกรมเข้าใจได้ง่ายขึ้น และจะต้องสามารถทดสอบได้ในทุกสถานะและพารามิเตอร์ที่ต้องการ โดยเฉพาะกับการสร้างออบเจกต์ซึ่งเราต้องสามารถเปลี่ยนสถานะของออบเจกต์เพื่อการทดสอบได้ ความสามารถในการควบคุมจะทำให้เราเข้าถึงโปรแกรม (reach) และค้นหาข้อผิดพลาดได้ (trigger)
ความสามารถในการติดตามพฤติกรรมของโปรแกรม (observability) : โปรแกรมจะต้องรองรับการทดสอบแบบเปรียบเทียบผลลัพธ์ (assertion test) เช่น เราอาจจะต้องแก้ไขให้โปรแกรมคืนค่าบางอย่างที่เราสามารถเอามาใช้เปรียบเทียบกับผลลัพธ์ที่กำหนดไว้ได้ ความสามารถในการติดตามพฤติกรรมของโปรแกรมจะช่วยให้เราสามารถเผยแพร่ (propagate) และติดตาม (observe) ข้อผิดพลาดได้
การแยกโปรแกรมออกเป็นส่วนย่อยๆ (isolateability) : เมื่อเราพบข้อผิดพลาดจากการทดสอบ เราต้องสามารถระบุสาเหตุให้อย่างง่ายและรวดเร็ว ดังนั้นการทำงานของโปรแกรมควรที่จะถูกออกแบบให้แยกออกเป็นส่วนย่อยที่ไม่เกี่ยวข้องกันและสามารถทดสอบได้อย่างอิสระ เพื่อหลีกเลี่ยงปัญหา เช่น แก้โปรแกรมนิดเดียวแต่ชุดทดสอบจำนวนมากแสดงข้อผิดพลาดเพราะโปรแกรมเกี่ยวเนื่องกัน หรือต้องค้นหาจุดผิดพลาดจากโปรแกรมเป็นร้อยเป็นพันบรรทัด การแยกโปรแกรมออกเป็นส่วนย่อยๆจะทำให้เราค้นหาข้อผิดพลาดได้ง่ายขึ้น (trigger)
การทดสอบแบบอัตโนมัติ (automatability) : จะช่วยให้เราสามารถทำการทดสอบได้อย่างรวดเร็วและถูกต้องมากกว่าแบบใช้คนไปนั่งทำ (manual) ซึ่งจะช้ากว่าและมีโอกาสผิดพลาดมากกว่า แต่การทดสอบแบบอัตโนมัติก็จะมีต้นทุนในการเตรียมการมากกว่าไม่ว่าอุปกรณ์หรือเครื่องคอมพิวเตอร์ที่จะใช้งาน การเขียนโปรแกรมสำหรับทดสอบ แต่เมื่อเราพูดถึงการทดสอบเพื่อยืนยันในภาพรวมของระบบ (regression test) ซึ่งจะทำทุกครั้งที่มีการปรับปรุงโปรแกรม การทดสอบแบบอัตโนมัติจะมีประโยชน์มากเพราะสามารถทำซ้ำได้หลายครั้งในเวลาที่รวดเร็ว แต่อย่าลืมว่าการทดสอบแบบอัตโนมัติเป็นการใช้โปรแกรมในการทดสอบ ดังนั้นเป็นไปได้ว่าข้อผิดพลาดที่พบอาจจะเป็นข้อผิดพลาดของโปรแกรมที่ใช้ในการทดสอบก็ได้ จึงต้องระมัดระวังและพิจารณาให้ดี การทดสอบแบบอัตโนมัติจะช่วยให้เราเข้าถึงโปรแกรม (reach) ค้นหาข้อผิดพลาด (trigger) เผยแพร่ (propagate) และติดตาม (observe) ข้อผิดพลาดได้