मुझे यह देखने के लिए 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 है, लेकिन मुझे नहीं लगता कि यह वही काम करता है जो मुझे चाहिए। ऐसा लगता है कि यह एकाधिक सर्वरों के बजाय एक ही नौकरी/सर्वर पर सभी परीक्षण चलाता है। यह कहने का एक स्पष्ट तरीका प्रदान नहीं करता है, "यहां इन परीक्षणों को चलाएं, और वहां परीक्षण करें"।
> ऐसा लगता है कि यह सभी परीक्षणों को चलाता है एकाधिक सर्वरों के बजाय एक एकल नौकरी/सर्वर। जब परीक्षण नौकरी "आवश्यक होने पर समवर्ती बिल्ड निष्पादित करने" के लिए कॉन्फ़िगर किया गया है, तो रन जेनकिंस द्वारा किसी अन्य नोड पर चलाया जा सकता है। –