ฉันได้ทดสอบหน่วยการเรียนของฉันแล้วฉันจะเริ่มต้นด้วยการทดสอบการรวมได้อย่างไร


19

ฉันได้เขียนคลาสที่จัดการผู้รับในรายการ MailChimp เรียกว่า MailChimpRecipient มันใช้คลาส MCAPI ซึ่งเป็น wrapper API ของบุคคลที่สาม

http://apidocs.mailchimp.com/api/1.3/ http://apidocs.mailchimp.com/api/downloads/

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

ขั้นตอนต่อไปของฉันคือการเขียนการทดสอบการรวมด้วยการใช้ PHPUnit ที่ฉันจะสร้างการติดตั้ง MailChimpRecipient โดยใช้วัตถุ MCAPI จริงตั้งค่าให้ใช้รายการ MailChimp จริง

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

public function testAddedRecipientCanBeFound()
{
    $emailAddress = 'fred@fredsdomain.com';
    $forename = 'Fred';
    $surname = 'Smith';

    // First, delete the email address if it is already on the list
    $oldRecipient = $this->createRecipient();
    if($oldRecipient->find($emailAddress))
    {
        $oldRecipient->delete();
    }
    unset($oldRecipient);

    // Add the recipient using the test data
    $newRecipient = $this->createRecipient();
    $newRecipient->setForename($forename);
    $newRecipient->setSurname($surname);
    $newRecipient->setEmailAddress($emailAddress);
    $newRecipient->add();
    unset($newRecipient);

    // Assert that the recipient can be found using the same email address
    $this->assertTrue($this->_recipient->find($emailAddress));
}

การทดสอบ "บูรณาการ" ไม่ได้เป็นการทดสอบภายในของชั้นเรียน - เพียงตรวจสอบให้แน่ใจว่าได้รับออบเจ็กต์ MCAPI จริงมันทำงานตามที่โฆษณาไว้

ถูกต้องหรือไม่ นี่เป็นวิธีที่ดีที่สุดในการทดสอบการใช้งานหรือไม่? หลังจากทั้งหมด internals ได้รับการทดสอบด้วยการทดสอบหน่วย ฉันคิดถูกหรือไม่ว่าการทดสอบการรวมเข้าด้วยกันนั้นมีไว้เพื่อทดสอบว่าใช้งานได้จริงหรือไม่ตามพฤติกรรมของโฆษณา

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

เสียงนี้สมเหตุสมผลหรือไม่ การทดสอบหน่วยทดสอบภายในของวัตถุการทดสอบการรวมกันทำให้แน่ใจว่ามันทำงานตามที่โฆษณาหรือไม่


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

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

1
นอกจากนี้อย่าทดสอบ hardcode ในการทดสอบของตัวเอง แต่อาจทำให้สมาชิกคลาสเหล่านั้นเพื่อให้พวกเขาสามารถใช้ร่วมกันในการทดสอบ (และเปลี่ยนที่ส่วนกลาง) หรือใช้DataProvider(นั่นคือฟังก์ชั่นที่ให้อินพุตเป็นพารามิเตอร์สำหรับการทดสอบ)
hakre

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

1
+1 สำหรับคำถามที่ดี แต่ยังโหวตให้โยกย้ายไปยังโปรแกรมเมอร์ ดูเหมือนว่ามีคำถามเกี่ยวกับกลยุทธ์การทดสอบอยู่
GordonM

คำตอบ:


17

เมื่อทำการทดสอบรหัสของคุณคุณควรคำนึงถึงสามด้าน:

  • การทดสอบสถานการณ์
  • การทดสอบการทำงาน
  • การทดสอบหน่วย

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

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

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

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

ตัวอย่างเช่นสมมติว่าคุณกำลังทดสอบรถยนต์

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

แต่คุณจะทดสอบชิ้นส่วนเล็ก ๆ ของเครื่องยนต์ด้วยความเป็นไปได้ทั้งหมด (การทดสอบหน่วย)

จากนั้นคุณทดสอบเครื่องยนต์ทั้งหมด (แยกจากรถ) ซึ่งจะเป็นการทดสอบการทำงาน

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

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

ประเด็นอื่น ๆ

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

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

1
ใช่ ฉันเข้าใจว่าคุณทำการทดสอบหน่วยแล้ว วัตถุ MCAPI ติดตามผู้รับหรือไม่และคุณต้องทำการล้างข้อมูลหรือไม่ หากเป็น 'ปัญหา' ของบุคคลที่สามไม่มีอะไรที่คุณสามารถทำได้ในการทดสอบการรวม หากคุณติดตามรายการอื่นคุณควรตรวจสอบให้แน่ใจว่าคุณหลีกเลี่ยงข้อมูลทั่วโลก (และซิงเกิลตัน) เพื่อให้แน่ใจว่าการทดสอบจะไม่ส่งผลกระทบต่อกันและกัน ในโลกที่สมบูรณ์แบบทำความสะอาดสิ่งต่าง ๆ เมื่อการทดสอบเริ่มต้น / เสร็จสิ้นชี้ไปที่ข้อบกพร่องในการออกแบบ แต่ในโลกแห่งความจริงคุณไม่สามารถหลีกเลี่ยงได้เสมอ
Wouter de Kort

1
ฉันจะเพิ่มว่าการทดสอบสถานการณ์ไม่น่าจะเป็นสิ่งที่ PHPUnit เหมาะสม Yu อาจต้องการดูเครื่องมือบางอย่างที่คุณสามารถเรียกใช้ในเบราว์เซอร์เช่น Selenium หรือเครื่องมือที่สามารถจำลองเบราว์เซอร์เช่น jMeter
GordonM

ขอบคุณเพื่อน! แน่นอนว่ามีหลายสิ่งที่ต้องเรียนรู้เมื่อพูดถึงการเขียนโค้ดที่ทดสอบได้ดีไม่มีอยู่จริง ผมได้รับคำสั่งให้ตัวเองสำเนาของหนังสือเล่มนี้: amazon.co.uk/... หวังว่าสิ่งที่คุณพูดจะทำให้รู้สึกมากกว่านี้หลังจากที่ฉันได้อ่าน @Wouter ฉันแค่ลบผู้รับเพราะการทดสอบจะทำให้ที่อยู่อีเมลจะถูกเพิ่มลงในรายการ ฉันกำลังลบมันเพื่อให้รายการไม่ได้รับผลกระทบจากการทดสอบนั้น

1
@LewisBassett ฉันไม่ใช่นักพัฒนา Php แต่รูปแบบการทดสอบ xUnit ( amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 ) เป็นการอ่านที่ดีแน่นอน บทความที่misko.hevery.com/code-reviewers-guideก็น่าสนใจเช่นกัน
Wouter de Kort
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.