ข้อตกลงการตั้งชื่อยอดนิยมสำหรับการทดสอบหน่วยมีอะไรบ้าง [ปิด]


203

ทั่วไป

  • ปฏิบัติตามมาตรฐานเดียวกันสำหรับการทดสอบทั้งหมด
  • ชัดเจนเกี่ยวกับสถานะการทดสอบแต่ละครั้ง
  • มีความเฉพาะเจาะจงเกี่ยวกับพฤติกรรมที่คาดหวัง

ตัวอย่าง

1) MethodName_StateUnderTest_ExpectedBehavior

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown() 

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown () 

Public void Sum_simpleValues_Calculated ()

ที่มา: การตั้งชื่อมาตรฐานสำหรับการทดสอบหน่วย

2) การแยกแต่ละคำด้วยการขีดเส้นใต้

Public void Sum_Negative_Number_As_1st_Param_Exception_Thrown() 

Public void Sum_Negative_Number_As_2nd_Param_Exception_Thrown () 

Public void Sum_Simple_Values_Calculated ()

อื่น ๆ

  • สิ้นสุดชื่อวิธีด้วยการทดสอบ
  • เริ่มต้นชื่อเมธอดพร้อมชื่อคลาส

ดูพฤติกรรมการขับเคลื่อนการพัฒนา
Wedge

คำตอบ:


94

ฉันสวยมากกับคุณกับผู้ชายคนนี้ แบบแผนการตั้งชื่อที่คุณใช้คือ:

  • ชัดเจนเกี่ยวกับสถานะการทดสอบแต่ละรายการ
  • โดยเฉพาะเกี่ยวกับพฤติกรรมที่คาดหวัง

คุณต้องการอะไรอีกจากชื่อการทดสอบ

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

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

ที่กล่าวว่าฉันยังค่อนข้างใหม่ในการทดสอบและบล็อกการผจญภัยของฉันด้วย :)


20
ความขัดแย้งเล็กน้อย "ตราบเท่าที่มันสามารถอ่านได้และชัดเจน" และ "ใคร ... ใส่ใจ" ทุกคนใส่ใจเมื่อมันอ่านไม่ได้ & ชัดเจนนั่นคือเหตุผลว่าทำไมมันถึงสำคัญ :-)
David Victor

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

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

@ negrotico19 ฉันกำลังคิดกรณีใน IntelliJ เมื่อคุณSearch Everywhere(shift shift) หรือFind a Class By Name(CMD O) ฉันเข้าใจว่ามันจะแตกต่างจากโครงสร้างโฟลเดอร์หรือโครงสร้างโมดูล แต่เมื่อเราค้นหาบางอย่างเรารู้แล้วว่าเราต้องการค้นหาอะไร ตัวอย่างเช่นหากฉันกำลังมองหาการทดสอบฉันต้องการ จำกัด การค้นหาของฉันtestและจากนั้นค้นหาชื่อแทนที่จะค้นหาชื่อจากนั้นกรองการทดสอบด้วยตาเอง มันเป็นความแตกต่างเล็ก ๆ น้อย ๆ แต่ง่ายกว่ามากในการ "ทดสอบ [ชื่อคลาส]" และมีป๊อปอัพเพียงหนึ่งเดียวและลดภาระทางจิต
นี้ต้องการความช่วยเหลือ

37

นี่เป็นสิ่งที่ควรอ่าน: การทดสอบโครงสร้างหน่วย

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

เช่น

using Xunit;

public class TitleizerFacts
{
    public class TheTitleizerMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void Name_AppendsTitle()
        {
            // Test code
        }
    }

    public class TheKnightifyMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void MaleNames_AppendsSir()
        {
            // Test code
        }

        [Fact]
        public void FemaleNames_AppendsDame()
        {
            // Test code
        }
    }
}

และนี่คือเหตุผล:

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

ฉันชอบวิธีนี้:

MethodName_StateUnderTest_ExpectedBehavior

ดังนั้นอาจปรับเป็น:

StateUnderTest_ExpectedBehavior

เพราะการทดสอบแต่ละครั้งจะอยู่ในชั้นซ้อนกันแล้ว


2
สำหรับผู้ที่ใช้โปรแกรมทดสอบของ Resharper ใน Visual Studio พวกเขาแก้ไขข้อบกพร่องโดยใช้การทดสอบซ้อนใน 8.x ตั้งแต่นี้มาฉันก็กลายเป็นโครงสร้างที่ฉันชอบ
angularsen

มันสำคัญไหมว่าชื่อนั้นยาวมากด้วยเมธอด MethodName_StateUnderTest_ExpectedBehavior เช่น "InitializeApiConfiguration_MissingApiKey_IllegalArgumentException" นี่เป็นชื่อการทดสอบที่ดีหรือไม่?
portfoliobuilder

28

ฉันมักจะใช้แบบแผนของMethodName_DoesWhat_WhenTheseConditionsตัวอย่างเช่น:

Sum_ThrowsException_WhenNegativeNumberAs1stParam

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

  • เตรียมการ
  • การกระทำ
  • ยืนยัน

ซึ่งยังติดตามไวยากรณ์ BDD / Gherkin ของ:

  • ป.ร. ให้ไว้
  • เมื่อไหร่
  • แล้วก็

ซึ่งจะตั้งชื่อการทดสอบในลักษณะของ: UnderTheseTestConditions_WhenIDoThis_ThenIGetThis

ตัวอย่างของคุณ:

WhenNegativeNumberAs1stParam_Sum_ThrowsAnException

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


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

