बार-बार एक ही जूनट टेस्ट चलाने का आसान तरीका?


121

जैसे शीर्षक कहता है, मैं JUnit 4.x परीक्षण चलाने के लिए कुछ सरल तरीके की तलाश कर रहा हूं ताकि एक पंक्ति में कई बार स्वचालित रूप से ग्रहण का उपयोग किया जा सके।

एक उदाहरण 10 बार एक ही परीक्षण चला रहा होगा और परिणाम की रिपोर्ट करेगा।

हमारे पास पहले से ही ऐसा करने का एक जटिल तरीका है लेकिन मैं इसे करने का एक सरल तरीका ढूंढ रहा हूं ताकि मैं यह सुनिश्चित कर सकूं कि जिस फ्लैकी टेस्ट को मैं तय करने की कोशिश कर रहा हूं।

एक आदर्श समाधान एक ग्रहण प्लगइन / सेटिंग / सुविधा होगी जिससे मैं अनजान हूं।


5
मैं बहुत उत्सुक हूं कि आप ऐसा क्यों करना चाहते हैं।
Buhb

मैं एक बड़ा ब्लैक बॉक्स टेस्ट चला रहा हूं, एक छोटा सा बदलाव किया है और यह देखना चाहता हूं कि इस पहले से भड़कीले टेस्ट की स्थिरता कैसे प्रभावित हुई।
स्टीफन थिएबर्ग

यह वास्तव में है, सिवाय इसके कि आप इसे असफलता तक चलाना चाहते हैं, जबकि मैं सिर्फ इसे कई बार चलाना चाहता हूं, जो आपको मिलने वाले उत्तरों को प्रभावित कर सकता है।
स्टीफन थ्यबर्ग

4
क्या आप TestNG के खिलाफ हैं क्योंकि यदि नहीं तो आप बस @Test (invocationCount = 10) का उपयोग कर सकते हैं और वह सब कुछ है।
रॉबर्ट मासैओली

1
मैं "टेस्टएनजी" के खिलाफ नहीं था, हम उस परियोजना में इसका उपयोग नहीं कर रहे थे।
स्टीफन थ्यबर्ग

जवाबों:


123

ऐसा करने के लिए सबसे आसान (नए कोड की कम से कम राशि के रूप में) तरीका यह है कि परीक्षण को पैरामीट्रिज्ड टेस्ट के रूप में चलाया जाए ( @RunWith(Parameterized.class)10 खाली मापदंडों को प्रदान करने के लिए एक विधि और जोड़ें)। इस तरह रूपरेखा 10 बार परीक्षण चलाएगी।

इस परीक्षण को कक्षा में एकमात्र परीक्षण करने की आवश्यकता होगी, या बेहतर परीक्षण के सभी तरीकों को कक्षा में 10 बार चलाने की आवश्यकता होनी चाहिए।

यहाँ एक उदाहरण है:

@RunWith(Parameterized.class)
public class RunTenTimes {

    @Parameterized.Parameters
    public static Object[][] data() {
        return new Object[10][0];
    }

    public RunTenTimes() {
    }

    @Test
    public void runsTenTimes() {
        System.out.println("run");
    }
}

उपरोक्त के साथ, यह एक पैरामीटर-कम कंस्ट्रक्टर के साथ भी करना संभव है, लेकिन मुझे यकीन नहीं है कि फ्रेमवर्क लेखकों का इरादा है, या यदि भविष्य में टूट जाएगा।

