อะไรคือความแตกต่างระหว่างความล้มเหลวและข้อผิดพลาดใน JUnit?


93

ฉันกำลังทำการทดสอบ JUnit บนฐานรหัสขนาดใหญ่และฉันตระหนักว่าบางครั้งฉันได้รับ "ข้อผิดพลาด" ในขณะที่บางครั้งฉันได้รับ "ความล้มเหลว" อะไรคือความแตกต่าง?

คำตอบ:


117

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


5
แม้ว่าสิ่งที่ขยายออกjava.lang.AssertionErrorไปจะถูกแสดงเป็นความล้มเหลวในการทดสอบแทนที่จะเป็นข้อผิดพลาดในการทดสอบ คุณควรพิจารณายอมรับคำตอบของคุณเองเพราะถูกต้อง
ponzao

ใช่นั่นคือความแตกต่าง และจากมุมมองเชิงปฏิบัตินั้น "ไม่มีความแตกต่าง" - หากคุณได้รับข้อผิดพลาดหรือความล้มเหลวคุณต้องแก้ไข ดังนั้นจึงอาจเป็นความผิดพลาดที่จะนับ "ความล้มเหลว" และ "ข้อผิดพลาด" แยกกันใน JUnit JUnit 4 รวมทั้งสองอย่างเข้าด้วยกัน (ตามที่อธิบายไว้ในคำตอบด้านล่าง)
Jeff Grigg

และถ้าข้อยกเว้นที่คาดว่าคุณควรมีคำอธิบายประกอบกับ@Test expected = SomeException.class
Downhillski

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

org.junit.Assert.assertEquals () หากล้มเหลวจะถือว่าผิดพลาดโดยรายงาน JUnit4 HTML สิ่งนี้ขัดแย้งกับคำพูดของคุณ (ซึ่งฉันรู้มาจนถึงตอนนี้) คุณช่วยเพิ่มความสว่างให้กับเรื่องนี้ได้ไหม
Krishnom

15

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

String s = null;
s.trim();

หรือ,

try {

    // your code
} catch(Exception e) {
    // log the exception
    throw new MyException(e);
}

ต้องบอกว่าสิ่งต่อไปนี้จะรายงานความล้มเหลว:

Assert.fail("Failure here");

หรือ,

Assert.assertEquals(1, 2);

หรือแม้กระทั่ง:

throw new AssertionException(e);

ขึ้นอยู่กับรุ่น Junit ที่คุณใช้ Junit 4- จะทำให้ความแตกต่างระหว่างความล้มเหลวและข้อผิดพลาด แต่ Junit 4 ทำให้ง่ายขึ้นเป็นความล้มเหลวเท่านั้น

ลิงค์ต่อไปนี้ให้ข้อมูลที่น่าสนใจมากขึ้น:

http://www.devx.com/Java/Article/31983/1763/page/2


สิ่งนี้ไม่ถูกต้อง ความแตกต่างระหว่างความล้มเหลวในการทดสอบและข้อผิดพลาดในการทดสอบไม่ได้หายไปใน JUnit 4 ฉันเพิ่งทดสอบ บทความที่เชื่อมโยงทำให้เข้าใจผิด มันบอกว่า "JUnit 4 ทำให้ง่ายขึ้นโดยใช้ความล้มเหลวเท่านั้น" แต่ควรเน้นว่า JUnit 4 เปลี่ยน java.lang.AssertionError เป็นข้อผิดพลาดในการทดสอบดังนั้นคุณไม่ต้องใช้ junit.framework.AssertionFailedError ข้อดีคือคุณสามารถเริ่มเขียนคำยืนยันการทดสอบในรหัสการผลิตโดยไม่ต้องเชื่อมโยงโปรเจ็กต์กับ JUnit ความแตกต่างระหว่างข้อผิดพลาดในการทดสอบและความล้มเหลวในการทดสอบยังมีประโยชน์อย่างมากและจะเป็นขั้นตอนถอยหลังหากนำออก
RonJRH

