รหัสทดสอบได้ดีขึ้นไหม


103

ฉันพยายามที่จะได้รับเป็นนิสัยของการเขียนการทดสอบหน่วยเป็นประจำกับรหัสของฉัน แต่ฉันได้อ่านว่าครั้งแรกมันเป็นสิ่งสำคัญที่จะเขียนรหัสทดสอบ คำถามนี้สัมผัสกับหลักการ SOLID ของการเขียนรหัสที่สามารถทดสอบได้ แต่ฉันต้องการทราบว่าหลักการออกแบบเหล่านั้นมีประโยชน์หรือไม่ (อย่างน้อยก็ไม่เป็นอันตราย) โดยไม่ต้องวางแผนในการเขียนการทดสอบเลย เพื่อชี้แจง - ฉันเข้าใจความสำคัญของการเขียนการทดสอบ; นี่ไม่ใช่คำถามเกี่ยวกับประโยชน์ของพวกเขา

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

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


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


24
มีคุณสมบัติพิเศษของฟังก์ชันที่คุณต้องผ่านในเวลาที่เรียกว่าidempotency ฟังก์ชั่นดังกล่าวจะให้ผลลัพธ์เดียวกันทุกครั้งที่มีการเรียกใช้ด้วยค่าอาร์กิวเมนต์ที่กำหนดซึ่งไม่เพียง แต่จะทำให้สามารถทดสอบได้มากขึ้น แต่สามารถเรียบเรียงได้ง่ายขึ้นและให้เหตุผลได้ง่ายขึ้น
Robert Harvey

4
คุณสามารถกำหนด "รหัสที่ดีกว่า" ได้หรือไม่? คุณหมายถึง "maintainable" หรือไม่ "ง่ายต่อการใช้งานโดยไม่ใช้ IOC-Container-Magic"
k3b

7
ฉันเดาว่าคุณไม่เคยมีการทดสอบล้มเหลวเพราะมันใช้เวลาของระบบจริงและจากนั้นเขตเวลาออฟเซ็ตก็เปลี่ยนไป
Andy

5
ดีกว่ารหัสที่ไม่สามารถทดสอบได้
Tulains Córdova

14
@RobertHarvey ฉันจะไม่เรียก idempotency นั้นฉันจะบอกว่ามันเป็นความโปร่งใสอ้างอิง : ถ้าfunc(X)ผลตอบแทน"Morning"จากนั้นแทนที่ทุกสิ่งที่เกิดขึ้นfunc(X)ด้วย"Morning"จะไม่เปลี่ยนโปรแกรม (เช่นการโทรfuncไม่ได้ทำอะไรนอกจากคืนค่า) Idempotency บอกเป็นนัยว่าfunc(func(X)) == X(ซึ่งไม่ถูกต้องประเภท) หรือที่func(X); func(X);มีผลข้างเคียงเช่นเดียวกับfunc(X)(แต่ไม่มีผลข้างเคียงที่นี่)
Warbo

คำตอบ:


116

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

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

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


3
ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
วิศวกรโลก

2
ฉันคิดว่ามันน่าสังเกตว่าฉันรู้ภาษาอย่างน้อยหนึ่งภาษาที่อนุญาตให้คุณทำสิ่งที่ย่อหน้าสุดท้ายของคุณอธิบาย: Python กับ Mock เนื่องจากการนำเข้าโมดูลทำงานอย่างไรสิ่งอื่นนอกเหนือจากคำหลักสามารถถูกแทนที่ด้วยการเยาะเย้ยแม้แต่วิธีการมาตรฐาน API / ชั้นเรียน / ฯลฯ ดังนั้นจึงเป็นไปได้ แต่อาจต้องใช้ภาษาในการรองรับความยืดหยุ่นชนิดนั้น
jpmc26

