वर्तमान में JUnit 4 में परीक्षण निष्पादित करने का नाम प्राप्त करें


240

JUnit 3 में, मैं इस तरह वर्तमान में चल रहे परीक्षण का नाम प्राप्त कर सकता हूं:

public class MyTest extends TestCase
{
    public void testSomething()
    {
        System.out.println("Current test is " + getName());
        ...
    }
}

जो "करंट टेस्ट टेस्टस्टॉर्मिंग" होता है।

JUnit 4 में ऐसा करने के लिए कोई आउट-ऑफ-द-बॉक्स या सरल तरीका है?

पृष्ठभूमि: जाहिर है, मैं सिर्फ टेस्ट का नाम नहीं छापना चाहता। मैं परीक्षण-विशिष्ट डेटा लोड करना चाहता हूं जो संसाधन में परीक्षण के समान नाम के साथ संग्रहीत होता है। तुम्हें पता है, कॉन्फ़िगरेशन और सभी पर सम्मेलन


उपरोक्त कोड आपको JUnit 4 में क्या देता है?
छिपकली

5
JUnit 3 परीक्षण TestCase का विस्तार करते हैं जहाँ getName () परिभाषित है। JUnit 4 परीक्षण एक बेस क्लास का विस्तार नहीं करता है, इसलिए इसमें कोई गेटनेम () विधि नहीं है।
डेव रे

मेरे पास एक ऐसी ही समस्या है जहां मैं <b> सेट </ b> परीक्षण नाम चाहता हूं क्योंकि मैं पैरामीट्रीज रनर का उपयोग कर रहा हूं जो केवल मुझे गिने हुए टेस्ट केस देता है।
वोल्कर स्टोलज़

टेस्ट या टेस्टवॉकर का उपयोग करके लवली समाधान ... बस सोचकर (ज़ोर से) कि क्या इसके लिए कभी कोई आवश्यकता होनी चाहिए? आप पा सकते हैं कि ग्रैड द्वारा दिए गए टाइमिंग आउटपुट चार्ट को देखकर कोई टेस्ट धीरे-धीरे चल रहा है या नहीं। आपको कभी भी उस आदेश को जानने की आवश्यकता नहीं होनी चाहिए जिसमें परीक्षण संचालित होते हैं ...?
माइक कृंतक

जवाबों:


378

JUnit 4.7 ने इस फीचर को जोड़ा, ऐसा लगता है कि यह TestName-Rule का उपयोग कर रहा है । ऐसा लगता है कि आपको विधि का नाम मिलेगा:

import org.junit.Rule;

public class NameRuleTest {
    @Rule public TestName name = new TestName();

    @Test public void testA() {
        assertEquals("testA", name.getMethodName());
    }

    @Test public void testB() {
        assertEquals("testB", name.getMethodName());
    }
}

4
यह भी ध्यान दें कि TestName @before में उपलब्ध नहीं है :( देखें: old.nabble.com/…

41
जाहिर है JUnit के नए संस्करण पर अमल @Ruleसे पहले @Before- मैं JUnit के लिए नया हूँ और के आधार पर किया गया था TestNameमेरी में @Beforeकोई समस्या नहीं है।
पराक्रमी


2
यदि आप पैरामीटराइज्ड टेस्ट "name.getMethodName ()" का उपयोग कर रहे हैं तो {testA [0], testA [1], आदि} का उपयोग करेगा। इस प्रकार मैं कुछ का उपयोग करता हूं: assertTrue (name.getMethodName) \ घ \]) "));
लेगना

2
@ डंकनजोन प्रस्तावित विकल्प "अधिक कुशल" क्यों है?
स्टीफन

117

JUnit 4.9.x और अधिक

4.9 के बाद से, TestWatchmanवर्ग को वर्ग के पक्ष में हटा दिया गया है TestWatcher, जिसमें आह्वान किया गया है:

@Rule
public TestRule watcher = new TestWatcher() {
   protected void starting(Description description) {
      System.out.println("Starting test: " + description.getMethodName());
   }
};