यदि आप अपने स्वयं के धावक को लागू कर रहे हैं, तो आप धावक को 10 बार परीक्षण चला सकते हैं। यदि आप तीसरे पक्ष के धावक का उपयोग कर रहे हैं, तो 4.7 के साथ, आप नए @Ruleएनोटेशन का उपयोग कर सकते हैं और MethodRuleइंटरफ़ेस को लागू कर सकते हैं ताकि यह स्टेटमेंट ले और इसे लूप के लिए 10 बार निष्पादित करें। इस दृष्टिकोण का नुकसान यह है कि वर्तमान है @Beforeऔर @Afterकेवल एक बार चलाने मिलता है। यह संभवत: JUnit के अगले संस्करण में बदल जाएगा ( @Beforeबाद में चलेगा @Rule), लेकिन इसकी परवाह किए बिना आप ऑब्जेक्ट के एक ही उदाहरण पर काम करेंगे (कुछ ऐसा जो Parameterizedरनर का सच नहीं है )। यह मानता है कि आप जो भी धावक वर्ग को सही ढंग से चला रहे हैं वह @Ruleएनोटेशन को पहचानता है । यह केवल मामला है अगर यह JUnit धावकों को सौंप रहा है।

यदि आप एक कस्टम धावक के साथ चल रहे हैं जो @Ruleएनोटेशन को नहीं पहचानता है , तो आप वास्तव में अपना रनर लिखने के लिए अटक गए हैं जो कि रनर को उचित रूप से दर्शाता है और इसे 10 बार चलाता है।

ध्यान दें कि संभावित रूप से इसे हल करने के अन्य तरीके हैं (जैसे कि सिद्धांत धावक) लेकिन उन सभी को एक धावक की आवश्यकता होती है। दुर्भाग्य से JUnit वर्तमान में धावकों की परतों का समर्थन नहीं करता है। यह एक धावक है जो अन्य धावकों को जंजीर देता है।


2
दुर्भाग्य से मैं पहले से ही एक अन्य धावक के साथ @ रनवे चल रहा हूं, लेकिन अन्यथा यह एक आदर्श समाधान होता।
स्टीफन थ्यबर्ग

हां, यह वह उपाय है जो मैं हालांकि करना चाहूंगा और जो ज्यादातर लोगों के लिए सबसे अच्छा होगा इसलिए मैं आगे जाऊंगा और जवाब स्वीकार करूंगा।
स्टीफन थिएबर्ग

एक वैकल्पिक और संभवतः कम
हैसी

अच्छा समाधान! मुझे एक अपवाद मिला, जिसमें कहा गया था कि डेटा विधि को एक निष्क्रिय सारणी वापस करनी चाहिए। मैंने इसे अपने अनुसार तय किया: @ Parameterized.Parameters public static Iterable <Object []> data () {रिटर्न Arrays.asList (नई वस्तु [20] [0]); }
नाद्रे 9'18

1
क्या आप JUnit 5 के लिए इस उत्तर से लिंक कर सकते हैं ? यह अनुरोधित विशेषता का वर्णन करता है जिसे JUnit 5
Marcono1234

100

IntelliJ के साथ, आप परीक्षण कॉन्फ़िगरेशन से ऐसा कर सकते हैं। एक बार जब आप इस विंडो को खोलते हैं, तो आप जितनी भी बार चाहें परीक्षण चलाने के लिए चुन सकते हैं,।

यहाँ छवि विवरण दर्ज करें

जब आप परीक्षण चलाते हैं, तो intellij आपके द्वारा निर्दिष्ट समय की संख्या के लिए चुने गए सभी परीक्षणों को निष्पादित करेगा।

उदाहरण के 6 बार परीक्षण 10 बार चल रहे हैं: यहाँ छवि विवरण दर्ज करें


4
यह सही है, अब अगर आप इसे करने के एक ग्रहण के तरीके की ओर इशारा कर सकते हैं, तो यह ओपी के सवाल का जवाब देगा
खल

वास्तविक तर्क या आवश्यकताओं की मेजबानी करने के लिए एक विशिष्ट उपकरण पर भरोसा करना एक विरोधी पैटर्न है।
मिकेल