5
ฉันคิดว่ามีความแตกต่างระหว่าง "รหัสที่ทดสอบได้" และ "รหัส [บิด] เพื่อให้เหมาะกับกรอบการทดสอบ" ฉันไม่แน่ใจว่าฉันจะไปที่ใดกับความคิดเห็นนี้นอกจากจะบอกว่าฉันยอมรับว่ารหัส "บิด" ไม่ดีและรหัส "ทดสอบได้" ที่มีอินเตอร์เฟสที่ดีนั้นดี
Bryan Oakley

2
ฉันแสดงความคิดเห็นบางส่วนในความคิดเห็นของบทความ (เนื่องจากความคิดเห็นเพิ่มเติมไม่ได้รับอนุญาตที่นี่) ลองดูสิ! ต้องมีความชัดเจน: ผมเป็นผู้เขียนบทความดังกล่าว :)
Sergey Kolodiy

ฉันเห็นด้วยกับ @BryanOakley "รหัสที่ทดสอบได้" แนะนำให้แยกข้อกังวลของคุณ: เป็นไปได้ที่จะทดสอบด้าน (โมดูล) โดยไม่มีการรบกวนจากด้านอื่น ๆ ฉันจะบอกว่าสิ่งนี้แตกต่างจาก "การปรับโครงการสนับสนุนข้อกำหนดการทดสอบเฉพาะของคุณ" สิ่งนี้คล้ายกับรูปแบบการออกแบบ: พวกเขาไม่ควรถูกบังคับ รหัสที่เหมาะสมใช้รูปแบบการออกแบบจะถือว่าเป็นรหัสที่แข็งแกร่ง เช่นเดียวกับหลักการทดสอบ หากการทำให้โค้ดของคุณ "ทดสอบได้" ส่งผลให้เกิดการบิดรหัสโครงการของคุณมากเกินไปคุณกำลังทำอะไรผิดพลาด
Vince Emigh

68

การเขียนโค้ดที่ทดสอบได้ยังคงเป็นแนวปฏิบัติที่ดีแม้จะไม่มีการทดสอบหรือไม่?

สิ่งแรกสิ่งแรกคือการขาดการทดสอบเป็นปัญหาใหญ่กว่ารหัสของคุณที่สามารถทดสอบได้หรือไม่ การไม่มีการทดสอบหน่วยหมายความว่าคุณไม่ได้ใช้รหัส / คุณสมบัติ

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

สำหรับฉันมีชุดของลำดับความสำคัญในการเขียนโค้ดอยู่เสมอ:

  1. ทำให้มันใช้งานได้ - หากโค้ดไม่ได้ทำในสิ่งที่จำเป็นต้องทำมันก็ไม่มีค่า
  2. ทำให้สามารถบำรุงรักษาได้ - หากรหัสไม่สามารถบำรุงรักษาได้รหัสจะหยุดทำงานอย่างรวดเร็ว
  3. ทำให้มีความยืดหยุ่น - หากรหัสไม่ยืดหยุ่นมันจะหยุดทำงานเมื่อธุรกิจเข้ามาอย่างหลีกเลี่ยงไม่ได้และถามว่ารหัสสามารถทำ XYZ ได้หรือไม่
  4. ทำให้รวดเร็ว - เหนือระดับที่ยอมรับได้ฐานประสิทธิภาพเป็นเพียงน้ำเกรวี่

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


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

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

4
@ WannabeCoder แน่นอนมันก็คุ้มค่าที่จะเพิ่มความยืดหยุ่นเมื่อมันช่วยคุณประหยัดเวลาในที่สุด นั่นเป็นเหตุผลที่เราไม่ได้เขียนทุก ๆ วิธีในส่วนต่อประสาน - ส่วนใหญ่เป็นการง่ายกว่าที่จะเขียนรหัสใหม่แทนที่จะรวมความยืดหยุ่นมากเกินไปจากการโจมตี YAGNI ยังคงเป็นหลักการที่ทรงพลังอย่างยิ่งเพียงให้แน่ใจว่าสิ่งที่ "คุณไม่ต้องการ" ก็คือการเพิ่มมันย้อนหลังจะไม่ทำให้คุณทำงานโดยเฉลี่ยมากกว่าการใช้งานก่อนเวลา มันเป็นรหัสที่ไม่ได้ติดตาม YAGNI ที่มีปัญหามากที่สุดกับความยืดหยุ่นในประสบการณ์ของฉัน
Luaan

