ละเว้นการทดสอบตามเงื่อนไขใน JUnit 4


365

ตกลงดังนั้น@Ignoreคำอธิบายประกอบจึงเหมาะสำหรับการทำเครื่องหมายว่าไม่ควรรันกรณีทดสอบ

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

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

หากใครเคยทำสิ่งที่คล้ายกันในอดีตหรือมีความคิดที่ชัดเจนว่าฉันจะทำสิ่งนี้ได้อย่างไรฉันยินดีที่จะรับฟัง

คำตอบ:


476

วิธี JUnit org.junit.Assumeคือการทำเช่นนี้ที่ใช้เวลาเป็น

 @Before
 public void beforeMethod() {
     org.junit.Assume.assumeTrue(someCondition());
     // rest of setup.
 }

คุณสามารถทำได้ใน@Beforeวิธีการหรือในการทดสอบตัวเอง แต่ไม่ได้อยู่ใน@Afterวิธีการ หากคุณทำมันในการทดสอบตัวเอง@Beforeวิธีการของคุณจะได้รับการเรียกใช้ คุณสามารถทำได้ภายใน@BeforeClassเพื่อป้องกันการเริ่มต้นคลาส

การสันนิษฐานล้มเหลวทำให้การทดสอบถูกเพิกเฉย

แก้ไข:เพื่อเปรียบเทียบกับ@RunIfบันทึกย่อจากjunit-extรหัสตัวอย่างจะมีลักษณะดังนี้:

@Test
public void calculateTotalSalary() {
    assumeThat(Database.connect(), is(notNull()));
    //test code below.
}

ไม่ต้องพูดถึงว่าการจับและใช้การเชื่อมต่อจากDatabase.connect()วิธีนี้ทำได้ง่ายกว่ามาก


1
@ notnoop นั่นไม่ใช่การสังเกตของฉันเลย พวกเขาจะถูกละเว้น นักวิ่งทดสอบ IDEA รายงานพวกเขาด้วยวิธีนั้นและดูซอร์สโค้ด JUnit แสดงว่ามันรายงานการทดสอบว่าถูกละเว้น
Yishai

1
ในการอ้างอิง: "ในอนาคตสิ่งนี้อาจเปลี่ยนแปลงได้และการสันนิษฐานที่ล้มเหลวอาจนำไปสู่การทดสอบที่ถูกเพิกเฉย" ในความเป็นจริงมันเปลี่ยนไปจาก 4.5 ฉันเชื่อว่า javadoc ปัจจุบันกล่าวว่า: "นักวิ่ง JUnit ที่เป็นค่าเริ่มต้นจะทำการทดสอบกับข้อผิดพลาดที่ไม่ได้รับการพิจารณาเนื่องจากนักวิ่งที่กำหนดเองอาจทำงานแตกต่างออกไป" github.com/KentBeck/junit/blob/…
Yishai

4
Eclipse 3.6 กับ Junit 4.8.1 รายงานข้อสันนิษฐานที่ผิดพลาดว่าเป็นการทดสอบผ่าน เหมือนกับมด 1.8.1
fijiaaron

8
Eclipse นั้นรายงานข้อสันนิษฐานที่ล้มเหลวขณะผ่านเป็นข้อบกพร่อง: bugs.eclipse.org/bugs/show_bug.cgi?id=359944
Martin

1
@JeffStorey แล้วคุณกำลังมองหาบางสิ่ง หนึ่งคือ@BeforeClassคำอธิบายประกอบที่คุณสามารถทำให้สมมติฐานของคุณล้มเหลวที่นั่นซึ่งจะข้ามชั้นเรียนทั้งหมด อีกอย่างคือ@ClassRule(สำหรับการควบคุมที่ละเอียดยิ่งขึ้น แต่เหนือคลาสทั้งหมดหนึ่งครั้ง)
Yishai

51

คุณควรชำระเงินJunit-extโครงการ พวกเขามีRunIfคำอธิบายประกอบที่ดำเนินการทดสอบตามเงื่อนไขเช่น:

@Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
    //your code there
}

class DatabaseIsConnected implements Checker {
   public boolean satisify() {
        return Database.connect() != null;
   }
}

[ตัวอย่างโค้ดที่นำมาจากบทช่วยสอนของพวกเขา]


3
ขอบคุณสำหรับคำตอบนี้ - ไวยากรณ์ทางเลือกที่น่าสนใจสำหรับฟังก์ชันการทำงานแม้ว่าฉันจะไปด้วยAssumeโดยตรงเพื่อไม่แนะนำการอ้างอิงอื่น
Andrzej Doyle

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

ฉันต้องการมันมากเพราะสิ่งนี้ช่วยในการทดสอบตามเงื่อนไขในเวลาทำงาน มันเหมาะกับการทดสอบจำนวนหน่วยกำลังจะทำงานและความต้องการคือการเรียกใช้การทดสอบหน่วยในการตรวจสอบโดยเฉพาะ ฉันประหลาดใจจริงๆที่เห็นว่า junit-ext ไม่สามารถใช้งานได้บนที่เก็บ Maven เราจะได้ประโยชน์อย่างไรในโครงการ maven
shambhu

4
คำอธิบายประกอบเช่น@RunIfแยกเงื่อนไขเมื่อการทดสอบควรเรียกใช้จากรหัสทดสอบจริงซึ่งฉันคิดว่าดี สิ่งที่ฉันไม่ชอบคือมันต้องใช้นักวิ่งทดสอบโดยเฉพาะ ดังนั้นฉันจึงเขียนกฎ JUnitเพื่อเพิกเฉยต่อการทดสอบอย่างตั้งใจ
Rüdiger Herrmann

2
หลังจากติดตั้งขวด junit-ext (ดูได้ที่นี่code.google.com/p/junit-ext/downloads/… ) ในที่เก็บข้อมูลในพื้นที่ของเราและใช้งาน @Run If หมายเหตุ ... ไม่มีอะไร! มันถูกเพิกเฉยโดยสิ้นเชิงและฉันคิดว่าเหตุผลอาจเป็นไปได้ว่า Junit-ext ดูเหมือนจะขึ้นอยู่กับ Junit 4.5 เราต้องการ 4.9+ เนื่องจากการทดสอบสปริง ดังนั้น ... ไม่เป็นไร
Marc

7

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

public class CustomRunner extends BlockJUnit4ClassRunner {
    public CTRunner(Class<?> klass) throws initializationError {
        super(klass);
    }

    @Override
    protected boolean isIgnored(FrameworkMethod child) {
        if(shouldIgnore()) {
            return true;
        }
        return super.isIgnored(child);
    }

    private boolean shouldIgnore(class) {
        /* some custom criteria */
    }
}

ขณะนี้ดูดีและสะอาด แต่จะไม่ทำงานกับเวอร์ชันปัจจุบันหาก JUnit4 เนื่องจากBlockJUnit4ClassRunnerไม่ได้เสนอisIgnoredวิธีการอีกต่อไป
เดฟ

-2

หมายเหตุอย่างรวดเร็ว: Assume.assumeTrue(condition)ละเว้นขั้นตอนที่เหลือ แต่ผ่านการทดสอบ หากต้องการทดสอบล้มเหลวให้ใช้org.junit.Assert.fail()ภายในคำสั่งแบบมีเงื่อนไข ทำงานเหมือนกันAssume.assumeTrue()แต่ไม่ผ่านการทดสอบ


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

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