การใช้ 'ล้มเหลว' จริงในกรณีทดสอบ JUnit คืออะไร?


คำตอบ:


138

บางกรณีที่ฉันพบว่ามีประโยชน์:

  • ทำเครื่องหมายว่าการทดสอบยังไม่สมบูรณ์ดังนั้นจึงล้มเหลวและเตือนคุณจนกว่าคุณจะสามารถทำเสร็จได้
  • ตรวจสอบให้แน่ใจว่ามีข้อยกเว้นเกิดขึ้น:
try{
  // do stuff...
  fail("Exception not thrown");
}catch(Exception e){
  assertTrue(e.hasSomeFlag());
}

บันทึก:

ตั้งแต่ JUnit4 มีวิธีที่สวยงามกว่าในการทดสอบว่ามีการโยนข้อยกเว้น: ใช้คำอธิบายประกอบ @Test(expected=IndexOutOfBoundsException.class)

fail()แต่นี้จะไม่ทำงานหากคุณยังต้องการที่จะตรวจสอบข้อยกเว้นแล้วคุณยังคงต้อง


5
พิจารณาบล็อกโพสต์นี้เกี่ยวกับข้อดีของความล้มเหลวเทียบกับคำอธิบายประกอบที่คาดไว้: blog.jooq.org/2016/01/20/…
lbalazscs

4
@sleske "หากคุณต้องการตรวจสอบข้อยกเว้นด้วยแสดงว่าคุณยังต้องล้มเหลว ()" - ไม่ คาดว่าจะได้รับข้อ
ยกเว้น

@kraxor: จริงไม่ทราบเกี่ยวกับเรื่องนี้เมื่อฉันเขียนคำตอบ (อาจจะยังไม่ถึงเวลานั้น)
sleske

14

สมมติว่าคุณกำลังเขียนกรณีทดสอบสำหรับโฟลว์เชิงลบซึ่งโค้ดที่กำลังทดสอบควรมีข้อยกเว้น

try{
   bizMethod(badData);
   fail(); // FAIL when no exception is thrown
} catch (BizException e) {
   assert(e.errorCode == THE_ERROR_CODE_U_R_LOOKING_FOR)
}

10

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

บางอย่างเช่นรหัสหลอกต่อไปนี้:

test_addNilThrowsNullPointerException()
{
    try {
        foo.add(NIL);                      // we expect a NullPointerException here
        fail("No NullPointerException");   // cause the test to fail if we reach this            
     } catch (NullNullPointerException e) {
        // OK got the expected exception
    }
}

3
หากคุณไม่ได้ตรวจสอบบางสิ่งในบล็อก catch คุณสามารถใช้คำอธิบายประกอบเมธอด @ExpectedException (NullNullPointerException.class) เพื่อประกาศว่าคุณคาดว่าจะมีข้อยกเว้น (ชนิดพิเศษ)
FrVaBe

8

ฉันเคยใช้มันในกรณีที่มีบางอย่างผิดปกติในเมธอด @Before ของฉัน

public Object obj;

@Before
public void setUp() {
    // Do some set up
    obj = new Object();
}

@Test
public void testObjectManipulation() {
    if(obj == null) {
        fail("obj should not be null");
     }

    // Do some other valuable testing
}

1
ใช่เงื่อนไขการทดสอบเป็นสิ่งที่ดี อย่างไรก็ตามหากคุณต้องการให้แน่ใจว่า@Beforeวิธีการนี้ประสบความสำเร็จคุณควรตรวจสอบโดยตรงในวิธีนั้น เป็นโบนัสอย่างน้อย JUnit และ TestNG จะรายงานความล้มเหลวที่แตกต่างกันสำหรับข้อผิดพลาดจาก@Before/ @Afterวิธีการดังนั้นจะเห็นได้ว่าปัญหาไม่ได้อยู่ในการทดสอบเอง
sleske

4

นี่คือวิธีที่ฉันใช้วิธี Fail

มีสามสถานะที่กรณีทดสอบของคุณสามารถจบลงได้

  1. ผ่าน: ฟังก์ชันภายใต้การทดสอบดำเนินการสำเร็จและส่งคืนข้อมูลตามที่คาดไว้
  2. ไม่ผ่าน: ฟังก์ชันภายใต้การทดสอบดำเนินการสำเร็จ แต่ข้อมูลที่ส่งกลับไม่เป็นไปตามที่คาดไว้
  3. ล้มเหลว: ฟังก์ชันไม่สามารถดำเนินการได้สำเร็จและไม่เป็นเช่นนั้น

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

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

ฉันใช้การดำเนินการที่ล้มเหลวสำหรับสถานการณ์ที่สาม

เช่น: public Integer add (จำนวนเต็ม a, Integer b) {return new Integer (a.intValue () + b.intValue ())}

  1. Passed Case: a = new Interger (1), b = new Integer (2) และฟังก์ชันที่ส่งคืน 3
  2. Not Passed Case: a = new Interger (1), b = new Integer (2) และฟังก์ชันที่ส่งคืนค่า soem อื่นที่ไม่ใช่ 3
  3. กรณีล้มเหลว: a = null, b = null และฟังก์ชันพ่น NullPointerException

1
ถ้าคุณดูที่รหัสที่มา JUnit fail()ของคุณจะเห็นว่ายืนยันการใช้งาน
Daniel C. Sobral

3

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

นี่อาจเป็นเพราะฉันไม่ทราบถึงฟังก์ชันการทำงานที่ไม่สมบูรณ์ () บางประเภทซึ่งมีอยู่ใน NUnit


2

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

ตัวอย่างเช่น:

final CountDownLatch latch = new CountDownLatch(1);

service.asyncCall(someParameter, new ResponseHandler<SomeType>() {
    @Override
    public void onSuccess(SomeType result) {
        assertNotNull(result);
        // Further test assertions on the result
        latch.countDown();
    }

    @Override
    public void onError(Exception e) {
        fail(exception.getMessage());
        latch.countDown();
    }
});

if ( !latch.await(5, TimeUnit.SECONDS) ) {
    fail("No response after 5s");
}

0

กรณีการใช้งานที่สำคัญที่สุดคือการตรวจสอบข้อยกเว้น

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

dao.insert(obj);
try {
  dao.insert(obj);
  fail("No DuplicateKeyException thrown.");
} catch (DuplicateKeyException e) {
  assertEquals("Error code doesn't match", 123, e.getErrorCode());
} finally {
  //cleanup
  dao.delete(obj);
}

ตามที่ระบุไว้ในความคิดเห็นอื่น. การมีการทดสอบล้มเหลวจนกว่าคุณจะสามารถนำไปใช้งานได้เสร็จสิ้นมันก็ฟังดูสมเหตุสมผลเช่นกัน

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