JUnit मुखर तरीके प्रदान क्यों नहीं करता है?


429

क्या किसी को पता है कि JUnit 4 प्रदान क्यों करता है assertEquals(foo,bar)लेकिन assertNotEqual(foo,bar)विधियाँ नहीं ?

यह assertNotSame(इसी assertSame) और assertFalse(इसी ) प्रदान करता है assertTrue, तो यह अजीब लगता है कि वे सहित परेशान नहीं किया था assertNotEqual

वैसे, मुझे पता है कि JUnit-addons उन तरीकों को प्रदान करता है जिनकी मुझे तलाश है। मैं सिर्फ जिज्ञासा से बाहर पूछ रहा हूं।


कम से कम JUnit 4.12 के बाद से, AssertNotEquals प्रदान किया जाता है। junit.org/junit4/javadoc/4.12/org/junit/…
WebF0x

जवाबों:


403

मेरा सुझाव है कि आप नई assertThat()शैली की अभिकल्पनाओं का उपयोग करें , जो आसानी से सभी प्रकार के नकारों का वर्णन कर सकते हैं और स्वचालित रूप से आपके द्वारा अपेक्षित की गई जानकारी का निर्माण कर सकते हैं और यदि आपने दावा किया तो आपको क्या मिला:

assertThat(objectUnderTest, is(not(someOtherObject)));
assertThat(objectUnderTest, not(someOtherObject));
assertThat(objectUnderTest, not(equalTo(someOtherObject)));

सभी तीन विकल्प समतुल्य हैं, वह चुनें जिसे आप सबसे अधिक पठनीय पाते हैं।

विधियों के सरल नामों का उपयोग करने के लिए (और इस तनाव सिंटैक्स को काम करने की अनुमति दें), आपको इन आयातों की आवश्यकता है:

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

134
मैं वैकल्पिक ऐसेट सिंटैक्स के लिए पॉइंटर की सराहना करता हूं, लेकिन कहीं और इशारा करते हुए जवाब नहीं देता कि जेनेट ने कभी क्यों नहीं प्रदान किया assertNotEquals()
seh

14
@seh: जिस तरह से मैंने इसे पढ़ा है वह प्रश्न ऐतिहासिक रुचि के बारे में नहीं था, बल्कि एक JUnit परीक्षा में "ये दो वस्तुएं समान नहीं हैं" के जोर देने के तरीके के बारे में था। मैंने जवाब दिया कि। "ऐसा क्यों है / क्या था / नहीं assertNotEqual" को ध्यान में रखते हुए, मैं कहूंगा कि यह एक विशेष शोधार्थी है जिसकी आवश्यकता उतनी बार नहीं है assertEqualsऔर इसलिए इसे सामान्य के माध्यम से व्यक्त किया जाएगा assertFalse
जोकिम सॉयर

21
"वह चुनें जिसे आप सबसे अधिक पठनीय पाते हैं"। यूनिट टेस्ट को पढ़ने और लिखने वाले लोग प्रोग्रामर होते हैं। क्या वे वास्तव में assertNotEqual (objectUnderTest, someOtherObject) या assertFalse (objectUnderTest.equals (someOtherObject)) की तुलना में इसे अधिक पठनीय पाते हैं? मैं फैंसी मिलानक एपीआई से आश्वस्त नहीं हूं - प्रोग्रामर के लिए यह पता लगाना / उनका उपयोग करना कैसे संभव है, यह काफी कठिन प्रतीत होता है ...
Bacar

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

5
@ जोचिम मैं सहमत हूं कि assertThatतुलना में अधिक अभिव्यंजक है assert*, लेकिन मुझे नहीं लगता कि यह जावा अभिव्यक्ति की तुलना में अधिक अभिव्यंजक है जिसे आप assert*सामान्य रूप से अभिव्यक्ति के अंदर और बाहर डाल सकते हैं (आखिरकार मैं जावा कोड में कुछ भी व्यक्त कर सकता हूं)। यह एक सामान्य समस्या है जो मैंने धाराप्रवाह शैली एपीआई के साथ शुरू की है - हर एक मूल रूप से एक नया डीएसएल है जिसे आपको सीखना होगा (जब हम सभी पहले से ही जावा को जानते हैं!)। मुझे लगता है कि Hamcrest अब सर्वव्यापी है कि लोगों को यह जानने की उम्मीद करना उचित है, हालांकि। मेरे पास एक नाटक होगा ...
बकार

154

assertNotEqualsJUnit 4.11 में एक है: https://github.com/junit-team/junit/blob/master/doc/ReleaseNotes4.11.md#improvements-to-assert-and-assume

import static org.junit.Assert.assertNotEquals;

