สร้างบัญชีตัวแทน JUnit ชุดทดสอบพร้อมตัวอย่าง: @RunWith @SuiteClasses

⚡ สรุปอย่างชาญฉลาด

JUnit ชุดทดสอบจะรวบรวมกรณีทดสอบจากหลายคลาสเข้าด้วยกันเพื่อให้ทำงานพร้อมกันในรอบเดียว โดยใช้คำอธิบายประกอบ @RunWith(Suite.class) และ @SuiteClasses และเรียกใช้งานผ่านคลาสเรียกใช้การทดสอบทั่วไป

  • 🔘 วัตถุประสงค์: รวมการทดสอบจากหลายคลาสเข้าไว้ในหน่วยเดียวที่สามารถเรียกใช้งานได้ แทนที่จะเรียกใช้คลาสทดสอบแต่ละคลาสแยกกัน
  • ☑️ คำอธิบายประกอบ: @RunWith(Suite.class) จะมอบหมายการดำเนินการ ในขณะที่ @SuiteClasses จะแสดงรายการคลาสทั้งหมดที่ชุดทดสอบต้องเรียกใช้
  • ขั้นตอน: เขียนคลาสทดสอบ เพิ่มคลาสตัวกลางที่เก็บคำอธิบายประกอบทั้งสอง จากนั้นเรียกใช้จาก JUnitนักวิ่งหลัก
  • 🧪 ตัวอย่าง: ไฟล์ JunitTest.java จัดกลุ่ม SuiteTest1 และ SuiteTest2 เข้าด้วยกัน และคอนโซลจะรายงานว่ามีการทดสอบผ่าน 3 รายการ
  • 🛠️ JUnit 5: Jupiter แทนที่ Runner ด้วย @Suite บวกกับ @SelectClasses หรือ @SelectPackages บน Platform Suite Engine
  • 📌 หลุมพราง: ชุดทดสอบที่ว่างเปล่า การนำเข้าที่ขาดหายไป และคลาสชุดทดสอบที่มีเมธอด @Test ของตัวเอง เป็นสาเหตุหลักของความล้มเหลว

การสร้าง JUnit ชุดทดสอบที่มีคำอธิบายประกอบ @RunWith และ @SuiteClasses

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

ในการรันชุดทดสอบ คุณต้องใส่คำอธิบายประกอบให้กับคลาสโดยใช้คำอธิบายประกอบที่ระบุไว้ด้านล่าง:

  1. @RunWith(Suite.class)
  2. @SuiteClasses(test1.class, test2.class…) หรือ @Suite.SuiteClasses({test1.class, test2.class…})

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

ขั้นตอนในการสร้างชุดทดสอบและตัวทดสอบ

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

ขั้นตอน 1) สร้างคลาสทดสอบอย่างง่าย (เช่น MyFirstClassTest) และเพิ่มเมธอดที่ใส่คำอธิบายประกอบด้วย @ทดสอบ.

คลาสแรกมีเมธอดทดสอบว่างเปล่าเพียงเมธอดเดียว ซึ่งเพียงพอที่จะพิสูจน์ได้ว่าชุดทดสอบนั้นตรวจพบเมธอดดังกล่าว:

คลาส MyFirstClassTest ใน Eclipse การประกาศ myFirstMethod ที่มีคำอธิบายประกอบ @Test

ขั้นตอน 2) สร้างคลาสทดสอบอีกคลาสเพื่อเพิ่ม (เช่น MySecondClassTest) และสร้างเมธอดที่ใส่คำอธิบายประกอบ @Test

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

คลาส MySecondClassTest ใน Eclipse การประกาศ mySecondMethod ที่มีคำอธิบายประกอบ @Test

ขั้นตอน 3) ในการสร้าง testSuite คุณต้องใส่คำอธิบายประกอบให้กับคลาสก่อนด้วย @RunWith(Suite.class) และ @SuiteClasses(class1.class, class2.class…)

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

