Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Maven 如何使用Jenkins并行运行集成测试?_Maven_Jenkins_Continuous Integration_Build Automation - Fatal编程技术网

Maven 如何使用Jenkins并行运行集成测试?

Maven 如何使用Jenkins并行运行集成测试?,maven,jenkins,continuous-integration,build-automation,Maven,Jenkins,Continuous Integration,Build Automation,现在我们有一个包含两个工作的项目。1) 是带有单元测试的标准构建。2) 是集成测试。它们是这样工作的: 构建整个项目,运行单元测试,启动集成测试工作 构建整个项目,将其部署到集成服务器,对集成服务器运行客户端集成测试 问题是步骤2)现在需要一个多小时才能运行,我想并行化集成测试,以便它们花费更少的时间。但我不确定我怎么能/应该这样做。我的第一个想法是,我可以有如下两个步骤: 构建整个项目,运行单元测试,启动集成测试工作 构建整个项目,将其部署到集成服务器1,对集成服务器1运行客户端集成测试 构建

现在我们有一个包含两个工作的项目。1) 是带有单元测试的标准构建。2) 是集成测试。它们是这样工作的:

  • 构建整个项目,运行单元测试,启动集成测试工作
  • 构建整个项目,将其部署到集成服务器,对集成服务器运行客户端集成测试
  • 问题是步骤2)现在需要一个多小时才能运行,我想并行化集成测试,以便它们花费更少的时间。但我不确定我怎么能/应该这样做。我的第一个想法是,我可以有如下两个步骤:

  • 构建整个项目,运行单元测试,启动集成测试工作
  • 构建整个项目,将其部署到集成服务器1,对集成服务器1运行客户端集成测试
  • 构建整个项目,将其部署到集成服务器2,对集成服务器2运行客户端集成测试
  • 但是,如何在integration server1上运行一半的集成测试,在integration server2上运行另一半的集成测试?我使用的是maven,所以我可能会找到一个复杂的includes/excludes模式。但这听起来像是需要花费很多努力才能维持的事情。当有人添加一个新的集成测试类时,我如何确保它在两台服务器之一上运行?开发人员必须修改maven模式吗?

    我找到了如何做到这一点的方法,但它在Groovy代码中提供了一种方法。我基本上遵循了这些步骤,但我还没有编写按持续时间平均分配测试的代码。但这仍然是一个有用的工具,所以我将与大家分享

    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>