नोट: युक्त वर्ग घोषित किया जाना चाहिए public

JUnit 4.7.x - 4.8.x

निम्नलिखित दृष्टिकोण एक कक्षा में सभी परीक्षणों के लिए विधि नामों को प्रिंट करेगा:

@Rule
public MethodRule watchman = new TestWatchman() {
   public void starting(FrameworkMethod method) {
      System.out.println("Starting test: " + method.getName());
   }
};

1
@takacsot यह आश्चर्यजनक है। क्या आप कृपया इस बारे में एक ताजा प्रश्न पोस्ट कर सकते हैं और मुझे यहाँ लिंक दे सकते हैं?
डंकन जोन्स

किसी publicफ़ील्ड का उपयोग क्यों करें ?
बजे रफी ​​खाचदौरीयन


16

JUnit 5 और उच्चतर

में JUnit 5 आप इंजेक्षन कर सकते हैं TestInfoपरीक्षण तरीकों के लिए उपलब्ध कराने के जो सरल परीक्षण मेटा डेटा। उदाहरण के लिए:

@Test
@DisplayName("This is my test")
@Tag("It is my tag")
void test1(TestInfo testInfo) {
    assertEquals("This is my test", testInfo.getDisplayName());
    assertTrue(testInfo.getTags().contains("It is my tag"));
}

और देखें: JUnit 5 उपयोगकर्ता गाइड , TestInfo javadoc


9

इसके बजाय यह प्रयास करें:

public class MyTest {
        @Rule
        public TestName testName = new TestName();

        @Rule
        public TestWatcher testWatcher = new TestWatcher() {
            @Override
            protected void starting(final Description description) {
                String methodName = description.getMethodName();
                String className = description.getClassName();
                className = className.substring(className.lastIndexOf('.') + 1);
                System.err.println("Starting JUnit-test: " + className + " " + methodName);
            }
        };

        @Test
        public void testA() {
                assertEquals("testA", testName.getMethodName());
        }

        @Test
        public void testB() {
                assertEquals("testB", testName.getMethodName());
        }
}

आउटपुट इस तरह दिखता है:

Starting JUnit-test: MyTest testA
Starting JUnit-test: MyTest testB

नोट: यदि आपका परीक्षण TestCase का उपवर्ग है तो यह काम नहीं करता है ! परीक्षण चलता है लेकिन @ नियम कोड कभी नहीं चलता है।


3
भगवान आपको उदाहरण के बहुत पर अपने नोट के लिए आशीर्वाद देते हैं।
user655419

"यह काम नहीं करता है" - बिंदु में मामला - खीरे की अनदेखी @ नियम एनोटेशन
बेंजीनर

8

SLF4J (जावा के लिए सरल लॉगिंग मुखौटा) का उपयोग करने पर विचार करें, जो पैरामीटर संदेश का उपयोग करके कुछ साफ-सुथरा सुधार प्रदान करता है। JUnit 4 नियम कार्यान्वयन के साथ SLF4J का संयोजन अधिक कुशल टेस्ट क्लास लॉगिंग तकनीक प्रदान कर सकता है।

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingTest {

  @Rule public MethodRule watchman = new TestWatchman() {
    public void starting(FrameworkMethod method) {
      logger.info("{} being run...", method.getName());
    }
  };

  final Logger logger =
    LoggerFactory.getLogger(LoggingTest.class);

  @Test
  public void testA() {

  }

  @Test
  public void testB() {

  }
}

6

एक जटिल तरीका यह है कि org.junit.runners.BlockJUnit4ClassRunner को दबाकर अपना रनर बनाएं।

फिर आप कुछ इस तरह से कर सकते हैं:

public class NameAwareRunner extends BlockJUnit4ClassRunner {

    public NameAwareRunner(Class<?> aClass) throws InitializationError {
        super(aClass);
    }

    @Override
    protected Statement methodBlock(FrameworkMethod frameworkMethod) {
        System.err.println(frameworkMethod.getName());
        return super.methodBlock(frameworkMethod);
    }
}