1
@ मिकेल एक परीक्षण को दोहराता है एन बार आमतौर पर परीक्षण की आवश्यकता नहीं होती है। वास्तव में परीक्षणों को नियतात्मक होना चाहिए, ताकि कितनी बार दोहराया जाए, यह हमेशा एक ही परिणाम उत्पन्न करना चाहिए। क्या आप उस विरोधी पैटर्न की व्याख्या कर सकते हैं जिसे आप बोलते हैं?
smac89

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

68

मैंने पाया है कि स्प्रिंग का रिपीट एनोटेशन उस तरह की चीज के लिए उपयोगी है:

@Repeat(value = 10)

नवीनतम (स्प्रिंग फ्रेमवर्क 4.3.11। कृपया एपीआई) डॉक्टर:


46
टेस्ट फ्रेमवर्क बदलना ऐसा नहीं है जिसे मैं करने का एक आसान तरीका कहूंगा।
स्टीफन थ्यबर्ग

3
आपको अपने परीक्षण ढांचे को बदलने की आवश्यकता नहीं है - यह JUnit के साथ ठीक काम करता है। मुख्य दोष यह है कि JUnit अभी भी इसे एकल परीक्षण के रूप में देखता है। तो पहली बार यह टूट जाता है, निष्पादन बंद हो जाएगा। हालांकि, यदि आप पहले से ही वसंत का उपयोग नहीं कर रहे हैं, तो यह संभवतः वह तरीका नहीं है जो आप जाना चाहते हैं ...
tveon

मेरे लिए (स्प्रिंग 4.3.6 स्प्रिंग बूट 1.5.1 के माध्यम से 4.3.6) काम करने के लिए प्रतीत नहीं होता है
डेविड टोनहोफर

वसंत बूट 2.1.6 और
jo-

वसंत बूट के साथ पूरी तरह से काम करता है। @ वसंत (स्प्रिंगरनर :: वर्ग) जोड़ने के लिए मत भूलना, पोस्टर की 'वसंत में इकाई परीक्षण' लिंक के अनुसार!
अगोस्तन होरवथ

33

निम्नलिखित संसाधनों से प्रेरित:

उदाहरण

एक @Repeatएनोटेशन बनाएं और उसका उपयोग करें :

public class MyTestClass {

    @Rule
    public RepeatRule repeatRule = new RepeatRule();

    @Test
    @Repeat(10)
    public void testMyCode() {
        //your test code goes here
    }
}

Repeat.java

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention( RetentionPolicy.RUNTIME )
@Target({ METHOD, ANNOTATION_TYPE })
public @interface Repeat {
    int value() default 1;
}

RepeatRule.java

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class RepeatRule implements TestRule {

    private static class RepeatStatement extends Statement {
        private final Statement statement;
        private final int repeat;    

        public RepeatStatement(Statement statement, int repeat) {
            this.statement = statement;
            this.repeat = repeat;
        }

        @Override
        public void evaluate() throws Throwable {
            for (int i = 0; i < repeat; i++) {
                statement.evaluate();
            }
        }

    }

    @Override
    public Statement apply(Statement statement, Description description) {
        Statement result = statement;
        Repeat repeat = description.getAnnotation(Repeat.class);
        if (repeat != null) {
            int times = repeat.value();
            result = new RepeatStatement(statement, times);
        }
        return result;
    }
}

PowerMock

इसके साथ इस समाधान का उपयोग करते हुए @RunWith(PowerMockRunner.class), पावरमॉक 1.6.5 (जिसमें एक पैच शामिल है ) को अपडेट करने की आवश्यकता होती है ।


हाँ। आप परीक्षणों को कैसे निष्पादित कर रहे हैं?
आर। ओस्टरहॉल्ट

मैं स्वयं ग्रहण का उपयोग नहीं कर रहा हूँ। हो सकता है कि आप एक जूनियर 4 टेस्ट रनर का उपयोग नहीं कर रहे हों? (देखें doc "एक परीक्षण विन्यास को अनुकूलित करना" )
R. Oosterholt