TestSuiteExample ที่มีคำอธิบายประกอบด้วย @RunWith(Suite.class) และ @SuiteClasses โดยตั้งชื่อว่า MyFirstClassTest และ MySecondClassTest

ขั้นตอน 4) สร้างคลาส Test Runner เพื่อรันชุดทดสอบของเราตามตัวอย่างด้านล่าง:

นักวิ่งนั้นเป็นคนธรรมดา Java คลาสที่มีเมธอด main ซึ่งส่งต่อคลาส suite ไปยัง JUnitหลัก:

การเรียกใช้คลาสรันการทดสอบ JUnitเรียกใช้ Core.runClasses บน TestSuiteExample และแสดงรายการข้อผิดพลาด

Code คำอธิบาย:

  • Code 8 แนว: ประกาศเมธอดหลักของคลาส Test ซึ่งจะรันคำสั่งของเรา JUnit ทดสอบ
  • Code 9 แนว: ดำเนินการทดสอบโดยใช้ JUnitCore.runClasses เป็นเมธอดที่รับชื่อคลาสทดสอบเป็นพารามิเตอร์ (ในตัวอย่างข้างต้น คุณใช้ TestSuiteExample.class ตามที่แสดงในขั้นตอนที่ 3)
  • Code 11 แนว: ประมวลผลผลลัพธ์โดยใช้ลูป for และพิมพ์ผลลัพธ์ที่ล้มเหลวออกมา
  • Code 13 แนว: การพิมพ์ผลลัพธ์สำเร็จ

Output: นี่คือผลลัพธ์ที่แสดงให้เห็นว่าการทดสอบประสบความสำเร็จโดยไม่มีข้อผิดพลาด trace ดังที่ระบุไว้ด้านล่าง:

Eclipse JUnit ดูรายงานผลการทดสอบ พบว่าการทดสอบ 2/2 ครั้ง โดยไม่มีข้อผิดพลาดหรือความล้มเหลวใดๆ สำหรับ TestSuiteExample

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

JUnit ตัวอย่างชุดทดสอบ

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

จูนิทเทสต์จาวา

JunitTest.java เป็นคลาสอย่างง่ายที่ติดคำอธิบายประกอบด้วย @รันวิท และ @สวีท คำอธิบายประกอบ คุณสามารถระบุคลาสจำนวนเท่าใดก็ได้ในชุดทดสอบเป็นพารามิเตอร์ ดังที่แสดงด้านล่าง:

package guru99.junit;		
import org.junit.runner.RunWith;		
import org.junit.runners.Suite;		

@RunWith(Suite.class)				
@Suite.SuiteClasses({				
  SuiteTest1.class,
  SuiteTest2.class,  			
})		

public class JunitTest {				
			// This class remains empty, it is used only as a holder for the above annotations		
}

SuiteTest1.java

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

package guru99.junit;		

import static org.junit.Assert.assertEquals;				

import org.junit.Test;		

public class SuiteTest1 {				

    public String message = "Saurabh";							

    JUnitMessage junitMessage = new JUnitMessage(message);							

    @Test(expected = ArithmeticException.class)					
    public void testJUnitMessage() {					

        System.out.println("Junit Message is printing ");					
        junitMessage.printMessage();			

    }		

    @Test		
    public void testJUnitHiMessage() {					
        message = "Hi!" + message;							
        System.out.println("Junit Hi Message is printing ");					
        assertEquals(message, junitMessage.printHiMessage());					
        System.out.println("Suite Test 2 is successful " + message);							
    }		
}		

SuiteTest2.java

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

package guru99.junit;		

import org.junit.Assert;		
import org.junit.Test;		

public class SuiteTest2 {				
   	

    @Test		
    public void createAndSetName() {					
        		

        String expected = "Y";					
        String actual = "Y";					

        Assert.assertEquals(expected, actual);					
        System.out.println("Suite Test 1 is successful " + actual);							
    }		

}		

เอาท์พุต