फिर प्रत्येक परीक्षण वर्ग के लिए, आपको @RunWith (NameAwareRunner.class) एनोटेशन जोड़ना होगा। वैकल्पिक रूप से, आप उस एनोटेशन को टेस्ट सुपरक्लास पर रख सकते हैं यदि आप इसे हर बार याद नहीं रखना चाहते हैं। यह, निश्चित रूप से आपके चयनकर्ताओं को सीमित करता है लेकिन यह स्वीकार्य हो सकता है।

इसके अलावा, रनर से वर्तमान परीक्षण नाम और आपके ढांचे में आने के लिए थोड़ा सा कुंग फू लग सकता है, लेकिन यह आपको कम से कम नाम देता है।


वैचारिक रूप से कम से कम, यह विचार मुझे सीधा लगता है। मेरी बात: मैं इसे दृढ़ नहीं कहूंगा।
user98761

"एक टेस्ट सुपरक्लास पर ..." - कृपया, भयानक वंशानुक्रम आधारित डिजाइन पैटर्न का कोई और अधिक नहीं। यह तो JUnit3 है!
oberlies

3

JUnit 4 में टेस्ट केस के लिए कोई भी आउट-ऑफ-द-बॉक्स तंत्र नहीं है, ताकि इसे स्वयं का नाम मिल सके (सेटअप और अशांति के दौरान)।


1
क्या स्टैक का निरीक्षण करने के अलावा अन्य कोई आउट-ऑफ-द-बॉक्स तंत्र नहीं है?
डेव रे

4
नीचे दिए गए जवाबों को नहीं दिया मामला! शायद किसी और को सही जवाब दे?
टोबे

3
String testName = null;
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (int i = trace.length - 1; i > 0; --i) {
    StackTraceElement ste = trace[i];
    try {
        Class<?> cls = Class.forName(ste.getClassName());
        Method method = cls.getDeclaredMethod(ste.getMethodName());
        Test annotation = method.getAnnotation(Test.class);
        if (annotation != null) {
            testName = ste.getClassName() + "." + ste.getMethodName();
            break;
        }
    } catch (ClassNotFoundException e) {
    } catch (NoSuchMethodException e) {
    } catch (SecurityException e) {
    }
}

1
मैं तर्क दे सकता हूं कि वह केवल एक समाधान दिखाना चाहते थे .. यह नहीं देखें कि नकारात्मक वोट क्यों .... @downvoter: कम से कम, कम से कम, उपयोगी जानकारी जोड़ें ..
विक्टर

1
@skaffman हम सभी वैकल्पिक समाधानों की पूरी श्रृंखला देखना पसंद करते हैं। मैं जो खोज रहा हूं, उसके लिए यह सबसे निकटतम है: टेस्ट का नाम सीधे टेस्टक्लास में नहीं बल्कि कक्षा में जो परीक्षण के दौरान उपयोग किया जाता है (उदाहरण के लिए एक लकड़हारा घटक में)। वहां, परीक्षण-प्रासंगिक एनोटेशन अब काम नहीं करते हैं।
डैनियल एल्डर

3

पिछली टिप्पणी और आगे के विचार के आधार पर मैंने TestWather का एक विस्तार बनाया, जिसका उपयोग आप अपने JUnit परीक्षण विधियों में कर सकते हैं:

public class ImportUtilsTest {
    private static final Logger LOGGER = Logger.getLogger(ImportUtilsTest.class);

    @Rule
    public TestWatcher testWatcher = new JUnitHelper(LOGGER);

    @Test
    public test1(){
    ...
    }
}

परीक्षण सहायक वर्ग अगले है:

public class JUnitHelper extends TestWatcher {
private Logger LOGGER;

public JUnitHelper(Logger LOGGER) {
    this.LOGGER = LOGGER;
}

@Override
protected void starting(final Description description) {
    LOGGER.info("STARTED " + description.getMethodName());
}

@Override
protected void succeeded(Description description) {
    LOGGER.info("SUCCESSFUL " + description.getMethodName());
}

@Override
protected void failed(Throwable e, Description description) {
    LOGGER.error("FAILURE " + description.getMethodName());
}
}