29

JUnit 5 के साथ मैं @RepeatedTest एनोटेशन का उपयोग करके इसे हल करने में सक्षम था :

@RepeatedTest(10)
public void testMyCode() {
    //your test code goes here
}

ध्यान दें कि @Testएनोटेशन का उपयोग नहीं किया जाना चाहिए @RepeatedTest


बहुत आशाजनक लगता है, बस ध्यान दें कि अभी तक कोई रिलीज़ संस्करण नहीं है।
9ilsdx 9rvj 0lo

1
JUnit 5 ने GA को कुछ हफ़्ते पहले हिट किया था।
19

11

कुछ भी गलत:

@Test
void itWorks() {
    // stuff
}

@Test
void itWorksRepeatably() {
    for (int i = 0; i < 10; i++) {
        itWorks();
    }
}

उस मामले के विपरीत, जहां आप प्रत्येक सरणी मानों का परीक्षण कर रहे हैं, आप विशेष रूप से परवाह नहीं करते हैं जो विफल हो जाते हैं।

कोड में आप क्या कर सकते हैं कॉन्फ़िगरेशन या एनोटेशन में करने की आवश्यकता नहीं है।


2
मैं सामान्य इकाई परीक्षणों के रूप में कई परीक्षण चलाना चाहता हूं और प्रत्येक के लिए एक ट्रेस और स्थिति प्राप्त करना चाहता हूं।
स्टीफन थिएबर्ग

24
इस मामले में "@Before" s और "@After" चलाया नहीं जाएगा
बोगदान

3
मेरी समस्या को हल @Beforeकरने से पहले एनोटेट विधि को मैन्युअल रूप से कॉल करने के साथ यह itWorks()
जोहो नेव्स

क्या आप DRY अवधारणा जानते हैं? en.wikipedia.org/wiki/Don%27t_repeat_yourself मैं हर जगह आपके पाश को कॉपी करने के बजाय कुछ सेटअप बनाने की सलाह देता हूं।
किकिवा

इस उत्तर के लिए संपादित कतार भरी हुई है; इसलिए, मैं इसे एक टिप्पणी में डालूंगा: JUnit4 के लिए, परीक्षणों को सार्वजनिक करने की आवश्यकता है।
रिचर्ड जेसप

7

यह मेरे लिए बहुत आसान काम करता है।

public class RepeatTests extends TestCase {

    public static Test suite() {
        TestSuite suite = new TestSuite(RepeatTests.class.getName());

        for (int i = 0; i < 10; i++) {              
        suite.addTestSuite(YourTest.class);             
        }

        return suite;
    }
}

बहुत बढ़िया के रूप में एक और फ्रेमवर्क का उपयोग नहीं करता है और वास्तव में JUnit 3 (Android के लिए महत्वपूर्ण) के साथ काम करता है
व्लादिमीर इवानोव

1
JUnit4 के साथ एक कार्यान्वयन एक धावक के साथ किया जा सकता है: public class RepeatRunner extends BlockJUnit4ClassRunner { public RepeatRunner(Class klass) throws InitializationError { super(klass); } @Override public void run(final RunNotifier notifier) { for (int i = 0; i < 10; i++) { super.run(notifier); } } }हालांकि कम से कम ग्रहण JUnit प्लगइन में आपको परिणाम मिलते हैं: "10/1 परीक्षण पारित"
पीटर विप्परमैन

7

टेम्पू-फुगिट लाइब्रेरी में एक आंतरायिक एनोटेशन है जो @Ruleकई बार या साथ एक परीक्षण को दोहराने के लिए JUnit 4.7 के साथ काम करता है @RunWith

उदाहरण के लिए,

@RunWith(IntermittentTestRunner.class)
public class IntermittentTestRunnerTest {

   private static int testCounter = 0;

   @Test
   @Intermittent(repition = 99)
   public void annotatedTest() {
      testCounter++;
   }
}