3
"ไม่มีการทดสอบหน่วยหมายความว่าคุณไม่ได้ใช้รหัส / คุณสมบัติ" - ไม่จริง "คำจำกัดความของการกระทำ" เป็นสิ่งที่ทีมตัดสินใจ อาจครอบคลุมหรือไม่ครอบคลุมขอบเขตการทดสอบ แต่ไม่มีที่ใดที่มีข้อกำหนดที่เข้มงวดซึ่งระบุว่าฟีเจอร์ไม่สามารถ "ทำได้" หากไม่มีการทดสอบ ทีมอาจเลือกที่จะต้องทำการทดสอบหรือไม่ก็ได้
aroth

3
@Telastyn ในการพัฒนากว่า 10 ปีฉันไม่เคยมีทีมงานที่ได้รับคำสั่งกรอบการทดสอบหน่วยและเพียงสองคนที่มีแม้แต่คนเดียว (ทั้งคู่มีความครอบคลุมที่ไม่ดี) ที่แห่งหนึ่งต้องการเอกสารคำว่าจะทดสอบคุณสมบัติที่คุณเขียน แค่นั้นแหละ. บางทีฉันอาจโชคร้าย ฉันไม่ได้ทำการทดสอบต่อต้านหน่วย (จริงจังฉันปรับเปลี่ยนไซต์ SQA.SE ฉันเป็นแบบทดสอบระดับมืออาชีพมาก!) แต่ฉันไม่พบว่าพวกเขาแพร่หลายมากเท่าที่งบของคุณอ้าง
corsiKa

50

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

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

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

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


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

10
Nobody cares about the tests themselves-- ฉันทำ. ฉันพบว่าการทดสอบเป็นเอกสารที่ดีกว่าว่าโค้ดทำอะไรได้มากกว่าความคิดเห็นหรือไฟล์ readme
jcollum

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

12

ณ จุดหนึ่งค่าจะต้องเริ่มต้นและทำไมไม่ใกล้เคียงกับการบริโภค?

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

การสร้างรหัสที่ทดสอบได้มีผลบังคับใช้หมายถึงการสร้างรหัสที่สามารถ (ตั้งแต่เริ่มต้น) ในสถานการณ์ที่แตกต่างกันสองสถานการณ์ (การผลิตและการทดสอบ)

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

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

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


10

มันอาจดูงี่เง่าที่จะพูดแบบนี้ แต่ถ้าคุณต้องการที่จะทดสอบโค้ดของคุณใช่แล้วการเขียนโค้ดที่ทดสอบได้จะดีกว่า คุณถาม:

ณ จุดหนึ่งค่าจะต้องเริ่มต้นและทำไมไม่ใกล้เคียงกับการบริโภค?

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

นอกจากความยืดหยุ่นแล้ววิธีการเล็ก ๆ ที่มีปัญหานั้นมีความรับผิดชอบสองประการ: (1) ทำให้เวลาของระบบและจากนั้น (2) คืนค่าบางอย่างขึ้นอยู่กับมัน

public static string GetTimeOfDay()
{
    DateTime time = DateTime.Now;
    if (time.Hour >= 0 && time.Hour < 6)
    {
        return "Night";
    }
    if (time.Hour >= 6 && time.Hour < 12)
    {
        return "Morning";
    }
    if (time.Hour >= 12 && time.Hour < 18)
    {
        return "Afternoon";
    }
    return "Evening";
}

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


1
ดังนั้นคุณต้องทดสอบตอนเช้าเพื่อตรวจสอบว่าคุณได้รับผลของ "คืน" เมื่อคุณต้องการ นั่นเป็นเรื่องยาก ทีนี้สมมติว่าคุณต้องการตรวจสอบว่าการจัดการวันที่ถูกต้องในวันที่ 29 กุมภาพันธ์ 2016 ... และนักเขียนโปรแกรม iOS บางคน (และคนอื่น ๆ อาจจะ) ถูกรบกวนจากความผิดพลาดของผู้เริ่มต้น ทดสอบว่า และจากประสบการณ์ฉันจะตรวจสอบการจัดการในวันที่ 2 กุมภาพันธ์ 2020
gnasher729

