2009-08-05 9 views
12

हम परीक्षण के लिए जुनीट 4 का उपयोग कर रहे हैं: हमारे पास कक्षाएं हैं जो TestCase के उप-वर्ग नहीं हैं, और उनके पास @Test के साथ सार्वजनिक विधियां हैं। हमारे पास एक फ़ाइल है जिसमें कई @Test विधियां हैं। यह JUnit 3 के लिए कमांड लाइन से चींटी के माध्यम से उनका कोई सबसेट को चलाने के लिए, यह नुस्खा की शैली में सक्षम होने के लिए अच्छा होगा:JUnit @Test विधियों का सबसेट चला रहा है

ant runtest -Dtest=MyTest -Dtests=testFoo,testBar 

http://today.java.net/pub/a/today/2003/09/12/individual-test-cases.html

मैं के बारे में सोच की कोशिश कर रहा है जावा प्रतिबिंब, आदि के साथ इसे प्राप्त करने के तरीके। चूंकि @Test विधियों को "छिपाने" या रनटाइम पर उनकी टिप्पणियां हटाने का कोई तरीका नहीं लगता है, इसलिए एकमात्र विकल्प क्लासलोडर की defineClass विधि का उपयोग करना प्रतीत होता है, जो काफी मुश्किल लगता है।

पीएस इस स्थिति में सही बात फाइल को विभाजित करना होगा, लेकिन क्या विकल्प हैं?

आपके समय के लिए धन्यवाद।

उत्तर

10

गुर्दा का समाधान अच्छा है।

@RunWith(FilteredRunner.class) 
public class MyTest { 
:

import org.junit.runner.manipulation.Filter; 
import org.junit.runner.Description; 

public final class AntCLFilter extends Filter { 
    private static final String TEST_CASES = "tests"; 
    private static final String ANT_PROPERTY = "${tests}"; 
    private static final String DELIMITER = "\\,"; 
    private String[] testCaseNames; 

    public AntCLFilter() { 
     super(); 
     if (hasTestCases()) testCaseNames = getTestCaseNames(); 
    } 

    public String describe() { 
     return "Filters out all tests not explicitly named in a comma-delimited list in the system property 'tests'."; 
    } 

    public boolean shouldRun(Description d) { 
     String displayName = d.getDisplayName(); 
     // cut off the method name: 
     String testName = displayName.substring(0, displayName.indexOf('(')); 
     if (testCaseNames == null) return true; 

     for (int i = 0; i < testCaseNames.length; i++) 
      if (testName.equals(testCaseNames[i])) 
       return true; 
     return false; 
    } 

    /** 
    * Check to see if the test cases property is set. Ignores Ant's 
    * default setting for the property (or null to be on the safe side). 
    **/ 
    public static boolean hasTestCases() { 
     return 
      System.getProperty(TEST_CASES) == null || 
      System.getProperty(TEST_CASES).equals(ANT_PROPERTY) ? 
      false : true; 
    } 

    /** 
    * Create a List of String names of test cases specified in the 
    * JVM property in comma-separated format. 
    * 
    * @return a List of String test case names 
    * 
    * @throws NullPointerException if the TEST_CASES property 
    * isn't set 
    **/ 
    private static String[] getTestCaseNames() { 

     if (System.getProperty(TEST_CASES) == null) { 
      throw new NullPointerException("Test case property is not set"); 
     } 

     String testCases = System.getProperty(TEST_CASES); 
     String[] cases = testCases.split(DELIMITER); 

     return cases; 
    } 
} 

import org.junit.internal.runners.*; 
import org.junit.runner.manipulation.Filter; 
import org.junit.runner.manipulation.NoTestsRemainException; 

public class FilteredRunner extends TestClassRunner { 

    public FilteredRunner(Class<?> clazz) throws InitializationError { 
     super(clazz); 
     Filter f = new AntCLFilter(); 
     try { 
      f.apply(this); 
     } catch (NoTestsRemainException ex) { 
      throw new RuntimeException(ex); 
     } 
    } 
} 

तो मैं के साथ अपने परीक्षण वर्ग एनोटेट: यहाँ है कि मैं क्या (यह ल्यूक Francl का नुस्खा है, जो मैं पहले लिंक का एक मिश्रण है, और कुछ अन्य सामान मैं नेट पर देखा था) कर समाप्त हो गया है

और मेरे चींटी buildfile में निम्नलिखित डाल:

<target name="runtest" 
     description="Runs the test you specify on the command line with -Dtest=" 
     depends="compile, ensure-test-name"> 
    <junit printsummary="withOutAndErr" fork="yes"> 
     <sysproperty key="tests" value="${tests}" /> 
     <classpath refid="classpath" /> 
     <formatter type="plain" usefile="false" /> 
     <batchtest> 
      <fileset dir="${src}"> 
       <include name="**/${test}.java" /> 
      </fileset> 
     </batchtest> 
    </junit> 
</target> 

कुंजी लाइन वहाँ sysproperty टैग किया जा रहा है।

और के रूप में वांछित अब मैं

ant runtest -Dtest=MyTest -Dtests=testFoo,testBar 

चला सकते हैं। यह जुनीट 4.1 के साथ काम करता है --- 4.4 में, जुनीट 4 क्लासरुनर से सबक्लास, और 4.5 और बाद में, ब्लॉकजुनिट 4 क्लासरुनर से सबक्लास।

+0

ठीक है, कि और अधिक सुंदर है मेरे समाधान से :) – guerda