परीक्षण चलने के बाद (IntermittentTestRunner के साथ @RunWith), testCounter99 के बराबर होगा।


हाँ, यह एक ही समस्या यहाँ है, पहले से ही एक और धावक का उपयोग कर रहा है और इसलिए यह एक, अच्छे विचार का उपयोग नहीं कर सकता है।
स्टीफन थ्यबर्ग

हाँ, मैं RunWith के साथ एक ही मुद्दा रहा हूँ ... क्योंकि यह एक छोटा सा दौर पाने के लिए मैं tempus-fugit tweaked चला जाता है, आप बार-बार चलाना चाहते हैं जब आप धावक के बजाय एक @ नियम का उपयोग कर सकते हैं। आप इसे आंतरायिक के बजाय @Repeating के साथ चिह्नित करते हैं। हालांकि, पहले / @ आफ़्टर से नियम संस्करण नहीं चलेगा। देखें tempus-fugit.googlecode.com/svn/site/documentation/... (लोड के लिए नीचे स्क्रॉल / परीक्षण सोख) अधिक जानकारी के लिए।
तोबी

0

मैं एक मॉड्यूल का निर्माण करता हूं जो इस तरह के परीक्षण करने की अनुमति देता है। लेकिन यह केवल दोहराने में ही केंद्रित नहीं है। लेकिन गारंटी में कि कुछ कोड थ्रेड सुरक्षित है।

https://github.com/anderson-marques/concurrent-testing

मावेन निर्भरता:

<dependency>
    <groupId>org.lite</groupId>
    <artifactId>concurrent-testing</artifactId>
    <version>1.0.0</version>
</dependency>

उपयोग का उदाहरण:

package org.lite.concurrent.testing;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import ConcurrentTest;
import ConcurrentTestsRule;

/**
 * Concurrent tests examples
 */
public class ExampleTest {

    /**
     * Create a new TestRule that will be applied to all tests
     */
    @Rule
    public ConcurrentTestsRule ct = ConcurrentTestsRule.silentTests();

    /**
     * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
     */
    @Test
    @ConcurrentTest(requests = 20, threads = 10)
    public void testConcurrentExecutionSuccess(){
        Assert.assertTrue(true);
    }

    /**
     * Tests using 10 threads and make 20 requests. This means until 10 simultaneous requests.
     */
    @Test
    @ConcurrentTest(requests = 200, threads = 10, timeoutMillis = 100)
    public void testConcurrentExecutionSuccessWaitOnly100Millissecond(){
    }

    @Test(expected = RuntimeException.class)
    @ConcurrentTest(requests = 3)
    public void testConcurrentExecutionFail(){
        throw new RuntimeException("Fail");
    }
}

यह एक ओपन सोर्स प्रोजेक्ट है। बेहिचक सुधार करें।


0

आप एक मुख्य विधि से अपना JUnit परीक्षण चला सकते हैं और कई बार इसे दोहरा सकते हैं, जिसकी आपको आवश्यकता है:

package tests;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.Result;

public class RepeatedTest {

    @Test
    public void test() {
        fail("Not yet implemented");
    }

    public static void main(String args[]) {

        boolean runForever = true;

        while (runForever) {
            Result result = org.junit.runner.JUnitCore.runClasses(RepeatedTest.class);

            if (result.getFailureCount() > 0) {
                runForever = false;
               //Do something with the result object

            }
        }

    }

}

0

यह अनिवार्य रूप से जवाब है कि Yishai ऊपर प्रदान किया गया है, कोटलिन में फिर से लिखा गया है:

@RunWith(Parameterized::class)
class MyTest {

    companion object {

        private const val numberOfTests = 200

        @JvmStatic
        @Parameterized.Parameters
        fun data(): Array<Array<Any?>> = Array(numberOfTests) { arrayOfNulls<Any?>(0) }
    }

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