เหตุใดการทดสอบภาษาจึงไม่รองรับคุณสมบัติที่ระดับไวยากรณ์


37

คุณสามารถค้นหารายการบล็อกบทความและเว็บไซต์ที่ไม่สิ้นสุดซึ่งส่งเสริมประโยชน์ของการทดสอบหน่วยซอร์สโค้ดของคุณ เกือบจะรับประกันได้ว่านักพัฒนาที่เขียนโปรแกรมคอมไพเลอร์สำหรับ Java, C ++, C # และภาษาที่พิมพ์อื่น ๆ ใช้การทดสอบหน่วยเพื่อตรวจสอบงานของพวกเขา

ดังนั้นทำไมแม้จะมีความนิยมของมันคือการทดสอบขาดจากไวยากรณ์ของภาษาเหล่านี้หรือไม่

Microsoft แนะนำLINQให้กับC #ดังนั้นทำไมพวกเขาจึงไม่สามารถเพิ่มการทดสอบได้อีกด้วย

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

เป็นตัวอย่าง: เรารู้ว่าคุณสามารถเขียนforลูปโดยไม่มีไวยากรณ์ของforคำสั่ง คุณสามารถใช้whileหรือif/ gotoงบ มีคนตัดสินใจว่าforข้อความนั้นมีประสิทธิภาพมากกว่าและนำมาใช้เป็นภาษา

ทำไมการทดสอบไม่ได้ทำตามวิวัฒนาการของภาษาโปรแกรมเดียวกัน?


24
เป็นการดีกว่าหรือที่จะทำให้การกำหนดภาษามีความซับซ้อนมากขึ้นโดยการเพิ่มไวยากรณ์เมื่อเทียบกับการออกแบบภาษาที่มีกฎง่าย ๆ ที่สามารถขยายได้อย่างง่ายดายในลักษณะทั่วไป
KChaloux

6
คุณหมายถึง "ที่ระดับไวยากรณ์" หมายความว่าอย่างไร คุณมีรายละเอียด / แนวคิดเกี่ยวกับวิธีการนำไปใช้หรือไม่?
SJuan76

21
คุณสามารถให้ตัวอย่างรหัสเทียมของการทดสอบเป็นคุณลักษณะที่รองรับไวยากรณ์ได้หรือไม่ ฉันอยากรู้ว่าคุณคิดว่ามันจะเป็นอย่างไร
FrustratedWithFormsDesigner

12
@FrustratedWithFormsDesigner ดูตัวอย่างภาษา D
Doval

4
อีกภาษาหนึ่งที่มีคุณสมบัติการทดสอบหน่วยในตัวคือ Rust
Sebastian Redl

คำตอบ:


36

เช่นเดียวกับหลาย ๆ สิ่งการทดสอบหน่วยได้รับการสนับสนุนที่ดีที่สุดในระดับห้องสมุดไม่ใช่ระดับภาษา โดยเฉพาะอย่างยิ่ง, C # มีหลายหน่วยทดสอบไลบรารีที่มีอยู่เช่นเดียวกับสิ่งที่เป็นชนพื้นเมืองที่ .NET Framework Microsoft.VisualStudio.TestTools.UnitTestingเช่น

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

ตัวอย่าง

  • Nunit - วัตถุประสงค์ทั่วไปกรอบการทดสอบหน่วยที่ออกแบบมาโดยเฉพาะซึ่งใช้ประโยชน์จากคุณลักษณะทางภาษาของ C # อย่างเต็มที่

  • Moq - กรอบการเยาะเย้ยที่ใช้ประโยชน์อย่างเต็มที่จากการแสดงออกแลมบ์ดาและทรีนิพจน์โดยไม่มีคำอุปมาบันทึก / การเล่น

มีตัวเลือกอื่น ๆ อีกมากมาย ไลบรารี่เช่น Microsoft Fakes สามารถสร้าง mocks "shims ... " ที่ไม่ต้องการให้คุณเขียนคลาสของคุณโดยใช้อินเตอร์เฟสหรือเมธอดเสมือน

Linq ไม่ใช่คุณสมบัติภาษา (แม้จะเป็นชื่อ)