RonJRH คุณสามารถดูข้อผิดพลาดในรายงาน Junit เริ่มต้นของคุณได้หรือไม่?
Neel

ใช่ Neel ผมเพิ่งลองทำ ไม่แน่ใจว่ามารยาทในการเชื่อมโยงรูปภาพที่นี่ แต่แสดงผลการทดสอบของฉัน: imagebucket.net/abpxucddkvn1/Capture.PNG
RonJRH

6

จาก "Pragmatic Unit Testing ใน Java 8 ด้วย JUnit":

Assertions (หรือ asserts) ใน JUnit คือการเรียกวิธีการแบบคงที่ที่คุณใส่ลงในการทดสอบของคุณ การยืนยันแต่ละครั้งเป็นโอกาสในการตรวจสอบว่าเงื่อนไขบางอย่างเป็นจริง หากเงื่อนไขที่ยืนยันไม่เป็นจริงการทดสอบจะหยุดลงที่นั่นและ JUnit จะรายงานการทดสอบล้มเหลว

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


5

ด้านล่างทดสอบอธิบายความแตกต่างระหว่างข้อผิดพลาดการทดสอบเทียบกับความล้มเหลวในการทดสอบ

ฉันได้แสดงความคิดเห็นในบรรทัดที่แสดงข้อผิดพลาดในการทดสอบและการทดสอบล้มเหลว

    @Test
    public void testErrorVsTestFailure() {

        final String sampleString = null;

        assertEquals('j', sampleString.charAt(0) );
        //above line throws test error as you are trying to access charAt() method on null reference

        assertEquals(sampleString, "jacob");
        //above line throws Test failure as the actual value-a null , is not equal to expected value-string "jacob"
        }

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


2

คลาสซอร์ส: JUnitReportReporter.java

public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String defaultOutputDirectory) {
//......

            for (ITestResult tr : (Set) entry.getValue()) {
                TestTag testTag = new TestTag();

                boolean isSuccess = tr.getStatus() == 1;
                if (!(isSuccess)) {
                    if (tr.getThrowable() instanceof AssertionError)
                        ++errors;
                    else {
                        ++failures;
                    }
                }
}

ดังที่คุณเห็นด้านล่างบรรทัดในวิธีการด้านบน

tr.getThrowable () อินสแตนซ์ของ AssertionError

จำนวนข้อผิดพลาดจะเพิ่มขึ้นเมื่อเป็นอินสแตนซ์ของ AssertionError มิฉะนั้น (Throwable ใด ๆ ) จะนับเป็นความล้มเหลว


1

คุณคิดถูกว่าความล้มเหลวมาจาก AssertionErrors ที่เกิดจากวิธีการยืนยัน JUnit หรือโดยการโยน AssertionError หรือโดยการโยนข้อยกเว้นที่คุณประกาศไว้ใน@Testคำอธิบายประกอบของคุณและข้อผิดพลาดมาจากข้อยกเว้นอื่น ๆ ที่ไม่คาดคิด แต่มีความแตกต่างที่สำคัญระหว่างพวกเขา:

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

ข้อผิดพลาดอาจหมายถึงข้อบกพร่องในโค้ดของคุณ แต่ข้อผิดพลาดที่คุณยังไม่ได้ทดสอบ นอกจากนี้ยังอาจหมายความว่าจุดบกพร่องอยู่ในการทดสอบ

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


0

แดกดันจูนิทและเฟรมเวิร์กที่เกี่ยวข้องกับการทดสอบอื่น ๆ (testng, hamcrest) ให้การดำเนินการที่ยืนยันซึ่งตรวจสอบเงื่อนไขและหากล้มเหลวจะมีการ "ภายใต้ฝากระโปรง" java.lang.AssertionError ซึ่ง btw ขยาย java.lang.Error

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


0

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

สำหรับข้อมูลเพิ่มเติมโปรดตรวจสอบนี้

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