1
@ gnasher729 ตรงประเด็นของฉัน "การทำให้รหัสนี้สามารถทดสอบได้" เป็นการเปลี่ยนแปลงง่าย ๆ ที่สามารถแก้ปัญหาได้มาก (การทดสอบ) หากคุณไม่ต้องการทำการทดสอบอัตโนมัติฉันก็เดาได้ว่ารหัสนั้นสามารถผ่านได้เหมือนเดิม แต่จะดีกว่าเมื่อ "ทดสอบได้"
Eric King

9

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

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

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

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


+1 - คุณต้องปรับปรุงการออกแบบและสถาปัตยกรรมเพื่อให้การทดสอบหน่วยการเขียนง่ายขึ้น
BЈовић

3
+ - คือสถาปัตยกรรมของรหัสของคุณที่มีความสำคัญ การทดสอบที่ง่ายขึ้นเป็นเพียงผลข้างเคียงที่มีความสุข
gbjbaanb

8

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

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

ใช่. เป็นวิธีปฏิบัติที่ดีในการเขียนโค้ดที่สามารถทดสอบได้แม้จะไม่ได้ทำการทดสอบก็ตาม


ไม่เห็นด้วยเกี่ยวกับเรื่องนี้ว่าเป็น DRY - การตัด GetCurrentTime ในเมธอด MyGetCurrentTime ทำซ้ำการเรียกใช้ OS ซ้ำโดยไม่มีประโยชน์ยกเว้นการช่วยในการทดสอบเครื่องมือ นั่นเป็นเพียงตัวอย่างที่ง่ายที่สุดพวกมันแย่ลงในความเป็นจริง
gbjbaanb

1
"การทำซ้ำการเรียกใช้ OS โดยไม่มีผลประโยชน์" - จนกว่าคุณจะจบลงด้วยการทำงานบนเซิร์ฟเวอร์ที่มีหนึ่งนาฬิกาพูดกับเซิร์ฟเวอร์ aws ในเขตเวลาที่แตกต่างกันและที่ทำลายรหัสของคุณและคุณต้องผ่านรหัสทั้งหมดของคุณและ อัปเดตเพื่อใช้ MyGetCurrentTime ซึ่งจะส่งคืน UTC แทน ; นาฬิกาเบ้, การปรับเวลาตามฤดูกาลและมีเหตุผลอื่น ๆ ที่ทำให้คุณไม่น่าไว้วางใจที่จะเชื่อใจในการโทรของระบบปฏิบัติการหรืออย่างน้อยก็มีจุดเดียวที่คุณสามารถทิ้งไว้ในที่อื่นได้
Andrew Hill

8

การเขียนรหัสที่สามารถทดสอบได้มีความสำคัญหากคุณต้องการพิสูจน์ว่ารหัสของคุณใช้งานได้จริง

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

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

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

แต่เพื่อให้ชัดเจนรหัสที่ฉลาดหรือนานและ / หรือพึ่งพาซึ่งกันและกันซึ่งไม่สามารถเข้าใจได้ง่ายโดยมนุษย์คนอื่นไม่ใช่รหัสที่ดี และยังบังเอิญรหัสไม่สามารถทดสอบได้ง่าย

ดังนั้นใกล้ถึงบทสรุปของฉันรหัสทดสอบได้ดีกว่ารหัสหรือไม่

ฉันไม่รู้อาจจะไม่ คนที่นี่มีบางจุดที่ถูกต้อง

แต่ฉันเชื่อว่ารหัสที่ดีกว่ามีแนวโน้มที่จะเป็นรหัสที่ทดสอบได้เช่นกัน

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

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


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