Linq เป็นคุณสมบัติห้องสมุด เรามีคุณสมบัติใหม่มากมายในภาษา C # ฟรีเช่นการแสดงออกแลมบ์ดาและวิธีการขยาย แต่การใช้งานจริงของ Linq อยู่ใน. NET Framework

มีน้ำตาลประโยคที่เพิ่มเข้าไปใน C # เพื่อให้งบ linq สะอาดขึ้น แต่น้ำตาลนั้นไม่จำเป็นต้องใช้ linq


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

@WyattBarnett: ใช่และเหมือนกันคือจริงสำหรับการทดสอบหน่วยง่าย - เช่นภาพสะท้อนและคุณลักษณะ
Doc Brown

8
LINQ ต้องการแลมบ์ดาและต้นไม้แสดงออก ยาสามัญอยู่แล้วใน C # (และ. Net โดยทั่วไปพวกเขากำลังอยู่ใน CLR) และการเปลี่ยนแปลงไม่มีอะไรเกี่ยวข้องกับ LINQ; คุณสามารถทำ LINQ ได้โดยไม่ต้องไดนามิก
Arthur van Leeuwen

Perl ของ DBIx :: Class เป็นตัวอย่างของฟังก์ชันการทำงานแบบ LINQ ที่ใช้งานมานานกว่า 10 ปีหลังจากคุณสมบัติทั้งหมดที่จำเป็นในการใช้งานนั้นเป็นภาษา
slebetman

2
@ Carson63000 ฉันคิดว่าคุณหมายถึงประเภทที่ไม่ระบุชื่อในการรวมกันกับvarคำหลัก :)
M.Mimpen

21

มีเหตุผลมากมาย Eric Lippert ได้ระบุหลายครั้งว่าเหตุผลที่feature Xไม่อยู่ใน C # นั้นเป็นเพราะมันไม่ได้อยู่ในงบประมาณของพวกเขา นักออกแบบภาษาไม่มีเวลาและเงินในการใช้งานและคุณลักษณะใหม่แต่ละอย่างมีค่าใช้จ่ายในการบำรุงรักษาที่เกี่ยวข้อง การทำให้ภาษามีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้นั้นไม่ใช่เรื่องง่ายสำหรับนักออกแบบภาษา - มันก็ง่ายขึ้นสำหรับทุกคนที่เขียนการใช้งานและเครื่องมือทางเลือก (เช่น IDEs) นอกจากนี้เมื่อบางสิ่งถูกนำมาใช้ในแง่ของภาษา พกพาได้ฟรี หากการทดสอบหน่วยกำลังใช้งานเป็นห้องสมุดคุณจะต้องเขียนเพียงครั้งเดียวและมันจะทำงานในการปรับใช้ภาษาที่สอดคล้องกัน

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

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

อย่างไรก็ตามฉันคิดว่าไลบรารีการทดสอบหน่วยที่ยอดเยี่ยมนั้นทำอะไรได้มากกว่าเพียงแค่หาวิธีและรันมัน ยกตัวอย่างQuickCheckของ Haskell ซึ่งช่วยให้คุณทดสอบสิ่งต่างๆเช่น "สำหรับทุก x และ y f (x, y) == f (y, x)" QuickCheck อธิบายได้ดีกว่าในฐานะเครื่องกำเนิดการทดสอบหน่วยและช่วยให้คุณสามารถทดสอบสิ่งต่าง ๆ ในระดับที่สูงกว่า "สำหรับอินพุตนี้ฉันคาดหวังเอาต์พุตนี้" QuickCheck และ Linq ไม่ได้มีความแตกต่างกัน - ทั้งสองเป็นภาษาเฉพาะโดเมน ดังนั้นแทนที่จะสนับสนุนการทดสอบหน่วยกับภาษาทำไมไม่เพิ่มคุณสมบัติที่จำเป็นในการทำให้ DSL ใช้งานได้จริง คุณจะจบลงด้วยการทดสอบหน่วยไม่เพียง แต่เป็นภาษาที่ดีกว่า


3
เพื่ออยู่ในโลกของ. Net มี FsCheck ซึ่งเป็นพอร์ตของ QuickCheck ถึง F # โดยมีผู้ช่วยบางคนใช้งานจาก C #
Arthur van Leeuwen