1
मन, jmock में से एक (2.6.0) मावेन आर्टिफैक्ट्स ने जूनिट-डिप का एक पुराना संस्करण लीक किया है जिसमें बदले में एस्टर-क्लास के बिना एक एस्टर-क्लास है। आइवी का उपयोग करते समय बेहतर बाहर।
gkephorus

7
मैं 4.12 का उपयोग कर रहा हूं, लेकिन अभी भी assertNotEqual को खोजने में सक्षम नहीं हूं। : s
मुबाशर

49

मुझे आश्चर्य है। Assert का एपीआई बहुत सममित नहीं है; परीक्षण के लिए कि क्या वस्तुएं समान हैं, यह प्रदान करता है assertSameऔर assertNotSame

बेशक, यह लिखने के लिए बहुत लंबा नहीं है:

assertFalse(foo.equals(bar));

इस तरह के दावे के साथ, आउटपुट का एकमात्र जानकारीपूर्ण हिस्सा दुर्भाग्य से परीक्षण विधि का नाम है, इसलिए वर्णनात्मक संदेश अलग से बनाया जाना चाहिए:

String msg = "Expected <" + foo + "> to be unequal to <" + bar +">";
assertFalse(msg, foo.equals(bar));

यह निश्चित रूप से इतना थकाऊ है, कि अपना खुद का रोल करना बेहतर है assertNotEqual। सौभाग्य से भविष्य में यह शायद JUnit का हिस्सा होगा: JUnit मुद्दा 22


19
लेकिन यह कम उपयोगी है, क्योंकि JUnit आपको यह बताने में एक सहायक विफलता संदेश उत्पन्न नहीं कर सकता है, उदाहरण के लिए, फू और बार के असमान मूल्य। वास्तविक विफलता का कारण छिपा है और एक साधारण बूलियन में बदल गया है।
बेन जेम्स

3
मैं पूरी तरह सहमत हूँ। विशेष रूप से assertFalse को वास्तव में क्या गलत हुआ यह बताने के लिए आउटपुट का उत्पादन करने के लिए उचित संदेश तर्क की आवश्यकता है।
मिको मूनु

मुझे लगता है कि यह पाठ वर्तमान परीक्षणों के लिए उपयोगी है। Thnx
Marouane Gazanayi

पाठ के साथ समस्या यह है कि कोड विकसित होते ही यह पुराना हो जाएगा।
मार्क लेविसन

13

मैं तर्क दूंगा कि assertNotEqual की अनुपस्थिति वास्तव में एक विषमता है और JUnit को थोड़ा कम सीखने योग्य बनाता है। ध्यान रखें कि यह एक साफ मामला है जब एक विधि जोड़ने से एपीआई की जटिलता कम हो जाएगी, कम से कम मेरे लिए: समरूपता बड़े स्थान पर शासन करने में मदद करती है। मेरा अनुमान है कि चूक का कारण यह हो सकता है कि विधि के लिए बहुत कम लोग बुला रहे हैं। फिर भी, मुझे एक ऐसा समय याद है जब मुखरता भी मौजूद नहीं थी; इसलिए, मुझे एक सकारात्मक उम्मीद है कि विधि को अंततः जोड़ा जा सकता है, यह देखते हुए कि यह एक मुश्किल नहीं है; हालांकि मैं स्वीकार करता हूं कि कई कामगार हैं, यहां तक ​​कि सुरुचिपूर्ण भी हैं।


7

मैं इस पार्टी में बहुत देर से आ रहा हूं लेकिन मैंने पाया है कि फॉर्म:

static void assertTrue(java.lang.String message, boolean condition) 

अधिकांश 'बराबर नहीं' मामलों के लिए काम करने के लिए बनाया जा सकता है।

int status = doSomething() ; // expected to return 123
assertTrue("doSomething() returned unexpected status", status != 123 ) ;

4
हालांकि यह काम करता है, समस्या यह है कि यदि अभिकथन विफल हो जाता है, तो यह बस "एक्सपेक्टेड ट्रू, लेकिन गलत था" या कुछ अन्य अस्पष्ट कथन कहेगा। क्या होगा अगर यह अपेक्षित नहीं था 123, लेकिन 123 था।
चुपके रब्बी

6

मैं jUnit4.12 का उपयोग करते हुए, java 8 पर्यावरण में JUnit पर काम कर रहा हूं

मेरे लिए: कंपाइलर विधि का उपयोग करने में सक्षम नहीं था, तब भी जब मैंने उपयोग किया था
import org.junit.Assert;

इसलिए मैं बदल
assertNotEquals("addb", string);
गया
Assert.assertNotEquals("addb", string);

इसलिए यदि आप assertNotEqualमान्यता प्राप्त नहीं होने के बारे में समस्या का सामना कर रहे हैं , तो इसे बदलकर Assert.assertNotEquals(,);अपनी समस्या को हल करना चाहिए


