JUnit4 विफल () यहाँ है, लेकिन पास () कहाँ है?


85

fail()JUnit4 लाइब्रेरी में एक विधि है। मुझे यह पसंद है, लेकिन एक pass()विधि की कमी का अनुभव करना जो पुस्तकालय में मौजूद नहीं है। ऐसा क्यों है?

मुझे पता चला है कि मैं assertTrue(true)इसके बजाय उपयोग कर सकता हूं, लेकिन फिर भी अनैतिक है।

@Test
 public void testSetterForeignWord(){
  try {
   card.setForeignWord("");
   fail();
  } catch (IncorrectArgumentForSetter ex){
  }

 // assertTrue(true);
 }

7
बस रिटर्न स्टेटमेंट का उपयोग करें - ज्यादातर मामलों में जो पास () के रूप में गुजरेंगे।
टॉपचेफ

@topchef उस एकल टिप्पणी ने सिर पर हथौड़ा मारा, जबकि हर कोई इस बारे में बहस करता है कि कौन सा स्वीकार्य है और कौन सा नहीं।

कुछ टेस्ट सिस्टम (पर्ल टेस्ट :: सिंपल) काउंट पास और फेल हुए दावे। जुनित, हालांकि, पास और असफल होने वाले परीक्षण विधियों की संख्या को गिनता है । इस प्रकार एक passविधि के लिए जुनित का समान उपयोग नहीं है ।
Randall Whitman

जवाबों:


65

जब तक परीक्षण एक अपवाद नहीं फेंकता, तब तक यह गुजरता है, जब तक कि आपका @Testएनोटेशन अपेक्षित अपवाद नहीं बताता है। मुझे लगता pass()है कि एक विशेष अपवाद को फेंक सकता है जो जुनाइट हमेशा पासिंग के रूप में व्याख्या करता है, इसलिए शॉर्ट सर्किट टेस्ट के रूप में, लेकिन यह परीक्षण के सामान्य डिजाइन के खिलाफ जाएगा (यानी सफलता मानें और केवल एक असफल होने पर विफल हो जाए) और, अगर मुझे मिल गया है यह विचार कि यह उपयोग करने के लिए बेहतर था pass(), यह गुजरने वाले परीक्षणों के एक बड़े सूट को धीमा कर देगा (अपवाद निर्माण के ओवरहेड के कारण)। असफल परीक्षण आदर्श नहीं होना चाहिए, इसलिए यह एक बड़ी बात नहीं है यदि उनके पास यह ओवरहेड है।

ध्यान दें कि आपका उदाहरण इस तरह से फिर से लिखा जा सकता है:

@Test(expected=IncorrectArgumentForSetter.class)
public void testSetterForeignWord("") throws Exception {
  card.setForeignWord("");
}

इसके अलावा, आपको मानक जावा अपवादों के उपयोग का पक्ष लेना चाहिए। आपका IncorrectArgumentForSetterशायद एक होना चाहिए IllegalArgumentException


4
असफल () विधि और assertX () विधियाँ वास्तव में केवल एक अभिक्रिया फेंकती हैं, जिससे परीक्षण विधि अस्पष्ट रूप से बाहर निकल जाती है। यही कारण है कि एक सफल रिटर्न सफलता को इंगित करता है ...
स्टीवन श्लांसकर

-1 - पास () विधि कुछ नहीं कर रही है - यह अपवादों के बिना तुरंत परीक्षण छोड़ने है। यह ज्यादातर मामलों में प्रभावी ढंग से विवरणी के बराबर होगा (अपेक्षित अपवादों को छोड़कर, टाइमआउट, आदि)।
टॉपचेफ

1
@grory: आप सही कह रहे हैं कि एक pass()विधि सिर्फ कुछ नहीं कर सकती है, ऐसा न हो कि परीक्षण के बाद उसे कॉल करने में विफल होना संभव हो। इसलिए मैंने वह वाक्य हटा दिया।
कॉलिनड

मैं आपको पर्याप्त धन्यवाद नहीं दे सकता, इससे मुझे बहुत निराशा हुई!
N00b Pr0grammer

71

returnकभी भी कॉल करें कि आपका परीक्षण समाप्त हो गया है और पास हो गया है।


3
+1 सही उत्तर रहा होगा (अपेक्षित समय, समय-समय पर अपवाद के साथ ज्यादातर मामलों में)
टॉपचेफ

वास्तव में एक परीक्षण को समाप्त करने का सबसे सरल और उपयोगी तरीका लगता है।
बेंज

7

मुझे लगता है कि इस प्रश्न को एक अद्यतन उत्तर की आवश्यकता है, क्योंकि यहाँ अधिकांश उत्तर काफी पुराने हैं।

सबसे पहले ओपी के सवाल:

मुझे लगता है कि इसकी बहुत अच्छी तरह से स्वीकार की गई है कि JUnit में "अपेक्षित अतिशयोक्ति" अवधारणा को पेश करना एक बुरा कदम था, क्योंकि उस अपवाद को कहीं भी उठाया जा सकता है, और यह परीक्षा पास करेगा। यह काम करता है यदि आपका फेंक (और पर जोर देकर) बहुत ही डोमेन विशिष्ट अपवाद हैं, लेकिन मैं केवल उन प्रकार के अपवादों को फेंक देता हूं जब मैं कोड पर काम कर रहा हूं जो बिल्कुल बेदाग होने की जरूरत है, - अधिकतम एपीआईएस केवल अपवादों में निर्मित IllegalArgumentExceptionया जैसे IllegalStateException। अगर दो कॉल करने से आपकी मेकिंग पॉजिटिवली इन अपवादों को फेंक सकती है, तो @ExpectedExceptionएनोटेशन आपके टेस्ट को ग्रीन-बार कर देगा भले ही इसकी गलत लाइन जो अपवाद को फेंके!

इस स्थिति के लिए मैंने एक वर्ग लिखा है जो मुझे यकीन है कि यहां कई अन्य लोगों ने लिखा है, यह एक assertThrowsविधि है:

public class Exceptions {
    private Exceptions(){}

    public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
        try{
            actionThatShouldThrow.run();
            fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
        }
        catch(Exception e){
            if ( ! expectedException.isInstance(e)) {
                throw e;
            }
        }
    }
}

यदि आप अपवाद को फेंक देते हैं, तो यह विधि केवल तभी वापस आती है, जब आप अपने परीक्षण में आगे की पुष्टि / सत्यापन कर सकते हैं।

जावा 8 सिंटैक्स के साथ आपका परीक्षण वास्तव में अच्छा लग रहा है। नीचे हमारे मॉडल पर सरल परीक्षणों में से एक है जो विधि का उपयोग करता है:

@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
    //setup
    AxisRange range = new AxisRange(0,100);

    //act
    Runnable act = () -> range.setLowerBound(200);

    //assert
    assertThrows(IllegalArgumentException.class, act);
}

ये परीक्षण थोड़े विस्मयकारी हैं क्योंकि "अधिनियम" कदम वास्तव में कोई कार्रवाई नहीं करता है, लेकिन मुझे लगता है कि अर्थ अभी भी काफी स्पष्ट है।

कैच-अपवाद नामक मावेन पर एक छोटा सा पुस्तकालय भी है जो इस बात को सत्यापित करने के लिए मॉकिटो-शैली सिंटैक्स का उपयोग करता है कि अपवादों को फेंक दिया जाए। यह बहुत अच्छा लग रहा है, लेकिन मैं गतिशील परदे के पीछे का प्रशंसक नहीं हूं। उस ने कहा, वहाँ वाक्यविन्यास इतना चालाक है कि वह लुभाता है:

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
// then: catch the exception if any is thrown 
catchException(myList).get(1);

// then: we expect an IndexOutOfBoundsException
assert caughtException() instanceof IndexOutOfBoundsException;

अंत में, इस स्थिति के लिए कि मैं इस धागे को प्राप्त करने के लिए भाग गया, परीक्षणों की अनदेखी करने का एक तरीका है अगर कुछ अनुमान मिलते हैं।

अभी मैं कुछ DLL प्राप्त करने पर काम कर रहा हूँ जिन्हें एक java देशी-लाइब्रेरी-लोडिंग-लाइब्रेरी के माध्यम से JNA कहा जाता है, लेकिन हमारा बिल्ड सर्वर ubuntu में है। मुझे JUnit परीक्षणों के साथ इस तरह के विकास को चलाने की कोशिश करना पसंद है - हालांकि, वे इस बिंदु पर "इकाइयों" से बहुत दूर हैं। यदि मैं एक स्थानीय मशीन पर हूं तो मैं परीक्षण करना चाहता हूं, लेकिन यदि हम जुबां पर हैं तो परीक्षण को अनदेखा करें। JUnit 4 में इसके लिए एक प्रावधान है, जिसे कहा जाता है Assume:

@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
    //this line will cause the test to be branded as "ignored" when "isCircleCI" 
    //(the machine running ubuntu is running this test) is true.
    Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
    //an ignored test will typically result in some qualifier being put on the results, 
    //but will also not typically prevent a green-ton most platforms. 

    //setup
    URL url = DLLTestFixture.class.getResource("USERDLL.dll");
    String path = url.toURI().getPath();
    path = path.substring(0, path.lastIndexOf("/"));

    //act
    NativeLibrary.addSearchPath("USERDLL", path);
    Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);

    //assert
    assertThat(dll).isNotNull();
}