+0

मैं कुछ दिनों के लिए इस (या कम से कम समान) समस्या से जूझ रहा हूं और एक चीज है जो मुझे परेशान करती रहती है। क्या होगा यदि आप अपने फ़िल्टर किए गए कुनर को Powermock के साथ उपयोग करना चाहते हैं, जिसके लिए इसकी अपनी @RunWith (PowermockRunner.class) एनोटेशन की भी आवश्यकता है? –

+0

महान उत्तर, लेकिन अब पुराना है। मुझे लगता है कि BlockJUnit4ClassRunner को TestClassRunner – Illidanek

8

अपना खुद का TestClassMethodsRunner बनाएं (यह दस्तावेज नहीं है या मुझे अब यह नहीं मिला है)।
TestClassMethodsRunner सभी टेस्टकेस निष्पादित करता है और आप फ़िल्टर किए गए TestClassMethodsRunner सेट कर सकते हैं।

आपको बस TestMethodRunner createMethodRunner(Object, Method, RunNotifier) विधि ओवरराइड करना है। , आप सभी टेस्ट कि स्ट्रिंग "नहीं" शामिल नहीं है पर अमल

public class FilteredTestRunner extends TestClassMethodsRunner { 

    public FilteredTestRunner(Class<?> aClass) { 
     super(aClass); 
    } 

    @Override 
    protected TestMethodRunner createMethodRunner(Object aTest, Method aMethod, RunNotifier aNotifier) { 
     if (aTest.getClass().getName().contains("NOT")) { 
      return new TestMethodRunner(aTest, aMethod, aNotifier, null) { 
       @Override 
       public void run() { 
        //do nothing with this test. 
       } 
      }; 
     } else { 
      return super.createMethodRunner(aTest, aMethod, aNotifier); 
     } 
    } 

} 

इस TestRunner के साथ: यह एक सरल एक hacky समाधान है। दूसरों को अनदेखा कर दिया जाएगा :) बस अपने टेस्टरुनर क्लास के साथ @RunWith एनोटेशन को अपने परीक्षण में जोड़ें।

@RunWith(FilteredTestRunner.class) 
public class ThisTestsWillNOTBeExecuted { 
    //No test is executed. 
} 

@RunWith(FilteredTestRunner.class) 
public class ThisTestsWillBeExecuted { 
    //All tests are executed. 
} 

createMethodRunner विधि में आप परीक्षण है कि मार डाला या नए criterias परिचय किया जाना चाहिए की एक सूची के खिलाफ वर्तमान परीक्षण देख सकते हैं।

इसके साथ शुभकामनाएँ!

एक अच्छे समाधान के लिए संकेतों की सराहना की जाती है!

12

चूंकि जुनीट 4.8 हमारे पास उस समस्या को हल करने के लिए @ श्रेणी टिप्पणियां हैं।

+2

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

+2

और जब से Surefire 2.11 (या तो) हम सुइट्स के निर्माण के बिना श्रेणी के परीक्षणों का चयन करने के लिए -Dgroups का उपयोग कर सकते हैं। पिछले हफ्ते हमारे परीक्षण सूट को हटाने में मुझे खुशी हुई क्योंकि इस सुधार के लिए धन्यवाद! ( मेवेन सरेफायर प्लगइन का पैरामीटर केवल टेस्टएनजी के लिए प्रलेखित है, लेकिन 2.11 भी जुनीट के लिए काम करता है।) –

+0

वह साइट डाउन प्रतीत होती है ... –

1

मामले ऐसे हैं जिनमें केवल एक ही परीक्षा पद्धति चलाने की आवश्यकता के लिए एक सरल तरीका है, एक कस्टम Runner या Filter बनाने की परेशानी के माध्यम से जाने के बिना:

public class MyTestClass { 

    public static void main(final String[] args) throws Exception { 
    final JUnitCore junit = new JUnitCore(); 
    final String singleTest = // Get the name of test from somewhere (environment, system property, whatever you want). 
    final Request req; 
    if (singleTest != null) { 
     req = Request.method(MyTestClass.class, singleTest); 
    } else { 
     req = Request.aClass(MyTestClass.class); 
    } 
    final Result result = junit.run(req); 
    // Check result.getFailures etc. 
    if (!result.wasSuccessful()) { 
     System.exit(1); 
    } 
    } 

    // Your @Test methods here. 

} 
संबंधित मुद्दे