1
ऐसा इसलिए है क्योंकि विधियां स्थिर हैं, और आपको उन्हें सांख्यिकीय रूप से आयात करना होगा। इसका उपयोग करें import static org.junit.Assert.*;और आप वर्ग नाम के बिना सभी आवेषण का उपयोग करने में सक्षम होंगे।
टॉम स्टोन

3

स्पष्ट कारण है कि लोग मुखर करना चाहते थे () बिल्डरों की तुलना किए बिना उन्हें पूर्ण विकसित वस्तुओं में बदलना था:

क्रिया उदाहरण:

....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....

बनाम

assertNotEqual(1, winningBidderId);

अफसोस की बात है कि ग्रहण में डिफ़ॉल्ट रूप से JUnit 4.11 शामिल नहीं है।

मुझे नहीं लगता कि '1' को एक Integer.valueOf () में लपेटा जाना चाहिए, लेकिन जब से मैं .NET से वापस लौटा हूं, मेरी शुद्धता पर भरोसा नहीं करता।


1

यह बेहतर है कि एस्कॉर्टफ़ल के बजाय हैमरेस्ट का इस्तेमाल नकारात्मक अभिक्रियाओं के लिए किया जाए क्योंकि पूर्व की रिपोर्ट में यह दावा विफलता के लिए एक अंतर दिखाएगा।

यदि आप मुखर का उपयोग करते हैं, तो आपको रिपोर्ट में केवल मुखर विफलता मिलती है। असफलता के कारण पर खोई जानकारी।


1

आमतौर पर मैं ऐसा तब करता हूं जब मुझे दो वस्तुओं के बराबर होने की उम्मीद होती है:

assertTrue(obj1.equals(obj2));

तथा:

assertFalse(obj1.equals(obj2));

जब उन्हें असमान होने की उम्मीद है। मुझे पता है कि यह आपके सवाल का जवाब नहीं है, लेकिन यह सबसे करीब है जो मुझे मिल सकता है। यह दूसरों की खोज में मदद कर सकता है कि वे JUnit संस्करणों में JUnit 4.11 से पहले क्या कर सकते हैं।


0

मैं ओपी के दृष्टिकोण से पूरी तरह सहमत हूं। Assert.assertFalse(expected.equals(actual))एक असमानता को व्यक्त करने का स्वाभाविक तरीका नहीं है।
लेकिन मैं तर्क दूंगा कि आगे से Assert.assertEquals(), Assert.assertNotEquals()काम करता है , लेकिन दस्तावेज़ के लिए उपयोगकर्ता के अनुकूल नहीं है कि परीक्षा वास्तव में क्या कहती है और यह समझने / बहस करने में विफल हो जाती है कि क्या है।
तो हाँ JUnit 4.11 और JUnit 5 प्रदान करता है Assert.assertNotEquals()( Assertions.assertNotEquals()JUnit 5 में), लेकिन मैं वास्तव में उनका उपयोग करने से बचता हूँ।

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

यहाँ एक उदाहरण है।
मान लीजिए कि मेरे पास एक एनिमल क्लास है, जिसे मैं createWithNewNameAndAge()विधि, एक ऐसी विधि का परीक्षण करना चाहता हूं , जो अपना नाम और अपनी उम्र को बदलकर, लेकिन अपना पसंदीदा भोजन रखकर एक नया एनिमल ऑब्जेक्ट बनाता है।
मान लीजिए कि मैं Assert.assertNotEquals()यह दावा करने के लिए उपयोग करता हूं कि मूल और नई वस्तुएं अलग-अलग हैं।
यहाँ एक त्रुटिपूर्ण कार्यान्वयन के साथ पशु वर्ग है createWithNewNameAndAge():

public class Animal {

    private String name;
    private int age;
    private String favoriteFood;

    public Animal(String name, int age, String favoriteFood) {
        this.name = name;
        this.age = age;
        this.favoriteFood = favoriteFood;
    }

    // Flawed implementation : use this.name and this.age to create the 
    // new Animal instead of using the name and age parameters
    public Animal createWithNewNameAndAge(String name, int age) {
        return new Animal(this.name, this.age, this.favoriteFood);
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getFavoriteFood() {
        return favoriteFood;
    }

    @Override
    public String toString() {
        return "Animal [name=" + name + ", age=" + age + ", favoriteFood=" + favoriteFood + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((favoriteFood == null) ? 0 : favoriteFood.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Animal)) return false;

        Animal other = (Animal) obj;
        return age == other.age && favoriteFood.equals(other.favoriteFood) &&
                name.equals(other.name);
    }

}

JUnit 4.11+ (या JUnit 5) दोनों परीक्षण धावक और जोर उपकरण के रूप में

@Test
void assertListNotEquals_JUnit_way() {
    Animal scoubi = new Animal("scoubi", 10, "hay");
    Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
    Assert.assertNotEquals(scoubi, littleScoubi);
}

