2013-06-26 9 views
5

अभी हमारे पास एक परियोजना है जो दो नौकरियों में बनती है। 1) मानक परीक्षण के साथ मानक निर्माण है। 2) एकीकरण परीक्षण है। वे इस तरह काम करते हैं:मैं समानांतर में अपने एकीकरण परीक्षण चलाने के लिए जेनकींस का उपयोग कैसे कर सकता हूं?

  1. निर्माण पूरी परियोजना, चलाने इकाई परीक्षण, एकीकरण परीक्षण काम
  2. शुरू पूरी परियोजना का निर्माण, एकीकरण सर्वर पर तैनात, एकीकरण सर्वर के विरुद्ध ग्राहक के पक्ष एकीकरण परीक्षण चलाने

समस्या चरण 2 है) अब चलाने के लिए एक घंटे लगते हैं और मैं एकीकरण परीक्षणों को समानांतर करना चाहता हूं ताकि वे कम समय ले सकें। लेकिन मुझे बिल्कुल यकीन नहीं है कि मैं इसे कैसे कर सकता/सकती हूं।

  1. , पूरी परियोजना, चलाने इकाई परीक्षण का निर्माण शुरू एकीकरण परीक्षण काम
  2. , पूरी परियोजना का निर्माण एकीकरण server1 करने के लिए इसे तैनात: मेरा पहला विचार मैं हो सकता था कि दो चरण 2) इस तरह रों है, चलाने क्लाइंट साइड एकीकरण एकीकरण server1 के खिलाफ परीक्षण
  3. निर्माण पूरी परियोजना,, एकीकरण server2 करने के लिए इसे तैनात एकीकरण server2 के खिलाफ चलाए ग्राहक के पक्ष एकीकरण परीक्षणों

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

उत्तर

2

मुझे यह देखने के लिए this great article मिला, लेकिन यह ग्रोवी कोड में ऐसा करने का एक तरीका देता है। मैंने इन चरणों का बहुत पालन किया, लेकिन मैंने अवधि के आधार पर परीक्षणों को समान रूप से वितरित करने के लिए कोड नहीं लिखा है। लेकिन यह अभी भी एक उपयोगी उपकरण है इसलिए मैं इसे साझा करूंगा।

import junit.framework.JUnit4TestAdapter; 
import junit.framework.TestSuite; 
import org.junit.Ignore; 
import org.junit.extensions.cpsuite.ClassesFinder; 
import org.junit.extensions.cpsuite.ClasspathFinderFactory; 
import org.junit.extensions.cpsuite.SuiteType; 
import org.junit.runner.RunWith; 
import org.junit.runners.AllTests; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.List; 

@RunWith(AllTests.class) 
public class DistributedIntegrationTestRunner { 

    private static Logger log = LoggerFactory.getLogger(DistributedIntegrationTestRunner.class); 

    public static TestSuite suite() { 
     TestSuite suite = new TestSuite(); 

     ClassesFinder classesFinder = new ClasspathFinderFactory().create(true, 
       new String[]{".*IntegrationTest.*"}, 
       new SuiteType[]{SuiteType.TEST_CLASSES}, 
       new Class[]{Object.class}, 
       new Class[]{}, 
       "java.class.path"); 

     int nodeNumber = systemPropertyInteger("node.number", "0"); 
     int totalNodes = systemPropertyInteger("total.nodes", "1"); 

     List<Class<?>> allTestsSorted = getAllTestsSorted(classesFinder); 
     allTestsSorted = filterIgnoredTests(allTestsSorted); 
     List<Class<?>> myTests = getMyTests(allTestsSorted, nodeNumber, totalNodes); 
     log.info("There are " + allTestsSorted.size() + " tests to choose from and I'm going to run " + myTests.size() + " of them."); 
     for (Class<?> myTest : myTests) { 
      log.info("I will run " + myTest.getName()); 
      suite.addTest(new JUnit4TestAdapter(myTest)); 
     } 

     return suite; 
    } 

    private static int systemPropertyInteger(String propertyKey, String defaultValue) { 
     String slaveNumberString = System.getProperty(propertyKey, defaultValue); 
     return Integer.parseInt(slaveNumberString); 
    } 

    private static List<Class<?>> filterIgnoredTests(List<Class<?>> allTestsSorted) { 
     ArrayList<Class<?>> filteredTests = new ArrayList<Class<?>>(); 
     for (Class<?> aTest : allTestsSorted) { 
      if (aTest.getAnnotation(Ignore.class) == null) { 
       filteredTests.add(aTest); 
      } 
     } 
     return filteredTests; 
    } 

    /* 
    TODO: make this algorithm less naive. Sort each test by run duration as described here: http://blog.tradeshift.com/just-add-servers/ 
    */ 
    private static List<Class<?>> getAllTestsSorted(ClassesFinder classesFinder) { 
     List<Class<?>> allTests = classesFinder.find(); 
     Collections.sort(allTests, new Comparator<Class<?>>() { 
      @Override 
      public int compare(Class<?> o1, Class<?> o2) { 
       return o1.getSimpleName().compareTo(o2.getSimpleName()); 
      } 
     }); 
     return allTests; 
    } 