หลังจากดำเนินการ จูนิทเทสต์.java ซึ่งประกอบด้วยชุดคำสั่งต่างๆ SuiteTest1.java และ SuiteTest2.javaคุณจะได้รับผลลัพธ์ดังต่อไปนี้ คอนโซลจะแสดงข้อความที่สร้างขึ้นโดยทั้งสองคลาส:

Eclipse หน้าจอคอนโซลแสดงข้อความที่พิมพ์จากคลาสทั้งสองหลังจาก JunitTest ทำงานเสร็จสิ้น

การขอ JUnit การแสดงผลจะบันทึกการทำงานเดียวกันกับวิธีการทดสอบที่ผ่านสามวิธีซึ่งจัดกลุ่มไว้ภายใต้คลาสชุดทดสอบ:

Eclipse JUnit ดูรายงานผลการทำงาน ผลลัพธ์เป็นสีเขียว 3/3 สำหรับ JunitTest โดยมีการขยาย SuiteTest1 และ SuiteTest2

หมายเหตุ ป้ายกำกับคอนโซลในตัวอย่างนี้สลับกัน — ข้อความที่พิมพ์โดย SuiteTest1 อ่านว่า “Suite Test 2” และข้อความที่พิมพ์โดย SuiteTest2 อ่านว่า “Suite Test 1” รายการต้นฉบับถูกแสดงซ้ำโดยไม่มีการเปลี่ยนแปลง ดังนั้นป้ายกำกับจึงยังคงเหมือนเดิมตามที่ผู้เขียนเขียนไว้ โปรดอ่านชื่อคลาสใน JUnit เมื่อคุณทำการจับคู่ผลลัพธ์กับแหล่งที่มา ให้ดูภาพแทนที่จะดูที่ฉลากที่พิมพ์ออกมา

วิธีการสร้างชุดทดสอบใน JUnit 5

JUnit 5 ลบ Runner ออกทั้งหมด ดังนั้น @RunWith(Suite.class) จึงไม่มีอยู่ในแพ็กเกจ org.junit.jupiter แล้ว Suites ถูกย้ายไปยัง JUnit แพลตฟอร์ม ซึ่งจัดส่งสิ่งเหล่านี้ในรูปแบบไฟล์แยกต่างหากที่เรียกว่า เอ็นจิ้นแพลตฟอร์มชุดจูนิทเพิ่มการพึ่งพา (dependency) นั้น จากนั้นใส่คำอธิบายประกอบให้กับคลาสด้วย @Suite และคำอธิบายประกอบตัวเลือก (selector annotations) ตัวใดตัวหนึ่ง

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
import org.junit.platform.suite.api.SuiteDisplayName;

@Suite
@SuiteDisplayName("Guru99 suite")
@SelectClasses({ SuiteTest1.class, SuiteTest2.class })
public class JunitTest {
    // Empty holder, exactly as in JUnit 4
}

คำอธิบายประกอบตัวเลือกจะแทนที่รายการ @SuiteClasses รายการเดียวด้วยกลุ่มตัวเลือกขนาดเล็ก:

คำอธิบายประกอบ สิ่งที่มันเลือก
@เลือกคลาส ตั้งชื่อคลาสทดสอบแต่ละคลาสทีละคลาส ซึ่งเป็นการแทนที่ @SuiteClasses โดยตรง
@เลือกแพ็คเกจ คลาสทดสอบทุกคลาสในแพ็กเกจที่ระบุชื่อและในแพ็กเกจย่อยทั้งหมดของแพ็กเกจนั้น
@IncludeClassNamePatterns มีการใช้ตัวกรองนิพจน์ปกติ (Regular Expression Filter) ซ้อนทับบนส่วนที่เลือกไว้
@SuiteDisplayName แสดงชื่อที่อ่านง่ายในรายงานแทนชื่อคลาส