परीक्षण उम्मीद के अनुसार विफल रहता है लेकिन डेवलपर को प्रदान किया गया कारण वास्तव में मददगार नहीं है। यह सिर्फ यह कहता है कि मान अलग-अलग होने चाहिए और toString()वास्तविक Animalपैरामीटर पर लागू परिणाम का उत्पादन करना चाहिए :

java.lang.AssertionError: मान भिन्न होना चाहिए। वास्तविक: पशु

[नाम = स्कौबी, आयु = १०, पसंदीदा = घास]

org.junit.Assert.fail (Assert.java:88) पर

ठीक है वस्तुओं के बराबर नहीं हैं। लेकिन समस्या कहां है?
परीक्षण विधि में किस क्षेत्र का सही मान नहीं है? एक ? दो ? उन सभी को ?
इसे खोजने के लिए आपको createWithNewNameAndAge() कार्यान्वयन में खुदाई करनी होगी / डिबगर का उपयोग करना होगा, जबकि परीक्षण एपीआई बहुत अधिक अनुकूल होगा यदि यह हमारे लिए वह अंतर बनाएगा जिसकी अपेक्षा की जाती है और जो प्राप्त होता है।


परीक्षण धावक के रूप में JUnit 4.11 और जोर उपकरण के रूप में एक परीक्षण मिलान एपीआई

यहाँ परीक्षण का एक ही परिदृश्य है, लेकिन जो Animalराज्य के दावे को बनाने के लिए AssertJ (एक उत्कृष्ट परीक्षण माचिस API) का उपयोग करता है :

import org.assertj.core.api.Assertions;

@Test
void assertListNotEquals_AssertJ() {
    Animal scoubi = new Animal("scoubi", 10, "hay");
    Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
    Assertions.assertThat(littleScoubi)
              .extracting(Animal::getName, Animal::getAge, Animal::getFavoriteFood)
              .containsExactly("little scoubi", 1, "hay");
}

बेशक परीक्षण अभी भी विफल है लेकिन इस बार कारण स्पष्ट रूप से कहा गया है:

java.lang.AssertionError:

उम्मीद:

<["स्कौबी", 10, "हाय"]>

सम्‍मिलित करने के लिए (और उसी क्रम में):

<["थोड़ा स्कौबी", 1, "हाय"]>

लेकिन कुछ तत्व नहीं मिले:

<["थोड़ा स्कौबी", 1]>

और दूसरों से अपेक्षित नहीं थे:

<["स्कौबी", 10]>

junit5.MyTest.assertListNotEquals_AssertJ (MyTest.jpg:26) पर

हम पढ़ सकते हैं कि Animal::getName, Animal::getAge, Animal::getFavoriteFoodलौटे हुए जानवरों के मूल्यों के लिए, हम इन मानों की अपेक्षा करते हैं:

"little scoubi", 1, "hay" 

लेकिन हमारे पास ये मूल्य हैं:

"scoubi", 10, "hay"

इसलिए हम जानते हैं कि कहां जांच की जाती है: nameऔर ageसही ढंग से मूल्यवान नहीं हैं। इसके अतिरिक्त, रिटर्न के अधिक सूक्ष्मता के लिए भी अनुमति hayके दावे में मूल्य निर्दिष्ट करने का तथ्य । हम चाहते हैं कि वस्तुएं कुछ गुणों के लिए समान न हों लेकिन जरूरी नहीं कि वे हर गुणों के लिए हों। तो निश्चित रूप से, माचिस एपीआई का उपयोग करना अधिक स्पष्ट और लचीला है।Animal::getFavoriteFood()Animal


-1

मोडुलो एपीआई स्थिरता, जो यूनीट ने प्रदान नहीं assertNotEquals()की वही कारण है कि जेयूनीट ने कभी इस तरह के तरीके प्रदान नहीं किए

  • assertStringMatchesTheRegex(regex, str) बनाम assertStringDoesntMatchTheRegex(regex, str)
  • assertStringBeginsWith(prefix, str) बनाम assertStringDoesntBeginWith(prefix, str)

यानी आपके मुखर तर्क में उन चीजों के प्रकारों के लिए एक विशिष्ट अभिकथन विधियाँ प्रदान करने का कोई अंत नहीं है!

अभी तक बेहतर की तरह composable परीक्षण पुरातन प्रदान करने के लिए equalTo(...), is(...), not(...), regex(...)और प्रोग्रामर टुकड़ा उन एक साथ के बजाय अधिक पठनीयता और विवेक के लिए करते हैं।


3
ठीक है, किसी कारण से, जोर () मौजूद है। यह नहीं था, लेकिन यह करता है। यह सवाल समरूपता की कमी के बारे में था - क्यों मुखर मौजूद है लेकिन इसके समकक्ष नहीं है?
foo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.