पहले और बाद में सुइट निष्पादन हुक jUnit 4.x में


84

मैं एकीकरण परीक्षणों के एक सेट के लिए सेटअप और टियरडाउन को सुधारने की कोशिश कर रहा हूं, परीक्षणों को निष्पादित करने के लिए junit 4.4 का उपयोग कर रहा हूं। आंसू को मज़बूती से चलाने की ज़रूरत है। मुझे TestNG के साथ अन्य समस्याएं हो रही हैं, इसलिए मैं वापस jUnit में पोर्ट करना चाह रहा हूं। किसी भी परीक्षण को चलाने से पहले निष्पादन के लिए कौन से हुक उपलब्ध हैं और सभी परीक्षण पूरे होने के बाद?

नोट: हम अपने निर्माण के लिए मावेन 2 का उपयोग कर रहे हैं। मैंने मावेन के pre-& post-integration-testचरणों का उपयोग करने की कोशिश की है, लेकिन, यदि कोई परीक्षण विफल हो जाता है, तो मावेन रुक जाता है और नहीं चलता है post-integration-test, जो कोई मदद नहीं है।


1
एकीकरण परीक्षणों के लिए आपको अचूक के बजाय मावेन-फ़ेलसेफ़-प्लगइन का उपयोग करना चाहिए । post-integration-testयदि परीक्षण विफल हो जाता है तो यह स्किप नहीं होगा । इस विकी पेज को भी देखें ।
क्रिस एच।

क्या आप कृपया अंतिम कार्यान्वयन साझा कर सकते हैं?
विक्रमवी

जवाबों:


113

हां, टेस्ट सूट में किसी भी परीक्षण से पहले और बाद में निर्धारित तरीके से सेट अप और फाड़ नीचे चलाने के लिए संभव है। मुझे कोड में प्रदर्शित करें:

package com.test;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
public class TestSuite {

    @BeforeClass
    public static void setUp() {
        System.out.println("setting up");
    }

    @AfterClass
    public static void tearDown() {
        System.out.println("tearing down");
    }

}

तो आपकी Test1कक्षा कुछ इस तरह दिखाई देगी:

package com.test;

import org.junit.Test;


public class Test1 {
    @Test
    public void test1() {
        System.out.println("test1");
    }

}

... और आप कल्पना कर सकते हैं कि Test2समान दिखता है। यदि आप भागते हैं TestSuite, तो आपको मिलेगा:

setting up
test1
test2
tearing down

तो आप देख सकते हैं कि सेट अप / आंसू नीचे क्रमशः सभी परीक्षणों से पहले और बाद में चलते हैं।

पकड़: यह केवल तभी काम करता है जब आप टेस्ट सूट चला रहे हों, और टेस्ट 1 और टेस्ट 2 को अलग-अलग JUnit परीक्षणों के रूप में नहीं चला रहे हों। आपने उल्लेख किया कि आप मावेन का उपयोग कर रहे हैं, और मावेन अचूक प्लगइन व्यक्तिगत रूप से परीक्षण चलाना पसंद करता है, और एक सूट का हिस्सा नहीं है। इस मामले में, मैं एक सुपरक्लास बनाने की सिफारिश करूंगा जो प्रत्येक टेस्ट क्लास तक फैले। सुपरक्लास में तब एनोटेट @BeforeClass और @AfterClass विधियाँ सम्‍मिलित होती हैं। हालांकि उपरोक्त विधि के रूप में काफी साफ नहीं है, मुझे लगता है कि यह आपके लिए काम करेगा।

असफल परीक्षणों के साथ समस्या के लिए, आप maven.test.error.ignore सेट कर सकते हैं ताकि बिल्ड विफल परीक्षणों पर जारी रहे। यह निरंतर अभ्यास के रूप में अनुशंसित नहीं है, लेकिन यह आपको तब तक कार्यशील होना चाहिए जब तक कि आपके सभी परीक्षण पास न हो जाएं। अधिक विवरण के लिए, मावेन अचूक दस्तावेज देखें


2
यह मेरे लिए पूरी तरह से काम करता था जब मैं मावेन-अचूक-प्लगइन में जाता था और इसमें एक सूची शामिल करता था जो उस सूट की ओर इशारा करता था जिसे मैं चलाना चाहता था।
झेरिको

2
4.8.2 JUnit के रूप में, यह पैरामीटर परीक्षण के साथ अच्छा नहीं खेलता है। सुइट का @BeforeClass तरीके परीक्षण के @ Parameterized.Parameters विधि के बाद चलाया जाएगा , जिससे सूट की स्थापना पर कोई निर्भरता न हो।
एएम

अपने आप के जवाब में, @ सिद्धांतों का उपयोग करते समय, @DataPoints विधि के लिए कॉल सुइट के @BeforeClass के बाद कॉल है ।
एएम