1
เผง พิจารณาสิ่งประดิษฐ์ หากเป็นรหัสที่ไม่สามารถทดสอบได้จะไม่ถูกทดสอบ หากยังไม่ได้ทดสอบคุณจะรู้ได้อย่างไรว่ามันใช้งานได้หรือไม่นอกเหนือจากสถานการณ์จริง
pjc50

1
การทดสอบทั้งหมดพิสูจน์ได้ว่ารหัสผ่านการทดสอบ มิฉะนั้นรหัสที่ผ่านการทดสอบแล้วจะไม่มีข้อผิดพลาดและเรารู้ว่าไม่เป็นเช่นนั้น
wobbily_col

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

1
... แต่การทำให้ระบบราชการหมดไปจากการทดสอบอาจเป็นของเสียทั้งหมดและไม่สร้างข้อมูลที่เป็นประโยชน์หรือผลลัพธ์ที่น่าเชื่อถือ โดยไม่คำนึงถึง; ฉันแน่ใจว่ามีใครบางคนทดสอบSSL Heartbleed bug ใช่ไหม? หรือข้ามไปของ Apple ล้มเหลวบั๊ก?
Craig

5

ถึงฉันมันดูเหมือนว่า overkill จะผ่านในเวลาเป็นข้อโต้แย้ง

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

def time_of_day():
    return datetime.datetime.utcnow().strftime('%H:%M:%S')

ตอนนี้สมมติว่าคุณต้องการทดสอบสิ่งที่เกิดขึ้นในระหว่างการกระโดดครั้งที่สอง อย่างที่คุณพูดเพื่อทดสอบวิธี overkill นี้คุณจะต้องเปลี่ยนรหัส (การผลิต):

def time_of_day(now=None):
    now = now if now is not None else datetime.datetime.utcnow()
    return now.strftime('%H:%M:%S')

ถ้า Python รองรับการเผ่นวินาทีรหัสทดสอบจะเป็นดังนี้:

def test_handle_leap_second(self):
    actual = time_of_day(
        now=datetime.datetime(year=2015, month=6, day=30, hour=23, minute=59, second=60)
    expected = '23:59:60'
    self.assertEquals(actual, expected)

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

def time_of_day():
    return datetime.datetime.utcnow().strftime('%H:%M:%S')

รหัสทดสอบ:

@unittest.patch('datetime.datetime.utcnow')
def test_handle_leap_second(self, utcnow_mock):
    utcnow_mock.return_value = datetime.datetime(
        year=2015, month=6, day=30, hour=23, minute=59, second=60)
    actual = time_of_day()
    expected = '23:59:60'
    self.assertEquals(actual, expected)

สิ่งนี้ให้ประโยชน์หลายประการ:

  • คุณกำลังทดสอบtime_of_day อิสระของการอ้างอิง
  • คุณกำลังทดสอบเส้นทางรหัสเดียวกันกับรหัสการผลิต
  • รหัสการผลิตง่ายที่สุดเท่าที่จะทำได้

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


FYI: อาร์กิวเมนต์เริ่มต้นของคุณผิด มันจะถูกกำหนดเพียงครั้งเดียวดังนั้นฟังก์ชั่นของคุณจะกลับเวลาที่ประเมินครั้งแรก
ahruss

4

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

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

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


4

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

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

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

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

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

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

โดยสรุปรหัสที่ทดสอบได้ไม่จำเป็นต้องเป็นรหัส "ดี" แต่รหัส "ดี" มักจะสามารถทดสอบได้


1

หากคุณกำลังจะมีSOLIDหลักการคุณจะได้ในด้านที่ดีโดยเฉพาะอย่างยิ่งถ้าขยายนี้กับKISS , แห้งและYAGNI

จุดหนึ่งที่ขาดหายไปสำหรับฉันคือจุดของความซับซ้อนของวิธีการ มันเป็นวิธี getter / setter อย่างง่ายหรือไม่? จากนั้นเพียงแค่เขียนแบบทดสอบเพื่อตอบสนองกรอบการทดสอบของคุณจะเสียเวลา

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

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

เพียงแค่ฉันสองเซ็นต์

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