जैसा कि आपने कहा "अधिनियम" कुछ विशिष्ट नहीं करता है, इसलिए हम अभी भी नहीं जानते हैं कि वास्तव में अपवाद को फेंकता है या नहीं, यह वह रेखा है जिसकी हम अपेक्षा कर रहे हैं या नहीं। इस मामले में, उदाहरण का परीक्षण और सत्यापन किया जाना काफी सरल है, लेकिन कल्पना करें कि आपके परीक्षण में उपयोगिता विधि शामिल है जो परिणाम वापस करने से पहले नेस्टेड विधियों का उपयोग करती है। जब तक आईडीई अपवाद साइट को इंगित नहीं करता है तब तक समस्या का स्रोत प्राप्त करने का कोई तरीका नहीं है
फरीद

4

मैं passJUnit के लिए भी विधि की तलाश कर रहा था , ताकि मैं कुछ परीक्षणों को शॉर्ट-सर्किट कर सकूं जो कुछ परिदृश्यों में लागू नहीं थे (शुद्ध इकाई परीक्षणों के बजाय एकीकरण परीक्षण हैं)। इतना बुरा भी नहीं है।

सौभाग्य से, सशर्त रूप से परीक्षण को अनदेखा करने का एक तरीका है, जो वास्तव में assumeTrueविधि का उपयोग करके मेरे मामले में और भी बेहतर बैठता है :

Assume.assumeTrue (isTestApplicable);

इसलिए यहाँ परीक्षण को तभी निष्पादित किया जाएगा जब TestApplicable सत्य है, अन्यथा परीक्षण को अनदेखा कर दिया जाएगा।


2

पास विधि की कोई आवश्यकता नहीं है क्योंकि जब कोई भी अभिकथन नहीं किया जाता है तो परीक्षण कोड से फेंक दिया जाता है जो यूनिट टेस्ट केस पास करेगा।

यदि वास्तव में उस बिंदु पर नियंत्रण आता है तो असफलता () विधि वास्तव में टेस्टकेस को विफल करने के लिए एक AssertionFailedException फेंकता है।


मुझे लगता है कि यह वास्तव में एक junit.framework.AssertionFailedError है।
काइल

त्रुटियों के मामलों के बारे में क्या। Iam तत्व को वेबड्राइवर से अपवाद नहीं दिखाई दे रहा है। क्या मैं अपवाद को पकड़ता हूं और वापस लौट आता हूं।
शशिकुमार

1

मुझे लगता है कि यह प्रश्न परीक्षण निष्पादन प्रक्रिया की थोड़ी गलतफहमी का परिणाम है। JUnit में (और अन्य परीक्षण उपकरण) परिणाम प्रति पद्धति से गिने जाते हैं, न कि मुखर कॉल के अनुसार। एक काउंटर नहीं है, जो ट्रैक करता है कि कितने पारित / असफल हुए assertXथे।

JUnit प्रत्येक परीक्षण विधि को अलग-अलग निष्पादित करता है। यदि विधि सफलतापूर्वक लौटती है, तो परीक्षण "पारित" के रूप में पंजीकृत है। यदि अपवाद होता है, तो परीक्षण "असफल" के रूप में पंजीकृत है। बाद के मामले में दो सबकेस संभव हैं: 1) एक जेयूनाइट अभिकथन अपवाद, 2) किसी अन्य प्रकार के अपवाद। स्थिति पहले मामले में "विफल" होगी, और दूसरे मामले में "त्रुटि"।

में Assert वर्ग कई आशुलिपि तरीकों अभिकथन अपवाद फेंकने के लिए तो उपलब्ध हैं। दूसरे शब्दों में, AssertJUnit के अपवादों पर एक अमूर्त परत है।

उदाहरण के लिए, यह GitHubassertEquals पर स्रोत कोड है :

/**
 * Asserts that two Strings are equal.
 */
static public void assertEquals(String message, String expected, String actual) {
    if (expected == null && actual == null) {
        return;
    }
    if (expected != null && expected.equals(actual)) {
        return;
    }
    String cleanMessage = message == null ? "" : message;
    throw new ComparisonFailure(cleanMessage, expected, actual);
}

जैसा कि आप देख सकते हैं, समानता के मामले में कुछ नहीं होता है, अन्यथा एक अतिशयोक्ति को फेंक दिया जाएगा।

इसलिए:

assertEqual("Oh!", "Some string", "Another string!");

बस एक ComparisonFailureअपवाद फेंकता है, जो JUnit द्वारा पकड़ा जाएगा, और

assertEqual("Oh?", "Same string", "Same string");

कुछ नहीं करता।

संक्षेप में, ऐसा कुछ pass()मतलब नहीं होगा, क्योंकि यह कुछ भी नहीं करता था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.