का आनंद लें!


हाय क्या है ImportUtilsTest, मुझे एक त्रुटि मिलती है, यह एक लकड़हारा वर्ग लगता है, क्या मुझे अधिक जानकारी है? धन्यवाद
Sylhare

1
नामित वर्ग JUnit परीक्षण वर्ग का एक उदाहरण है: JUnitHelper का उपयोगकर्ता। मैं उपयोग उदाहरण को सही करूंगा।
सेसाबा तेनकेन्स

आह अब मैं गूंगा महसूस करता हूं, यह बहुत स्पष्ट था। आपका बहुत बहुत धन्यवाद! ;)
सिलहारे

1
@ClassRule
public static TestRule watchman = new TestWatcher() {
    @Override
    protected void starting( final Description description ) {
        String mN = description.getMethodName();
        if ( mN == null ) {
            mN = "setUpBeforeClass..";
        }

        final String s = StringTools.toString( "starting..JUnit-Test: %s.%s", description.getClassName(), mN );
        System.err.println( s );
    }
};

0

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



0

JUnit 5 TestInfoमें JUnit 4 से TestName नियम के लिए ड्रॉप-इन प्रतिस्थापन के रूप में कार्य करता है।

प्रलेखन से:

TestInfo का उपयोग वर्तमान परीक्षण या कंटेनर के बारे में जानकारी को @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, @BeforeEach, @AfterEach, @BefforeAll, और @AAAAll विधियों में इंजेक्ट करने के लिए किया जाता है।

वर्तमान निष्पादित परीक्षण की विधि का नाम प्राप्त करने के लिए, आपके पास दो विकल्प हैं: String TestInfo.getDisplayName()और Method TestInfo.getTestMethod()

केवल वर्तमान परीक्षण विधि का नाम पुनर्प्राप्त करने के TestInfo.getDisplayName()लिए पर्याप्त नहीं हो सकता है क्योंकि परीक्षण विधि डिफ़ॉल्ट प्रदर्शन नाम है methodName(TypeArg1, TypeArg2, ... TypeArg3)। एक अच्छे विचार के लिए
डुप्लिकेटिंग विधि के नाम @DisplayName("..")आवश्यक नहीं हैं।

विकल्प के रूप में आप TestInfo.getTestMethod()एक Optional<Method>वस्तु लौटा सकते हैं ।
यदि परीक्षण विधि के अंदर पुनर्प्राप्ति विधि का उपयोग किया जाता है, तो आपको Optionalलिपटे मूल्य का परीक्षण करने की भी आवश्यकता नहीं है ।

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.Test;

@Test
void doThat(TestInfo testInfo) throws Exception {
    Assertions.assertEquals("doThat(TestInfo)",testInfo.getDisplayName());
    Assertions.assertEquals("doThat",testInfo.getTestMethod().get().getName());
}

0

ExtensionContext के माध्यम से JUnit 5

फायदा:

आपको ExtensionContextओवरराइड करके जोड़े गए कार्य करने होंगे afterEach(ExtensionContext context)

public abstract class BaseTest {

    protected WebDriver driver;

    @RegisterExtension
    AfterEachExtension afterEachExtension = new AfterEachExtension();

    @BeforeEach
    public void beforeEach() {
        // Initialise driver
    }

    @AfterEach
    public void afterEach() {
        afterEachExtension.setDriver(driver);
    }

}
public class AfterEachExtension implements AfterEachCallback {

    private WebDriver driver;

    public void setDriver(WebDriver driver) {
        this.driver = driver;
    }

    @Override
    public void afterEach(ExtensionContext context) {
        String testMethodName = context.getTestMethod().orElseThrow().getName();
        // Attach test steps, attach scsreenshots on failure only, etc.
        driver.quit();
    }

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