มาตรฐานการเข้ารหัสหน่วยทดสอบ


22

โดยปกติเมื่อพูดถึงมาตรฐานการเข้ารหัสเราอ้างถึงรหัสของโปรแกรม แต่สิ่งที่เกี่ยวกับการทดสอบหน่วย? มีแนวทางมาตรฐานการเข้ารหัสบางอย่างที่ไม่ซ้ำกับการทดสอบหน่วย? พวกเขาคืออะไร

คำตอบ:


12

จากด้านบนของหัวของฉันฉันสามารถนึกถึงความแตกต่างสามแบบในการเขียนโค้ดสำหรับการทดสอบ

shouldDoSomethingWhenSomeConditionHoldsในการตั้งชื่อวิธีการทดสอบผมตามรูปแบบของ

ในการทดสอบเป็นเรื่องปกติที่จะทำตามรูปแบบระยะห่างต่อไปนี้:

@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
    // Some lines 
    // of setup code
    // go here.

    // The action being tested happens after a blank line.

    // An assertion follows another blank line.
}

บางคนยืนยันในการยืนยันเพียงครั้งเดียวต่อการทดสอบ แต่สิ่งนี้อยู่ไกลจากความเป็นสากล

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


แน่นอนว่ามีหลากหลายรูปแบบซึ่งเป็นสาเหตุที่คุณควรให้คำตอบด้วย
Eric Wilson

10
นั่นคือArrange, Act, Assert pattern
StuperUser

DRY ยังคงมีความสำคัญ หากคุณต้องการยืนยันแบบเดียวกันในการทดสอบหลาย ๆ ครั้งให้สร้างฟังก์ชั่นทั่วไปและเรียกมันว่าในการทดสอบทั้งหมด
MiFreidgeim หยุดความชั่วร้าย

@MichaelFreidgeim บางทีเราอาจจะพูดถึงองศา แต่ฉันมีความอดทนสูงขึ้นอย่างมากสำหรับการทำซ้ำในรหัสทดสอบ ฉันมีประสบการณ์หลายครั้งในการสร้างชุดทดสอบที่มีการทำซ้ำน้อยมากและพบว่าการทดสอบนั้นยากที่จะแก้ไขและเข้าใจเมื่อมีการเปลี่ยนแปลงข้อกำหนด จากนั้นฉันก็หยุดกังวลเกี่ยวกับ DRY มากในการทดสอบและชุดทดสอบของฉันนั้นใช้งานง่ายกว่า <shrug>
Eric Wilson

16

Roy Osherove แนะนำรูปแบบต่อไปนี้สำหรับการตั้งชื่อการทดสอบของคุณ:

NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior() 

ดูhttp://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx


ฉันเห็นด้วยกับรอย มันช่วยให้อ่านง่ายขึ้นแม้ว่า ReSharper จะบอกฉันว่าฉันควรลบออกไปNameOfMethodUnderTestStateUnderTestExpectedBehavior());
Oscar Mederos

วิธีทำให้มันทำงานเมื่อเมธอดโอเวอร์โหลดดังนั้นอาจมีหลายวิธีที่มีชื่อเหมือนกัน?
Narendra Pathai

6

สิ่งสำคัญคือต้องจำไว้ว่าการทดสอบหน่วยเป็นข้อกำหนดขนาดเล็ก ซึ่งหมายความว่าการเน้นจะต้องอ่านได้เสมอ

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

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

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

ฉันจะปัดเศษด้วยคำแนะนำหนังสือไม่กี่:

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

ศิลปะการทดสอบหน่วย: ด้วยตัวอย่างใน. Net : หนังสือที่ดีที่สุดเกี่ยวกับการเขียนและการบำรุงรักษาที่ดีที่สุด แม้จะเป็นเรื่องใหม่จริง ๆ แต่ฉันพบว่าส่วนที่ล้อเล่นล้าสมัยไปแล้วเล็กน้อยเนื่องจากไวยากรณ์ AAA ตอนนี้เป็นมาตรฐานที่ค่อนข้างดี

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


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

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

