พฤติกรรมการทดสอบหน่วยโดยไม่ต้องเชื่อมต่อกับรายละเอียดการใช้งาน


16

ในการพูดคุยของเขาTDD มันผิดพลาดที่ไหนเอียนคูเปอร์ผลักดันความตั้งใจดั้งเดิมของเบ็คเบ็คหลังการทดสอบหน่วยใน TDD (เพื่อทดสอบพฤติกรรม

ในกรณีของพฤติกรรมเช่นsave X to some data sourceในระบบที่มีชุดบริการและที่เก็บทั่วไปเราจะทดสอบการบันทึกข้อมูลบางอย่างในระดับการบริการผ่านที่เก็บโดยไม่ต้องเชื่อมต่อการทดสอบกับรายละเอียดการใช้งาน (เช่นการเรียกวิธีการเฉพาะ )? การหลีกเลี่ยงการมีเพศสัมพันธ์แบบนี้จริง ๆ แล้วไม่คุ้มค่าความพยายาม / ไม่ดีในบางวิธี?


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

คำถามของฉันเกี่ยวกับการหลีกเลี่ยงการทดสอบข้อต่อกับรายละเอียดการใช้งานเช่นการเรียกวิธีการเฉพาะบนที่เก็บหรือจริงๆแล้วถ้าเป็นสิ่งที่ควรทำ
Andy Hunt

คำตอบ:


8

ตัวอย่างเฉพาะของคุณคือกรณีที่คุณมักจะต้องทดสอบโดยการตรวจสอบว่ามีวิธีการบางอย่างที่เรียกว่าเพราะsaving X to data sourceหมายถึงการสื่อสารกับการพึ่งพาภายนอกดังนั้นพฤติกรรมที่คุณต้องทดสอบคือการสื่อสารที่เกิดขึ้นตามที่คาดไว้

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

ตอนนี้ให้พิจารณาเฉพาะกฎเกณฑ์ทางธุรกิจของแอปพลิเคชันแยกออกจาก UI ฐานข้อมูลและบริการภายนอกอื่น ๆ นี่คือคุณต้องมีอิสระในการเปลี่ยนแปลงทั้งโครงสร้างและพฤติกรรมของรหัส นี่คือที่ทดสอบการมีเพศสัมพันธ์และรายละเอียดการใช้งานจะบังคับให้คุณเปลี่ยนรหัสทดสอบมากกว่ารหัสการผลิตแม้ว่าจะไม่มีการเปลี่ยนแปลงในพฤติกรรมโดยรวมของแอปพลิเคชัน นี่คือที่ทดสอบStateแทนที่จะInteractionช่วยให้เราไปได้เร็วขึ้น

PS: มันไม่ใช่ความตั้งใจของฉันที่จะบอกว่าการทดสอบโดยรัฐหรือการโต้ตอบเป็นวิธีที่แท้จริงเพียงอย่างเดียวของ TDD - ฉันเชื่อว่าเป็นเรื่องของการใช้เครื่องมือที่เหมาะสมสำหรับงานที่เหมาะสม


เมื่อคุณพูดถึง "การสื่อสารกับการพึ่งพาภายนอก" คุณหมายถึงการอ้างอิงจากภายนอกว่าเป็นสิ่งที่อยู่ภายนอกหน่วยที่อยู่ภายใต้การทดสอบหรือที่ภายนอกกับระบบโดยรวมหรือไม่?
Andy Hunt

โดย "การพึ่งพาจากภายนอก" ฉันหมายถึงทุกสิ่งที่คุณถือได้ว่าเป็นปลั๊กอินในแอปพลิเคชันของคุณ โดยการประยุกต์ใช้ฉันหมายถึงกฎทางธุรกิจไม่เชื่อเรื่องรายละเอียดใด ๆ เช่นกรอบที่จะใช้สำหรับการคงอยู่หรือ UI ฉันคิดว่าลุงบ๊อบสามารถอธิบายได้ดีกว่าเช่นในการพูดคุยนี้: youtube.com/watch?v=WpkDN78P884
MichelHenrich

ฉันคิดว่านี่เป็นวิธีที่สมบูรณ์แบบเช่นคำพูดที่พูดถึงเพื่อทดสอบบนพื้นฐาน "คุณสมบัติ" หรือ "พฤติกรรม" และการทดสอบหนึ่งครั้งต่อคุณสมบัติหรือพฤติกรรม (หรือการเปลี่ยนรูปแบบของพารามิเตอร์ที่เปลี่ยนแปลง) อย่างไรก็ตามถ้าฉันมีการทดสอบ 1 รายการ "มีความสุข" เพื่อที่จะทำ TDD นั่นหมายความว่าฉันจะต้องใช้การยืนยัน (และการตรวจสอบโค้ด) สำหรับคุณลักษณะนั้นซึ่งเป็นแนวคิดที่ไม่ดี สิ่งนี้จะหลีกเลี่ยงได้อย่างไร? เขียนส่วนหนึ่งของคุณสมบัตินั้นเป็นการทดสอบและรหัสทั้งหมดที่เกี่ยวข้องแล้วเพิ่มส่วนที่เหลือของสถานที่ในภายหลัง?
จอร์แดน

ฉันอยากเห็นตัวอย่างการทดสอบจริง ๆ ในโลกที่เชื่อมโยงกับการนำไปใช้
PositiveGuy

7

การตีความของฉันในการพูดนั้นคือ:

  • ส่วนประกอบการทดสอบไม่ใช่คลาส
  • ทดสอบส่วนประกอบผ่านพอร์ตอินเตอร์เฟส

มันไม่ได้ระบุในการพูดคุย แต่ฉันคิดว่าบริบทที่สันนิษฐานสำหรับคำแนะนำนั้นเป็นอย่างไร:

  • คุณกำลังพัฒนาระบบสำหรับผู้ใช้ไม่ใช่พูดไลบรารีสาธารณูปโภคหรือกรอบงาน
  • เป้าหมายของการทดสอบคือการประสบความสำเร็จในการส่งมอบมากที่สุดเท่าที่เป็นไปได้ภายในงบประมาณที่มีการแข่งขัน
  • ส่วนประกอบเขียนด้วยภาษาเดียวที่เป็นผู้ใหญ่อาจพิมพ์แบบคงที่ภาษาอย่าง C # / Java
  • ส่วนประกอบคือลำดับ 10,000-50000 บรรทัด โครงการ Maven หรือ VS, ปลั๊กอิน OSGI ฯลฯ
  • ส่วนประกอบถูกเขียนขึ้นโดยผู้พัฒนารายเดียวหรือทีมงานที่มีการผสมผสานอย่างใกล้ชิด
  • คุณกำลังติดตามคำศัพท์และวิธีการบางอย่างเช่นสถาปัตยกรรมหกเหลี่ยม
  • พอร์ตคอมโพเนนต์เป็นที่ที่คุณออกจากภาษาท้องถิ่นและระบบชนิดด้านหลังสลับเป็น http / SQL / XML / bytes / ...
  • การรวมทุกพอร์ตเป็นอินเทอร์เฟซที่พิมพ์ใน Java / C # sense ซึ่งสามารถนำการใช้งานไปใช้เพื่อสลับเทคโนโลยี

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

การคาดการณ์จากนั้นและโยนความคิดของตัวเองออกมา

  • ทุกอินเตอร์เฟสจะเป็นอินพุทเอาท์พุทหรือผู้ทำงานร่วมกัน (เช่นฐานข้อมูล)
  • คุณทดสอบอินเทอร์เฟซการป้อนข้อมูล เรียกวิธีการยืนยันค่าที่ส่งคืน
  • คุณจำลองอินเตอร์เฟสเอาท์พุท ตรวจสอบว่าวิธีการที่คาดหวังจะถูกเรียกสำหรับกรณีทดสอบที่กำหนด
  • คุณปลอมผู้ทำงานร่วมกัน; ให้การใช้งานที่เรียบง่าย แต่ใช้งานได้

หากคุณทำอย่างถูกต้องและเรียบร้อยคุณต้องใช้เครื่องมือเยาะเย้ย มันใช้งานได้ไม่กี่ครั้งต่อระบบ

ฐานข้อมูลโดยทั่วไปแล้วจะเป็นผู้ทำงานร่วมกันดังนั้นมันจึงแกล้งทำแทนที่จะแกล้งทำ นี่จะเจ็บปวดที่จะใช้ด้วยมือ โชคดีที่สิ่งเหล่านั้นมีอยู่แล้ว

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

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

โปรดทราบว่าแม้ที่นี่การให้คุณใช้เครื่องมือการเยาะเย้ยแบบปลอดภัยเช่นmockito การเปลี่ยนชื่อวิธีการอินเทอร์เฟซไม่สามารถทำให้เกิดการทดสอบล้มเหลว หากคุณใช้ IDE ที่โหลดการทดสอบแล้วมันจะได้รับการปรับเปลี่ยนใหม่พร้อมกับการเปลี่ยนชื่อเมธอด ถ้าคุณไม่ทดสอบจะไม่รวบรวม


คุณสามารถอธิบาย / ยกตัวอย่างที่เป็นรูปธรรมของพอร์ตอินเตอร์เฟสได้หรือไม่?
PositiveGuy

ตัวอย่างของอินเทอร์เฟซผลลัพธ์คืออะไร คุณสามารถระบุรหัสได้หรือไม่? เหมือนกับอินเทอร์เฟซอินพุต
PositiveGuy

อินเทอร์เฟซ (ในความรู้สึก Java / C #) ล้อมพอร์ตซึ่งสามารถเป็นอะไรก็ได้ที่พูดคุยกับโลกภายนอก (d / b, ซ็อกเก็ต, http, .... ) อินเทอร์เฟซการส่งออกเป็นวิธีที่ไม่มีวิธีการที่มีค่าส่งคืนที่มาจากโลกภายนอกผ่านทางพอร์ตยกเว้นเฉพาะหรือเทียบเท่า
soru

อินเทอร์เฟซการป้อนข้อมูลอยู่ตรงกันข้ามผู้ทำงานร่วมกันเป็นทั้งอินพุทและเอาท์พุท
soru

1
ฉันคิดว่าคุณกำลังพูดถึงวิธีการออกแบบที่แตกต่างอย่างสิ้นเชิงและชุดคำศัพท์ที่อธิบายไว้ในวิดีโอ แต่ 90% ของเวลาที่ที่เก็บข้อมูล (เช่นฐานข้อมูล) เป็นผู้ทำงานร่วมกันไม่ใช่อินพุตหรือเอาต์พุต และอินเทอร์เฟซสำหรับมันคืออินเทอร์เฟซการทำงานร่วมกัน
soru

0

ข้อเสนอแนะของฉันคือการใช้วิธีการทดสอบตามรัฐ:

GIVEN เรามีฐานข้อมูลการทดสอบในสถานะที่รู้จัก

เมื่อ บริการถูกเรียกด้วยอาร์กิวเมนต์ X

จาก นั้นยืนยันว่า DB ได้เปลี่ยนจากสถานะดั้งเดิมเป็นสถานะที่คาดไว้โดยการเรียกวิธีการเก็บข้อมูลแบบอ่านอย่างเดียวและตรวจสอบค่าที่ส่งคืน

ด้วยวิธีการนี้คุณไม่ต้องพึ่งพาอัลกอริทึมภายในของบริการและมีอิสระในการปรับโครงสร้างการใช้งานโดยไม่ต้องเปลี่ยนการทดสอบ

ข้อต่อเดียวที่นี่คือการเรียกใช้เมธอดบริการและการเรียกใช้ที่เก็บข้อมูลเพื่ออ่านข้อมูลจากฐานข้อมูลซึ่งไม่เป็นปัญหา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.