อยู่ในโลก. NET คำถามนี้ไม่เกี่ยวข้องกับ. NET
Miles Rout

@MilesRout C # เป็นส่วนหนึ่งของ. NET คำถามและคำตอบพูดคุยเกี่ยวกับ C # บ่อยครั้งและคำถามยังพูดถึง LINQ ด้วย
Zachary Dow

คำถามไม่ได้ติดแท็ก. NET หรือ C #
เส้นทาง Miles

@MilesRout อาจเป็นเรื่องจริง แต่คุณไม่สามารถพูดได้ว่ามันไม่มีส่วนเกี่ยวข้องกับมันเพียงเพราะไม่มีแท็ก :)
Zachary Dow

13

เนื่องจากการทดสอบและการพัฒนาโดยเฉพาะอย่างยิ่งการทดสอบเป็นปรากฏการณ์ที่ต่อต้านได้ง่าย

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

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

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


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

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

@ Robert: สิ่งเดียวที่ฉันเชื่อว่าเขาพูดเกินจริงคือ "การทดสอบทางศาสนากำลังกลายเป็นกระแสหลักมากขึ้น" หากมีการกำหนดอย่างช้าๆในแง่ของกรอบเวลาทางภูมิศาสตร์เขาอาจจะไม่ไกล ..... :)
mattnz

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

1
ขออภัยอีกหนึ่งความคิดอีกครั้ง: ความคิดเห็นของ Robert Harvey ตอนนี้ระบบการพิมพ์คือการตรวจสอบที่ดี แต่จริง ๆ แล้วมีข้อ จำกัด ในการกำหนดประเภทที่น่าแปลกใจ - พวกเขากล่าวถึงอินเตอร์เฟส แต่ไม่ได้ จำกัด พฤติกรรมที่ถูกต้อง (เช่น 1 + 1 == 3 จะรวบรวม แต่อาจหรืออาจไม่จริงขึ้นอยู่กับการใช้ +) ฉันสงสัยว่าแนวโน้มต่อไปจะเห็นระบบประเภทที่แสดงออกมากขึ้นซึ่งรวมสิ่งที่เราพิจารณาว่าเป็นการทดสอบหน่วยตอนนี้
Rob

6

หลายภาษารองรับการทดสอบ การยืนยันของ C เป็นการทดสอบที่โปรแกรมสามารถล้มเหลวได้ นั่นคือที่ภาษาส่วนใหญ่หยุด แต่ไอเฟลและ Ada 2012 เร็ว ๆ นี้มี preinvariants (สิ่งที่ขัดแย้งกับฟังก์ชั่นจะต้องผ่าน) และ postinvariants (สิ่งที่เอาท์พุทของฟังก์ชั่นจะต้องผ่าน) กับ Ada เสนอความสามารถในการอ้างอิงอาร์กิวเมนต์เริ่มต้นใน postinvariant Ada 2012 ยังมีประเภทค่าคงที่ดังนั้นเมื่อใดก็ตามที่มีการเรียกใช้เมธอดบนคลาส Ada ค่าคงที่ประเภทจะถูกตรวจสอบก่อนส่งคืน

นั่นไม่ใช่ประเภทของการทดสอบเต็มรูปแบบกรอบการทดสอบที่ดีสามารถให้คุณได้ แต่เป็นประเภทการทดสอบที่สำคัญที่ภาษาสามารถให้การสนับสนุนได้ดีที่สุด


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

2

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

สอง, imho, ตัวอย่างที่ดีของเรื่องนี้คือจาก F # เพื่อความสนุกและกำไรที่นี่และที่นี่

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


2

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

ตัวอย่างเช่นการทดสอบหน่วยใน C # ส่วนใหญ่ขับเคลื่อนด้วยการใช้คุณลักษณะ แอตทริบิวต์ที่กำหนดเองคุณลักษณะให้เป็นกลไกส่วนขยายที่อุดมไปด้วยที่ช่วยให้กรอบเช่น NUnit ย้ำและแข่งขันกับสิ่งต่างๆเช่นทฤษฎี-basedและParameterizedทดสอบ

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

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

การอ่านอื่น ๆ ที่เกี่ยวข้อง:

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