    private static List<Class<?>> getMyTests(List<Class<?>> allTests, int nodeNumber, int totalNodes) { 
     List<Class<?>> myTests = new ArrayList<Class<?>>(); 

     for (int i = 0; i < allTests.size(); i++) { 
      Class<?> thisTest = allTests.get(i); 
      if (i % totalNodes == nodeNumber) { 
       myTests.add(thisTest); 
      } 
     } 

     return myTests; 
    } 
} 

ClasspathFinderFactory सभी परीक्षण कक्षाओं कि .*IntegrationTest स्वरूप से मेल खाते को खोजने के लिए प्रयोग किया जाता है।

मैं एन नौकरियां करता हूं और वे सभी Runner चलाते हैं लेकिन वे सभी node.number सिस्टम प्रॉपर्टी के लिए अलग-अलग मानों का उपयोग करते हैं, इसलिए प्रत्येक नौकरी परीक्षणों का एक अलग सेट चलाती है। इस तरह फेल सेफ प्लगइन लग रहा है:

 <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-failsafe-plugin</artifactId> 
      <version>2.12.4</version> 
      <executions> 
       <execution> 
        <id>integration-tests</id> 
        <goals> 
         <goal>integration-test</goal> 
         <goal>verify</goal> 
        </goals> 
       </execution> 
      </executions> 
      <configuration> 
       <includes> 
        <include>**/DistributedIntegrationTestRunner.java</include> 
       </includes> 
       <skipITs>${skipITs}</skipITs> 
      </configuration> 
     </plugin> 

ClasspathFinderFactory से

 <dependency> 
      <groupId>cpsuite</groupId> 
      <artifactId>cpsuite</artifactId> 
      <version>1.2.5</version> 
      <scope>test</scope> 
     </dependency> 

आता है मुझे लगता है कि इस के लिए कुछ जेनकींस प्लगइन होना चाहिए, लेकिन मैं एक ढूँढने में सक्षम नहीं किया गया है। कुछ जो करीब है Parallel Test Executor है, लेकिन मुझे नहीं लगता कि यह वही काम करता है जो मुझे चाहिए। ऐसा लगता है कि यह एकाधिक सर्वरों के बजाय एक ही नौकरी/सर्वर पर सभी परीक्षण चलाता है। यह कहने का एक स्पष्ट तरीका प्रदान नहीं करता है, "यहां इन परीक्षणों को चलाएं, और वहां परीक्षण करें"।

+0

> ऐसा लगता है कि यह सभी परीक्षणों को चलाता है एकाधिक सर्वरों के बजाय एक एकल नौकरी/सर्वर। जब परीक्षण नौकरी "आवश्यक होने पर समवर्ती बिल्ड निष्पादित करने" के लिए कॉन्फ़िगर किया गया है, तो रन जेनकिंस द्वारा किसी अन्य नोड पर चलाया जा सकता है। –

1

मेरा मानना ​​है कि आप पहले से ही अब तक एक समाधान मिल गया, लेकिन मैं अन्य लोगों से सवाल पूछने इस पृष्ठ को खोलने के लिए एक रास्ता छोड़ देंगे:
समानांतर परीक्षण निष्पादक प्लगइन:
"यह प्लगइन एक नए कहते हैं बिल्डर जो आपको समानांतर में एक अलग नौकरी में परिभाषित परीक्षणों को आसानी से निष्पादित करने देता है। यह जेनकिंस को अंतिम रन के परीक्षण निष्पादन समय को देखते हुए, लगभग समान आकार के कई इकाइयों में विभाजित परीक्षणों को देखते हुए हासिल किया जाता है, फिर उन्हें समानांतर में निष्पादित किया जाता है। "
https://wiki.jenkins-ci.org/display/JENKINS/Parallel+Test+Executor+Plugin

+0

यदि यह लिंक भविष्य में टूटा हुआ हो तो आप अपने उत्तर में वास्तविक समाधान भी शामिल कर सकते हैं। – Christina

0

हाँ, समानांतर टेस्ट निर्वाहक एक शांत प्लगइन यदि आप 2 गुलाम या 8 प्रबंधक के साथ एक गुलाम मिल गया है, क्योंकि इस प्लगइन पर "परीक्षण बंटवारे" तो जैसे आधारित: आप 4 अलग में अपने JUnit परीक्षण विभाजित सरणी, ये सरणी उस दास पर 4 अलग-अलग निष्पादक पर चलेंगी जो आपने निर्दिष्ट की थी। मुझे आशा है कि आपको यह मिल जाएगा: डी, ​​यह उस दास पर निष्पादकों की संख्या पर निर्भर करता है जहां आप समानांतर परीक्षण चलाने के लिए चाहते हैं या आपको विभाजित परीक्षणों को कम करना चाहिए 4 से 4 तक की गणना करें।

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

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