3

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

void MyTest_SaysHello()
{
   string name = "Bob";
   string expected = string.Format("Hello, {0}", name);
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello(name);
   Assert.AreEqual(expected, actual);
}

โดยเฉพาะอย่างยิ่งในกรณีนี้คุณมีแนวโน้มที่จะทำซ้ำตรรกะเดียวกันกับสิ่งที่อยู่ในการทดสอบดังนั้นคุณจำเป็นต้องทดสอบ "1 + 1 == 1 + 1" มากกว่า "1 + 1 == 2" ซึ่งเป็น การทดสอบ "ของจริง" ดังนั้นสิ่งที่คุณต้องการให้โค้ดทดสอบของคุณมีลักษณะดังนี้คือ:

void MyTest_SaysHello()
{
   string expected = "Hello, Bob";
   IMyObjectType myObject = new MyObjectType();
   string actual = myObject.SayHello("Bob");
   Assert.AreEqual(expected, actual);
}

2
การแก้ไขเล็กน้อย: ฉันคิดว่าคุณหมายถึง 'string คาด = string.Format ("Hello, Bob") "ควรเป็น" คาดหวังสตริง = "Hello, Bob"'
Mike Rosenblum

@MikeRosenblum เห็นได้ชัดว่าคุณถูกต้องและมีคนพยายามแก้ไข แต่ผู้ตรวจสอบสองคนปฏิเสธการแก้ไขนี้
Konrad Morawski

@ Konrad: มันแปลก นี่คือฟอรัมการเขียนโปรแกรมใช่ไหม
Mike Rosenblum

ฉันได้แก้ไขคำตอบอีกครั้งตามที่ Mike Rosenblum แนะนำ
bdsl

0

ชื่อเมธอดแบบยาวและเป็นคำอธิบาย จำไว้ว่าวิธีการทดสอบจะไม่ถูกเรียกจากรหัส (พวกมันถูกเรียกโดยนักทดสอบหน่วยที่ค้นพบและเรียกมันผ่านการสะท้อนกลับ) ดังนั้นจึงเป็นเรื่องปกติที่จะบ้าและมีชื่อวิธียาว 50-80 ตัว แบบแผนการตั้งชื่อที่เฉพาะเจาะจง (อูฐ - ตัวอักษรขีดล่าง "ควร", "ต้อง", "เมื่อ", "ให้", ฯลฯ ) ไม่สำคัญจริง ๆ ตราบเท่าที่ชื่อตอบคำถามสามข้อ:

  • สิ่งที่อยู่ภายใต้การทดสอบ?
  • เงื่อนไขคืออะไร?
  • ผลลัพธ์ที่คาดหวังคืออะไร

วิธีการทดสอบควรจะสั้น

วิธีการทดสอบควรจะมีความเรียบง่ายโครงสร้างเชิงเส้น ไม่มีถ้าหรือวนรอบการสร้าง

วิธีการทดสอบควรทำตาม"จัด-กระทำยืนยัน" รูปแบบ

การทดสอบแต่ละครั้งควรทดสอบสิ่งหนึ่ง ซึ่งมักจะหมายถึงหนึ่งยืนยันต่อการทดสอบ การทดสอบเช่น{ Do A; Assert B; Assert C; }นั้นควรปรับโครงสร้างเป็นสอง: { Do A; Assert B; }และ{ Do A; Assert C; }

หลีกเลี่ยงข้อมูลแบบสุ่มหรือสิ่งต่าง ๆ เช่น 'DateTime.Now'

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

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


-1

ค่อนข้างคล้ายกับที่ Farmboy พูดถึงแล้ว, รูปแบบชื่อเมธอดของฉัน

 <MethodName>Should<actionPerformed>When<Condition>

เช่น

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