Maven 如何使用Jenkins并行运行集成测试?
现在我们有一个包含两个工作的项目。1) 是带有单元测试的标准构建。2) 是集成测试。它们是这样工作的:Maven 如何使用Jenkins并行运行集成测试?,maven,jenkins,continuous-integration,build-automation,Maven,Jenkins,Continuous Integration,Build Automation,现在我们有一个包含两个工作的项目。1) 是带有单元测试的标准构建。2) 是集成测试。它们是这样工作的: 构建整个项目,运行单元测试,启动集成测试工作 构建整个项目,将其部署到集成服务器,对集成服务器运行客户端集成测试 问题是步骤2)现在需要一个多小时才能运行,我想并行化集成测试,以便它们花费更少的时间。但我不确定我怎么能/应该这样做。我的第一个想法是,我可以有如下两个步骤: 构建整个项目,运行单元测试,启动集成测试工作 构建整个项目,将其部署到集成服务器1,对集成服务器1运行客户端集成测试 构建
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
来自
<dependency>
<groupId>cpsuite</groupId>
<artifactId>cpsuite</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
cpsuite
,但我认为这和我需要的不一样。它似乎在单个作业/服务器上运行所有测试,而不是在多个服务器上运行。它没有提供一个明显的方式来表示“在这里运行这些测试,在那里运行这些测试” 我相信您现在已经找到了解决方案,但我将为其他人留下一条路径,他们将打开此页面,提出相同的问题:
并行测试执行器插件:
“此插件添加了一个新的构建器,让您轻松并行执行在单独作业中定义的测试。这是通过让Jenkins查看上次运行的测试执行时间,将测试拆分为大小大致相同的多个单元,然后并行执行来实现的。”
是的,如果你有2个从机或一个从机和8个执行器,那么并行测试执行器是一个很酷的插件,因为这个插件基于“测试拆分”,例如:你将junit测试拆分为4个不同的数组,这些数组将在你指定的从机上的4个不同执行器上运行。我希望你得到它:D,这取决于您希望运行并行测试的从机上的执行器数量,或者您应该将拆分测试计数从4减少到2。如果您还可以在回答中包含实际的解决方案,以防将来此链接中断。>它看起来像是在单个作业/服务器上运行所有测试,而不是在单个服务器上运行多台服务器。当测试作业配置为“必要时执行并发构建”时,Jenkins可能会在另一个节点上运行这些运行。
<dependency>
<groupId>cpsuite</groupId>
<artifactId>cpsuite</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>