ความแตกต่างอีกสองประการที่สำคัญในทางปฏิบัติ ได้แก่ ก. JUnit คลาส Suite 5 อาจประกาศเมธอด @BeforeSuite และ @AfterSuite ซึ่งจะทำงานหนึ่งครั้งตลอดทั้งชุดทดสอบ และ JUnit ตัวอย่างที่ 4 ข้างต้นยังคงทำงานอยู่ JUnit แพลตฟอร์มนี้ใช้เอนจิ้นแบบดั้งเดิม ดังนั้นโค้ดเดิมในหน้านี้จึงไม่จำเป็นต้องเขียนใหม่เพื่อให้ยังคงใช้งานได้

ข้อดีและข้อจำกัดของ JUnit ห้องทดสอบ

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

ข้อดี

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

ข้อ จำกัด

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

ข้อผิดพลาดทั่วไปเมื่อสร้าง JUnit ชุดทดสอบ

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

ข้อความหรืออาการ ก่อให้เกิด แก้ไขปัญหา
initializationError: ไม่มีเมธอดที่สามารถเรียกใช้งานได้ คลาสนี้ทำงานเหมือนคลาสทดสอบทั่วไป แต่มีเพียงคำอธิบายประกอบเท่านั้น เพิ่ม @RunWith(Suite.class) เพื่อให้ตัวรันชุดทดสอบทำงานแทนตัวรันเริ่มต้น
ไม่พบสัญลักษณ์: คลาส Suite การนำเข้า Suite หายไป นำเข้า org.junit.runners.Suite ควบคู่ไปกับ org.junit.runner.RunWith
ชุดโปรแกรมทำงานได้ แต่มีการข้ามชั้นเรียนไปหนึ่งชั้นเรียน คลาสนี้ไม่เคยถูกเพิ่มเข้าไปในรายการ @SuiteClasses เลย เพิ่มคลาสอย่างชัดเจน หรือย้ายไปที่ @SelectPackages ใน JUnit 5.
ชื่อคลาสไม่ได้รับการยอมรับจากคอมไพเลอร์ @Runwith หรือ @suiteClasses พิมพ์ด้วยตัวพิมพ์ใหญ่-เล็กผิด Java การใส่คำอธิบายประกอบนั้นต้องตรงตามตัวพิมพ์ใหญ่เล็ก: เขียน @RunWith และ @SuiteClasses ให้ตรงเป๊ะ
การทดสอบในคลาส Suite เองจะไม่ถูกเรียกใช้งาน มีการเพิ่มเมธอด @Test ลงใน suite holder แล้ว เว้นช่องว่างสำหรับเก็บข้อมูลไว้ และย้ายเมธอดทดสอบไปไว้ในคลาสสมาชิก

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

คำถามที่พบบ่อย

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

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

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

Copilot เขียนคู่คำอธิบายประกอบได้อย่างรวดเร็ว แต่บ่อยครั้งที่มันสับสน JUnit 4 และ JUnit มีการนำเข้า 5 รายการในไฟล์เดียวกัน ตรวจสอบให้แน่ใจว่า org.junit.runners.Suite และ org.junit.platform.suite.api.Suite ไม่ปรากฏร่วมกัน เนื่องจากมีเพียงรายการเดียวเท่านั้นที่ตรงกับ runner ของคุณ

เพิ่ม junit-platform-suite-engine ลงในขอบเขตการทดสอบ คำอธิบายประกอบ @Suite และ @SelectClasses อยู่ใน junit-platform-suite-api ซึ่งอาร์ติแฟกต์ของเอนจิ้นนั้นดึงเข้ามาโดยทางอ้อม ดังนั้นโดยปกติแล้วการพึ่งพาเพียงรายการเดียวก็เพียงพอแล้ว

โดยปกติแล้วไม่ใช่ Surefire และ Gradle งานทดสอบจะค้นหาคลาสทดสอบโดยใช้รูปแบบการตั้งชื่อและเรียกใช้ทั้งหมดอยู่แล้ว การเขียนชุดทดสอบนั้นคุ้มค่าเมื่อคุณต้องการชุดย่อยที่มีชื่อ เช่น ชุดทดสอบเบื้องต้น (smoke set) ที่มีขนาดเล็กกว่าการเรียกใช้ทั้งหมด

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

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

สรุปโพสต์นี้ด้วย: