สิ่งที่เข้าใจภายใต้“ หน่วย” ในการทดสอบหน่วย


9

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

หากคุณเห็นข้อควรพิจารณาบางประการเกี่ยวกับการใช้ TDD ด้วยวิธีการทดสอบวิธีใดวิธีหนึ่งเหล่านี้ฉันจะขอบคุณสำหรับความคิดของคุณ

คำตอบ:


11

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

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

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

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

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

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

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

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

ฉันคิดว่าศาสนากำลังเข้ามาในหัวข้อนี้ดังนั้นคุณจะเห็นความแตกแยกในสิ่งที่เรียกว่าการพัฒนา 'ที่ขับเคลื่อนด้วยพฤติกรรม' และ 'ที่ขับเคลื่อนด้วยการทดสอบ' - แนวคิดดั้งเดิมของการทดสอบหน่วยมีไว้สำหรับการพัฒนาพฤติกรรมที่ขับเคลื่อน


10

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

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

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

นี่คือปัญหาที่การพัฒนาที่ขับเคลื่อนด้วยพฤติกรรมและการพัฒนาที่ขับเคลื่อนด้วยการยอมรับโดยเฉพาะได้กำหนดไว้เพื่อแก้ไข แต่นั่นไม่ได้ลบความจำเป็นในการทดสอบหน่วย / การพัฒนาที่ขับเคลื่อนด้วยการทดสอบ มันเติมเต็มมันเท่านั้น


ฉันอยากจะบอกว่าการทดสอบพฤติกรรมนั้นบอบบาง พวกเขามักจะกลายเป็นลบเท็จในระหว่างการเปลี่ยนแปลง codebase มันเกิดขึ้นน้อยลงด้วยการทดสอบของรัฐ (แต่การทดสอบของรัฐไม่ค่อยมีการทดสอบหน่วย)
SiberianGuy

@Idsa: คำจำกัดความของคุณหายไปเล็กน้อย การทดสอบพฤติกรรมเป็นการทดสอบการรวมการทดสอบพฤติกรรมตามที่ระบุ อ่านคำถามเดิมของคุณดูเหมือนว่าเมื่อคุณพูดการทดสอบของรัฐคุณหมายถึงสิ่งเดียวกัน
pdr

โดยรัฐฉันหมายถึงการทดสอบที่ตรวจสอบรัฐผลของฟังก์ชั่นบางอย่าง; โดยพฤติกรรมฉันหมายถึงการทดสอบที่ตรวจสอบไม่ได้ผล แต่ความจริงที่ว่าบางฟังก์ชั่นถูกเรียกว่า
SiberianGuy

@Idsa: ในกรณีนี้ฉันไม่เห็นด้วยอย่างสมบูรณ์ สิ่งที่คุณเรียกการทดสอบสถานะฉันเรียกการรวม สิ่งที่คุณเรียกพฤติกรรมผมเรียกหน่วย การทดสอบบูรณาการโดยคำจำกัดความของพวกเขามีความเปราะบางมากขึ้น Google "หน่วยทดสอบรวมที่เปราะบาง" และคุณจะเห็นว่าฉันไม่ได้อยู่คนเดียว
สาธารณรัฐประชาธิปไตยประชาชนลาว

มีบันทึกของบทความเกี่ยวกับการทดสอบ แต่ความคิดเห็นใดบ้างที่คุณแชร์?
SiberianGuy

2

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

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


1
ไม่มากหน่วยเป็นเรื่องที่แยกได้เพียงเพราะเครื่องมืออัตโนมัติชอบที่จะรักษาวิธีการเช่นนี้ไม่ได้ทำให้มันหรือทำให้ดีที่สุด 'โดดเดี่ยว' คือกุญแจสำคัญที่นี่ แม้ว่าคุณจะทดสอบวิธีต่างๆคุณก็ควรทดสอบวิธีการส่วนตัวเช่นกัน
gbjbaanb

1

กฎง่ายๆของฉัน: โค้ดขนาดเล็กที่สุดซึ่งยังซับซ้อนพอที่จะมีข้อบกพร่อง

ไม่ว่าจะเป็นวิธีการหรือคลาสหรือระบบย่อยขึ้นอยู่กับรหัสเฉพาะไม่สามารถกำหนดกฎทั่วไปได้

ตัวอย่างเช่นมันไม่ได้ให้ค่าใด ๆ ในการทดสอบวิธี getter / setter อย่างง่าย ๆ ในการแยกหรือวิธีการหุ้มที่เรียกวิธีอื่นเท่านั้น แม้แต่คลาสทั้งหมดอาจจะง่ายเกินไปที่จะทดสอบถ้าคลาสเป็นเพียง wrapper หรืออะแดปเตอร์แบบบาง หากสิ่งเดียวที่จะทดสอบคือถ้าวิธีการในการเยาะเย้ยเรียกว่าแล้วรหัสภายใต้การทดสอบจะผอม

ในกรณีอื่นวิธีการเดียวอาจทำการคำนวณที่ซับซ้อนซึ่งมีค่าสำหรับการทดสอบแบบแยก

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

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