จำเป็นที่จะต้องทำการทดสอบฟังก์ชั่นที่เรียบง่าย (มีอยู่ในตัวเอง) หรือไม่?


36

พิจารณาสิ่งนี้:

public function polynominal($a, $b, $c, $d)
{
    return  $a * pow($x, 3) + $b * pow($x, 2) + $c * $x + $d;
}

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

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


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

3
เพราะไม่มีใครจะเขียนoverride_function('pow', '$a,$b', 'return $a * $b;');ในใจที่ถูกต้องของพวกเขา ... หรือพยายามเขียนใหม่เพื่อจัดการกับตัวเลขที่ซับซ้อน

8
ดังนั้น ... เอ่อ ... ว่า "การพิสูจน์แล้วว่ามีข้อผิดพลาดรหัสฟรี" ... มันมีข้อผิดพลาด

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

6
ฟังก์ชั่นนั้นเป็นตัวเลือกที่ยอดเยี่ยมสำหรับการเปลี่ยนรูปแบบของฮอร์เนอร์(($a*$x + $b)*$x + $c)*$x + $dซึ่งง่ายต่อการเข้าใจผิด แต่มักจะเร็วกว่ามาก เพียงเพราะคุณคิดว่ามันจะไม่เปลี่ยนไม่ได้หมายความว่ามันจะไม่
Michael Anderson

คำตอบ:


78

การทดสอบการถดถอย

มันเป็นเรื่องของการทดสอบการถดถอย

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

เมื่อถูกวอกแวกเขากลับค่าคงที่สองค่า

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

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

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

ผลข้างเคียง ...

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

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

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

การเปลี่ยนแปลงข้อกำหนด

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

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


โน้ตคนอวดรู้: ไม่มีความเสี่ยงใด ๆ ;)
jpmc26

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

หมายเหตุอวดอีกคน: ตัวเลข "เวทมนต์" บางอันใช้ได้จริงและการแทนที่ด้วยค่าคงที่เป็นความคิดที่ไม่ดี
Deduplicator

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

@ jwenting: เพิ่งเพิ่มบันทึกย่อนั้นเพราะ MainMa เขียนว่า "ไม่มีอะไรผิดปกติในการทำการเปลี่ยนแปลงนี้"
Deduplicator

45

เพราะไม่มีอะไรง่าย ๆ จนไม่มีบั๊ก

รหัสของคุณในขณะที่ดูเหมือนว่ามันจะปราศจากข้อบกพร่อง อันที่จริงแล้วมันคือการเขียนโปรแกรมแบบง่าย ๆ ของฟังก์ชันพหุนาม

ยกเว้นว่ามีข้อบกพร่อง ...

public function polynominal($a, $b, $c, $d)
{
    return  $a * pow($x, 3) + $b * pow($x, 2) + $c * $x + $d;
}

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


ภาคผนวก:

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

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

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


มีทางเลือกอื่นคือ: เปลี่ยนเป็นภาษาที่ไม่อ่อนแอ การทดสอบหน่วยมักจะมีวิธีแก้ปัญหาสำหรับการตรวจสอบเวลารวบรวมแข็งแกร่งเพียงพอและบางภาษาเป็นชนิดของดีที่นี้en.wikipedia.org/wiki/Agda_(programming_language)
Den

21

ใช่. ถ้าเราสามารถพูดด้วยความมั่นใจ 100% ด้วยความมั่นใจ: ฟังก์ชั่นนี้จะไม่ถูกแก้ไขและจะไม่ทำงานในบริบทที่อาจทำให้มันล้มเหลว - ถ้าเราสามารถพูดได้เราสามารถทดสอบและบันทึกได้ไม่กี่มิลลิวินาทีในทุก ๆ สร้าง CI

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

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


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

@Kapol: ไม่ใช่ข้อโต้แย้งการประชุมเพื่อพิจารณาว่าจะไปที่ไหนและอยู่ได้และควรใช้เกณฑ์ใดในการตัดสินใจเช่นเดียวกับที่จัดทำเอกสารเกี่ยวกับหลักเกณฑ์และใครเป็นผู้ลงนามในการตัดสินใจขั้นสุดท้าย ...
jmoreno

12

ทุกอย่างที่กล่าวในคำตอบอื่น ๆ นั้นถูกต้อง แต่ฉันจะเพิ่มอีกหนึ่งคำ

เอกสาร

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

มันสามารถทำให้การพบจุดบกพร่องง่ายขึ้นและลดความสับสน

ไม่ใช่ทุกคนที่จำชื่อพหุนามเรขาคณิตหรือพีชคณิต :) แต่การทดสอบหน่วยที่ดีในการควบคุมเวอร์ชันจะจำได้สำหรับฉัน

สำหรับตัวอย่างของเอกสารที่มีประโยชน์มีประโยชน์อย่างไรให้ดูที่การแนะนำจัสมิน: http://jasmine.github.io/edge/introduction.html ให้โหลดสักครู่แล้วเลื่อนไปที่ด้านล่าง คุณจะเห็นจัสมิน API ทั้งหมดที่บันทึกไว้เป็นเอาต์พุตทดสอบหน่วย

[อัพเดตตามข้อเสนอแนะจาก @Warbo] การทดสอบนั้นรับประกันว่าจะเป็นรุ่นล่าสุดเช่นกันเพราะหากไม่เป็นเช่นนั้นพวกเขาจะล้มเหลวซึ่งโดยทั่วไปจะทำให้เกิดความล้มเหลวในการสร้างหากใช้ CI เอกสารภายนอกมีการเปลี่ยนแปลงโดยไม่ขึ้นกับรหัสดังนั้นจึงไม่จำเป็นต้องทันสมัย


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

ฉันต้องการเพิ่มว่าบางภาษาเช่น D and Rust รวมการสร้างเอกสารของพวกเขาเข้ากับการทดสอบหน่วยดังนั้นคุณจึงสามารถมีโค้ดชิ้นเดียวกันทั้งคอมไพล์ในการทดสอบหน่วยและแทรกลงในเอกสาร HTML
Idan Arye

2

ตรวจสอบความเป็นจริง

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

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

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

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

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


4
ในกรณีนี้มีการทดสอบอยู่แล้วดังนั้นคำถามไม่ใช่ว่าจะเขียนพวกเขาหรือไม่ แต่จะมอบหมายและเรียกใช้มันกับแต่ละบิลด์หรือรีลีสหรือกำหนดเวลาใด ๆ สำหรับการทดสอบทั้งหมด
Paŭlo Ebermann

0

ใช่แล้วทำการทดสอบต่อไปและทำต่อไป

มีการทดสอบหน่วยเพื่อปกป้องคุณ (และคนอื่น ๆ ) จากตัวคุณเอง (และตัวเอง)

ทำไมการทดสอบจึงเป็นความคิดที่ดี

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

2
สิ่งนี้ดูเหมือนจะไม่เสนอสิ่งที่สำคัญกว่าคำตอบอื่น ๆ ที่ได้รับมา

1
มีปัญหาในการโพสต์ก่อนหน้านี้ แต่ในการหวนกลับมันเป็นบทสรุปที่ดี ฉันจะลบมัน
Niall

-1

เอกสารสำหรับนักพัฒนา

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

เอกสารประกอบสำหรับผู้ใช้

  • รอการบันทึกที่ไม่ดีฉันสามารถดูและยอมรับว่า {ศูนย์, ค่าลบ, ชุดที่ว่างเปล่า ฯลฯ } และค่าตอบแทนที่คาดหวังคืออะไร
  • มันยังเป็นตัวอย่างที่ดีว่าฉันควรใช้ object / function อย่างไร

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