วิธีที่จะทำให้การทดสอบหนึ่งขึ้นอยู่กับผลของการทดสอบอื่นได้อย่างไร


13

สมมติว่ามีคลาสยูทิลิตี้ที่ให้วิธีคงที่ทั่วไปบางอย่างที่ใช้ในทุกที่ในรหัสของคุณโดยชั้นอื่น ๆ

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

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

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

ฉันหาแท็กที่เหมาะสมไม่ได้ แต่ใช้เครื่องมือทดสอบหน่วยของ Visual Studio


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

1
ฉันไม่เคยได้ยินเกี่ยวกับใครที่ต้องการสิ่งนี้มาก่อน คุณกำลังพยายามทำอะไรอยู่?
Esben Skov Pedersen


ฉันใช้ฟังก์ชั่นยูทิลิตี้บางอย่างเพื่อเตรียมข้อมูลสำหรับการทดสอบวิเคราะห์คำ
t3chb0t

3
@ t3chb0t หากคุณต้องการให้ยูทิลิตี้ของคุณใช้งานได้คุณต้องเขียนการทดสอบหน่วยเพื่อตรวจสอบยูทิลิตี้ของคุณ การทดสอบหน่วยควรเป็นอะตอม คุณต้องการให้พวกเขาทดสอบองค์ประกอบเดียว
maple_shaft

คำตอบ:


11

มีจุดที่จะทำให้แน่ใจว่าข้อบกพร่องในระบบของคุณทุกการเดินทางเป็นว่าการทดสอบหนึ่ง

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

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

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


8

ขึ้นอยู่กับเครื่องมือของคุณ แต่คุณอาจทำไม่ได้ (และไม่ควร)

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

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

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

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


5

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

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

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


4

โดยสรุปคุณไม่ต้องการใช้เครื่องมือ / เทคนิคในการทำสิ่งอื่นนอกเหนือจากที่มีไว้สำหรับ

สิ่งที่คุณพยายามทำดูเหมือนเป็นข้อกังวลที่สามารถแก้ไขได้อย่างง่ายดายด้วยการฝึก CI (การรวมอย่างต่อเนื่อง)

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

หากการทดสอบใด ๆ ล้มเหลวคุณสามารถตั้งค่าเพื่อไม่ให้โค้ดของคุณถูกเผยแพร่


4

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

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

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

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

ฉันไม่ทราบวิธีการทำงานใน Visual Studio เพราะฉันยังไม่ได้ทำอะไรที่เกี่ยวข้องกับการทดสอบอย่างกว้างขวางกับ C # แต่ในด้าน Java ของโลกมันทำงานดังนี้: ภายใต้โฟลเดอร์ต้นทางของโครงการเรามักจะมีสองโฟลเดอร์ย่อย หนึ่งเรียกว่า "หลัก" ที่มีรหัสการผลิตและหนึ่งที่เรียกว่า "ทดสอบ" ที่มีรหัสการทดสอบ ภายใต้ "main" เรามีลำดับชั้นของโฟลเดอร์ที่สอดคล้องกับลำดับชั้นของแพคเกจของซอร์สโค้ดของเรา แพ็คเกจ Java ประมาณคร่าวๆกับ C # namespaces C # ไม่ต้องการให้คุณจับคู่ลำดับชั้นของโฟลเดอร์กับลำดับชั้นของเนมสเปซ แต่แนะนำให้ทำเช่นนั้น

ตอนนี้สิ่งที่ผู้คนมักจะทำในโลก Java คือภายใต้โฟลเดอร์ "test" พวกเขาสะท้อนลำดับชั้นของโฟลเดอร์ที่พบภายใต้โฟลเดอร์ "main" เพื่อให้การทดสอบแต่ละครั้งอยู่ในแพ็คเกจเดียวกันกับคลาสที่ทดสอบ เหตุผลที่อยู่เบื้องหลังสิ่งนี้คือบ่อยครั้งที่คลาสการทดสอบจำเป็นต้องเข้าถึงสมาชิกแพคเกจส่วนตัวของคลาสที่อยู่ภายใต้การทดสอบดังนั้นคลาสการทดสอบจะต้องอยู่ในแพ็คเกจเดียวกันกับคลาสที่อยู่ภายใต้การทดสอบ ในด้าน C # ของโลกไม่มีสิ่งเช่นทัศนวิสัย namespace ท้องถิ่นจึงไม่มีเหตุผลที่จะสะท้อนลำดับชั้นของโฟลเดอร์ แต่ฉันคิดว่าโปรแกรมเมอร์ C # ทำตามระเบียบเดียวกันในการสร้างโฟลเดอร์ของพวกเขา

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

ดังนั้นสิ่งที่ฉันทำคือฉันตั้งชื่อโฟลเดอร์ (หมายถึงแพ็คเกจ) ของการทดสอบดังนี้

t001_SomeSubsystem
t002_SomeOtherSubsystem
t003_AndYetAnotherSubsystem
...

สิ่งนี้รับประกันว่าการทดสอบทั้งหมดสำหรับ "SomeSubsystem" จะถูกดำเนินการก่อนการทดสอบทั้งหมดสำหรับ "SomeOtherSubsystem" ซึ่งจะถูกดำเนินการทั้งหมดก่อนการทดสอบทั้งหมดสำหรับ "AndYetAnotherSubsystem" และอื่น ๆ

ภายในโฟลเดอร์ไฟล์ทดสอบแต่ละไฟล์จะมีชื่อดังนี้:

T001_ThisTest.java
T002_ThatTest.java
T003_TheOtherTest.java

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


2
I don't know about everyone else, but I would prefer to have the freedom to try to do something in an odd way, and see for myself whether the results are better or worse++ เพื่อน ฉันไม่รู้ว่าฉันชอบวิธีแก้ปัญหา แต่ฉันชอบทัศนคติที่คุณแสดงออกมา
RubberDuck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.