ขึ้นอยู่กับว่าคุณกำลังทดสอบอะไร แต่สมมติว่าขอบเขตการทดสอบของคุณเป็นรหัสของคุณเท่านั้น ในกรณีนั้นคุณควรทดสอบ:
- "กรณีที่มีความสุข": ฟีดอินพุตที่ถูกต้องของแอปพลิเคชันของคุณและตรวจสอบให้แน่ใจว่ามันสร้างผลลัพธ์ที่ถูกต้อง
- กรณีล้มเหลว: ป้อนแอปพลิเคชันของคุณให้ป้อนข้อมูลไม่ถูกต้องและตรวจสอบให้แน่ใจว่าจัดการได้อย่างถูกต้อง
ในการทำเช่นนี้คุณไม่สามารถใช้องค์ประกอบของเพื่อนร่วมงานของคุณได้: ใช้การเยาะเย้ยแทนการใช้ส่วนที่เหลือของแอปพลิเคชันด้วยโมดูล "ปลอม" ที่คุณสามารถควบคุมได้จากกรอบการทดสอบ วิธีการที่คุณทำสิ่งนี้ขึ้นอยู่กับวิธีการที่โมดูลอินเตอร์เฟซ; อาจเพียงพอที่จะเรียกวิธีการของโมดูลของคุณด้วยอาร์กิวเมนต์ที่กำหนดรหัสยากและอาจซับซ้อนได้เช่นเดียวกับการเขียนกรอบงานทั้งหมดที่เชื่อมต่อส่วนต่อประสานสาธารณะของโมดูลอื่นกับสภาพแวดล้อมการทดสอบ
นั่นเป็นเพียงกรณีทดสอบหน่วย นอกจากนี้คุณยังต้องการทดสอบการรวมที่คุณทดสอบโมดูลทั้งหมดในคอนเสิร์ต อีกครั้งคุณต้องการทดสอบทั้งกรณีที่มีความสุขและความล้มเหลว
ในกรณี "ตัวอย่างพื้นฐาน" ของคุณในการทดสอบหน่วยของคุณให้เขียนคลาสจำลองที่จำลองเลเยอร์ฐานข้อมูล คลาสจำลองของคุณไม่ได้ไปที่ฐานข้อมูลจริงๆ: คุณเพียงโหลดล่วงหน้าด้วยอินพุตที่คาดหวังและเอาต์พุตคงที่ ใน pseudocode:
function test_ValidUser() {
// set up mocking and fixtures
userid = 23;
db = new MockDB();
db.fixedResult = { firstName: "John", lastName: "Doe" };
db.expectedCall = { method: 'getUser', params: { userid: userid } };
userController = new UserController(db);
expectedResult = "John Doe";
// run the actual test
actualResult = userController.displayUserAsString(userid);
// check assertions
assertEquals(expectedResult, actualResult);
db.assertExpectedCall();
}
และนี่คือวิธีที่คุณจะทดสอบฟิลด์ที่หายไปที่รายงานอย่างถูกต้อง :
function test_IncompleteUser() {
// set up mocking and fixtures
userid = 57;
db = new MockDB();
db.fixedResult = { firstName: "John", lastName: "NA" };
db.expectedCall = { method: 'getUser', params: { userid: userid } };
userController = new UserController(db);
// let's say the user controller is specified to leave "NA" fields
// blank
expectedResult = "John";
// run the actual test
actualResult = userController.displayUserAsString(userid);
// check assertions
assertEquals(expectedResult, actualResult);
db.assertExpectedCall();
}
ตอนนี้สิ่งต่าง ๆ น่าสนใจ เกิดอะไรขึ้นถ้าคลาส DB ที่แท้จริงทำงานผิดปกติ? ตัวอย่างเช่นอาจทำให้เกิดข้อยกเว้นด้วยเหตุผลที่ไม่ชัดเจน เราไม่รู้ว่ามันเป็นเช่นนั้นหรือไม่ แต่เราต้องการให้โค้ดของเราจัดการได้อย่างสง่างาม ไม่มีปัญหาเราแค่ทำให้ MockDB ของเรามีข้อยกเว้นเช่นโดยการเพิ่มวิธีดังนี้:
class MockDB {
// ... snip
function getUser(userid) {
if (this.fixedException) {
throw this.fixedException;
}
else {
return this.fixedResult;
}
}
}
จากนั้นกรณีทดสอบของเราจะเป็นดังนี้:
function test_MisbehavingUser() {
// set up mocking and fixtures
userid = 57;
db = new MockDB();
db.fixedException = new SQLException("You have an error in your SQL syntax");
db.expectedCall = { method: 'getUser', params: { userid: userid } };
userController = new UserController(db);
// run the actual test
try {
userController.displayUserAsString(userid);
}
catch (DatabaseException ex) {
// This is good: our userController has caught the raw exception
// from the database layer and wrapped it in a DatabaseException.
return TEST_PASSED;
}
catch (Exception ex) {
// This is not good: we have an exception, but it's the wrong kind.
testLog.log("Found the wrong exception: " + ex);
return TEST_FAILED;
}
// This is bad, too: either our mocking class didn't throw even when it
// should have, or our userController swallowed the exception and
// discarded it
testLog.log("Expected an exception to be thrown, but nothing happened.");
return TEST_FAILED;
}
นี่คือการทดสอบหน่วยของคุณ สำหรับการทดสอบการรวมคุณจะไม่ใช้คลาส MockDB คุณโยงทั้งคลาสจริงเข้าด้วยกันแทน คุณยังต้องติดตั้ง ตัวอย่างเช่นคุณควรเริ่มต้นฐานข้อมูลการทดสอบเป็นสถานะที่รู้จักก่อนที่จะทำการทดสอบ
ตอนนี้ตราบใดที่ความรับผิดชอบ: รหัสของคุณควรคาดหวังว่าส่วนที่เหลือของ codebase จะดำเนินการตามข้อกำหนด แต่ก็ควรเตรียมที่จะจัดการสิ่งต่าง ๆ อย่างสง่างามเมื่อส่วนที่เหลือกรูขึ้น คุณจะไม่รับผิดชอบสำหรับการทดสอบรหัสอื่นที่ไม่ใช่ของตัวเอง แต่คุณมีความรับผิดชอบในการทำให้รหัสของคุณมีความยืดหยุ่นในการทำงานไม่รหัสในส่วนอื่น ๆ และคุณยังมีความรับผิดชอบสำหรับการทดสอบความยืดหยุ่นรหัสของคุณ นั่นคือสิ่งที่การทดสอบที่สามด้านบนทำ