18
नेक्रो के लिए खेद है - लेकिन सुपर क्लास में फर्स्टक्लास / आफ्टरक्लास को जोड़ने से उम्मीद के मुताबिक काम नहीं होता है - प्रत्येक टेस्ट क्लास पूरा होने के बाद भी उन्हें बुलाया जाता है। यह पश्चाताप के लिए है।
सुबु शंकरा सुब्रमण्यन

3
क्या यह अभी भी एक मान्य दृष्टिकोण है? सुइटक्लास एनोटेशन में परीक्षण कक्षाओं की सूची को एन्यूमरेट करने की आवश्यकता से आप कैसे बचें?
बुरहान अली

33

मेरे एक सहयोगी ने निम्नलिखित सुझाव दिया: आप एक कस्टम RunListener का उपयोग कर सकते हैं और testRunFinished () विधि: http://junit.sourceforge.net/javadoc/org/junit/runner/notification-RunListener.html#testRunFinished(org लागू कर सकते हैं । junit.runner.Result)

RunListener को पंजीकृत करने के लिए बस अचूक प्लगइन को निम्नानुसार कॉन्फ़िगर करें: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html अनुभाग "कस्टम श्रोताओं और पत्रकारों का उपयोग करना"

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


5
+1 यह पहला प्रयोग करने योग्य समाधान है जो मैंने एक सूट वर्ग के बोझिल रखरखाव के बिना देखा है!
स्टेफन हैबर


7

एनोटेशन का उपयोग करते हुए, आप कुछ इस तरह से कर सकते हैं:

import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;

class SomethingUnitTest {
    @BeforeClass
    public static void runBeforeClass()
    {

    }

    @AfterClass
    public static void runAfterClass()
    {  

    }

    @Before  
    public void setUp()
    {

    }

    @After
    public void tearDown()
    {

    }

    @Test
    public void testSomethingOrOther()
    {

    }

}

4
सेटअप और फाड़ को चलाने के लिए एक बार निष्पादित किया जाना चाहिए। यह केवल तभी मदद करेगा जब सभी परीक्षण एक कक्षा में हों।
sblundy

3

यहाँ हम

  • JUnit 4.5 में अपग्रेड किया गया,
  • प्रत्येक परीक्षण वर्ग या विधि को टैग करने के लिए एनोटेशन लिखा है जिसमें एक काम करने वाली सेवा की आवश्यकता होती है,
  • प्रत्येक एनोटेशन के लिए हैंडलर लिखे, जिसमें सेवा के सेटअप और फाड़ को लागू करने के लिए स्थिर तरीके शामिल थे,
  • परीक्षण पर एनोटेशन का पता लगाने के लिए सामान्य धावक को बढ़ाया, स्थिर हैंडलर विधियों को परीक्षण निष्पादन श्रृंखला में उचित बिंदुओं पर जोड़ा।

2

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

आप इसके बजाय विफल-प्लगइन की कोशिश कर सकते हैं, मुझे लगता है कि सेटअप या मध्यवर्ती स्तर की स्थिति की परवाह किए बिना सफाई सुनिश्चित करने की सुविधा है


हां, फेलसेफ प्लगइन आपको विशिष्ट सेटअप और फाड़ निर्दिष्ट करने की अनुमति देगा। हालांकि मुझे नहीं लगता कि जिस समय यह प्रश्न पोस्ट किया गया था, उस समय फेलसेफ मौजूद था।
जेसन एक्सेलसन

2

बशर्ते कि आपके सभी परीक्षण एक "तकनीकी" वर्ग का विस्तार कर सकते हैं और एक ही पैकेज में हैं, तो आप थोड़ी चाल कर सकते हैं:

public class AbstractTest {
  private static int nbTests = listClassesIn(<package>).size();
  private static int curTest = 0;

  @BeforeClass
  public static void incCurTest() { curTest++; }

  @AfterClass
  public static void closeTestSuite() {
      if (curTest == nbTests) { /*cleaning*/ }             
  }
}

public class Test1 extends AbstractTest {
   @Test
   public void check() {}
}
public class Test2 extends AbstractTest {
   @Test
   public void check() {}
}

ज्ञात हो कि इस समाधान में बहुत सारी कमियां हैं:

  • पैकेज के सभी परीक्षणों को निष्पादित करना चाहिए
  • एक "टेचिंकल" वर्ग को उपवर्गित करना चाहिए
  • आप उप-वर्ग के अंदर @BeforeClass और @AfterClass का उपयोग नहीं कर सकते
  • यदि आप पैकेज में केवल एक परीक्षण निष्पादित करते हैं, तो सफाई नहीं की जाती है
  • ...

जानकारी के लिए: listClassesIn () => आप जावा में दिए गए वर्ग के सभी उपवर्गों को कैसे खोजते हैं ?