ในคำอื่น ๆ ผมชอบ: ดีกว่าSum_ThrowsException_WhenNegativeNumberAs1stParamSum_Throws_Exception_When_Negative_Number_As_1st_Param


22

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

[TestMethod]
public void CanCountAllItems() {
  // Test the total count of items in collection.
}

เนื่องจากข้อเท็จจริงที่ว่าแต่ละคลาสการทดสอบควรทดสอบคลาสอื่นเท่านั้นฉันปล่อยให้ชื่อของคลาสออกจากชื่อวิธี ชื่อของคลาสที่มีเมธอดการทดสอบมีชื่อเหมือนกับคลาสที่อยู่ภายใต้การทดสอบด้วย postfix "Tests"

[TestClass]
public class SuperCollectionTests(){
    // Any test methods that test the class SuperCollection
}

สำหรับวิธีการที่การทดสอบสำหรับข้อยกเว้นหรือการกระทำที่ไม่เป็นไปได้ผมคำนำหน้าวิธีการทดสอบที่มีคำว่าไม่สามารถ

[TestMethod]
[ExpectedException(typeOf(ArgumentException))]
public void CannotAddSameObjectAgain() {
  // Cannot add the same object again to the collection.
}

ความเชื่อมั่นในการตั้งชื่อของฉันอยู่ที่บทความ"เคล็ดลับ TDD: แบบทดสอบการตั้งชื่อและแนวทาง"ของ Bryan Cook ฉันพบบทความนี้มีประโยชน์มาก


1
+1 สำหรับลิงก์ไปยังโพสต์ของฉัน - แม้ว่าจะไม่จำเป็นต้องใช้คำนำหน้า "ทดสอบ" ในการทดสอบของคุณ ตรวจสอบให้แน่ใจว่าการทดสอบของคุณระบุพฤติกรรมที่คาดหวัง ตัวอย่างเช่น CanRetrieveProperCountWhenAddingMultipleItems ()
bryanbcook

2
ฉันไม่ชอบมันเพราะมันไม่รวมถึงพฤติกรรมที่คาดหวัง
โยฮันเนรูด

5

ชุดแรกของชื่อสามารถอ่านได้มากขึ้นสำหรับฉันเนื่องจาก CamelCasing แยกคำและแถบใต้ส่วนต่าง ๆ ของแผนการตั้งชื่อ

ฉันมักจะรวม "ทดสอบ" ที่ใดที่หนึ่งไม่ว่าจะเป็นในชื่อฟังก์ชั่นหรือล้อมรอบเนมสเปซหรือคลาส


2
@Frank methodName = camelCase MethodName = PascalCase
Metro Smurf

@ metro-smurf: ความแตกต่างที่น่าสนใจฉันไม่เคยได้ยินคำว่า PascalCase ที่ใช้และฉันได้ทำสิ่งนี้มาเป็นเวลานาน ฉันเห็นเฉพาะคำว่า PascalCase เกิดขึ้นในแวดวงนักพัฒนาของ Microsoft นั่นคือสิ่งที่คุณทำ
46420 Frank Szczerba

ประวัติศาสตร์รอบ ๆ Pascal Casing และ Camel Casing (จาก: Brad Abrams - blogs.msdn.com/brada/archive/2004/02/03/67024.aspx ) ... "ในการออกแบบเบื้องต้นของ Framework เรามีเวลาหลายร้อยชั่วโมง การถกเถียงเกี่ยวกับรูปแบบการตั้งชื่อเพื่อความสะดวกในการโต้วาทีเราประกาศเกียรติคุณจำนวนหนึ่งด้วย Anders Heilsberg (ผู้ออกแบบดั้งเดิมของ Turbo Pascal) เป็นสมาชิกคนสำคัญของทีมออกแบบจึงไม่น่าแปลกใจที่เราเลือกคำว่า Pascal Casing เป็นที่นิยมของภาษาการเขียนโปรแกรมภาษาปาสกาล "
Heliac

-3

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


-8

ฉันใช้คำนำหน้า 'T' สำหรับการทดสอบเนมสเปซ, คลาสและเมธอด

ฉันพยายามเรียบร้อยและสร้างโฟลเดอร์ที่ทำซ้ำเนมสเปซจากนั้นสร้างโฟลเดอร์การทดสอบหรือโปรเจ็กต์แยกต่างหากสำหรับการทดสอบและทำซ้ำโครงสร้างการผลิตสำหรับการทดสอบพื้นฐาน:

AProj
   Objects
      AnObj
         AProp
   Misc
      Functions
         AFunc
   Tests
      TObjects
         TAnObj
            TAnObjsAreEqualUnderCondition
      TMisc
         TFunctions
            TFuncBehavesUnderCondition

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

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

ง่ายในการรวบรวมโดยมีหรือไม่มีการทดสอบ

ในทางทฤษฎีแล้วมันใช้ได้ดีสำหรับโครงการขนาดเล็ก


3
แนวทางที่น่าสนใจ บางคนอาจโต้แย้งว่าคำนำหน้า T ขัดแย้งกับการประชุมที่คุณใช้ในข้อมูลทั่วไป (เช่น func (T1, T2, TResult)) แต่โดยส่วนตัวฉันไม่สนใจตราบใดที่มีความเห็นเป็นเอกฉันท์ในทีม ชื่อสั้น ๆ ซึ่งทำให้อ่านง่ายขึ้น
stung

ฮังการีเกินไป (สัญกรณ์) สำหรับฉัน นอกจากนี้ยังได้ระบุคำนำหน้า T ใช้สำหรับพารามิเตอร์ประเภททั่วไป
Danny Varod

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