1
यह सच नहीं है जहाँ तक मेरे अपने परीक्षणों से पता चलता है। मेरे पास एक सुपर क्लास है जो beforeclass पर एक एम्बेडेड ग्लासफिश शुरू करता है और क्लास के बाद इसे बंद कर देता है। मेरे पास तब 2 कक्षाएं हैं जो उस सुपर क्लास से विस्तारित होती हैं। प्रत्येक कक्षा में परिभाषित परीक्षणों को चलाने से पहले beforeclass को निष्पादित किया जाता है।
जोनाथन मोरालेस वेलेज़

0

जहाँ तक मुझे पता है कि JUnit में ऐसा करने के लिए कोई तंत्र नहीं है, हालाँकि आप सुइट को उप-वर्ग करने और रन () विधि को एक संस्करण के साथ ओवरराइड करने की कोशिश कर सकते हैं जो हुक प्रदान करता है।


0

चूंकि maven-Surefire-plugin पहले सुइट क्लास नहीं चलाता है, लेकिन सुइट और टेस्ट क्लास को समान करता है, इसलिए हम केवल सुइट क्लास को सक्षम करने के लिए नीचे दिए गए प्लगइन को कॉन्फ़िगर कर सकते हैं और सभी परीक्षणों को अक्षम कर सकते हैं। सुइट सभी परीक्षण चलाएगा।

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <includes>
                    <include>**/*Suite.java</include>
                </includes>
                <excludes>
                    <exclude>**/*Test.java</exclude>
                    <exclude>**/*Tests.java</exclude>
                </excludes>
            </configuration>
        </plugin>

0

एक ही रास्ता मुझे लगता है कि तब आप चाहते हैं कि कार्यक्षमता प्राप्त करने के लिए कुछ ऐसा करना होगा

import junit.framework.Test;  
import junit.framework.TestResult;  
import junit.framework.TestSuite;  

public class AllTests {  
    public static Test suite() {  
        TestSuite suite = new TestSuite("TestEverything");  
        //$JUnit-BEGIN$  
        suite.addTestSuite(TestOne.class);  
        suite.addTestSuite(TestTwo.class);  
        suite.addTestSuite(TestThree.class);  
        //$JUnit-END$  
     }  

     public static void main(String[] args)  
     {  
        AllTests test = new AllTests();  
        Test testCase = test.suite();  
        TestResult result = new TestResult();  
        setUp();  
        testCase.run(result);  
        tearDown();  
     }  
     public void setUp() {}  
     public void tearDown() {}  
} 

मैं ग्रहण में कुछ इस तरह का उपयोग करता हूं, इसलिए मुझे यकीन नहीं है कि यह उस वातावरण के बाहर कितना पोर्टेबल है


3
यह JUnit3 के लिए एक उदाहरण है, और OP ने JUnit4 के लिए कहा है, लेकिन सिर्फ कुछ JUnit3 उपयोगकर्ताओं को यह सवाल लगता है ... JUnit3 के लिए, मुख्य () विधि से छुटकारा पाने के लिए बेहतर होगा और सूट () विधि है। TestSuite को junit.extensions.TestSetup के उपवर्ग में लपेटें। आपके IDE में व्यक्तिगत परीक्षण कक्षाओं को चलाने के बारे में जूली के उदाहरण के रूप में आपके पास अभी भी एक ही चेतावनी है।
नम्शुबिटराइटर

0

यदि आप एक सूट नहीं बनाना चाहते हैं और आपको अपने सभी परीक्षण वर्गों को सूचीबद्ध करना है, तो आप प्रतिबिंब का उपयोग गतिशील रूप से परीक्षण कक्षाओं की संख्या को खोजने के लिए कर सकते हैं और एक बेस क्लास @AfterClass में काउंट डाउन कर सकते हैं केवल एक बार आंसू बहाने के लिए:

public class BaseTestClass
{
    private static int testClassToRun = 0;

    // Counting the classes to run so that we can do the tear down only once
    static {
        try {
            Field field = ClassLoader.class.getDeclaredField("classes");
            field.setAccessible(true);

            @SuppressWarnings({ "unchecked", "rawtypes" })
            Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
            for (Class<?> clazz : classes) {
                if (clazz.getName().endsWith("Test")) {
                    testClassToRun++;
                }
            }
        } catch (Exception ignore) {
        }
    }

    // Setup that needs to be done only once
    static {
        // one time set up
    }

    @AfterClass
    public static void baseTearDown() throws Exception
    {
        if (--testClassToRun == 0) {
            // one time clean up
        }
    }
}

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

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

प्रेरणा इस SO उत्तर से आती है https://stackoverflow.com/a/37488620/5930242

यदि आप इस वर्ग को हर जगह विस्तारित नहीं करना चाहते हैं, तो यह अंतिम SO उत्तर वही हो सकता है जो आप चाहते हैं।

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