简体   繁体   English

强制Gradle使用早期的依赖版本进行测试

[英]Forcing Gradle to use an earlier dependency version for testing

Is there a way to construct a Gradle build file to force the test phase to use an earlier version of a dependency than the one used for compilation and and packaging? 有没有办法构建一个Gradle构建文件来强制测试阶段使用早期版本的依赖项而不是用于编译和打包的依赖项?

I'm attempting to set up an HBase mini-cluster via HBaseTestingUtility to test my project; 我正在尝试通过HBaseTestingUtility建立一个HBase迷你集群来测试我的项目; unfortunately, HBaseTestingUtility relies on an old version of Guava (14.0.1 seems to work), while the rest of my project uses 18.0. 不幸的是,HBaseTestingUtility依赖于旧版本的Guava(14.0.1似乎可以工作),而我的项目的其余部分使用18.0。 Here are excerpts of my build script, as-is (I'm also using the Gradle test-sets plugin by unbroken-dome to create two separate sets of tests): 以下是我的构建脚本的摘录,原样(我也使用了unbroken-domeGradle测试集插件来创建两组独立的测试):

plugins {
    id 'org.unbroken-dome.test-sets' version '1.2.0'
}

apply plugin: 'java'

ext.verGuava = '18.0'
ext.verGuavaTEST = '14.0.1'

testSets {
    testUnit { dirName = 'test/unit' }
    testIntegration { dirName = 'test/integration' }
}

configurations {
    provided
    provided {
        extendsFrom(compile)
    }
    testIntConf
    testIntConf {
        extendsFrom(provided)
        resolutionStrategy {
            force "com.google.guava:guava:${verGuavaTEST}"
            forcedModules = ["com.google.guava:guava:${verGuavaTEST}"]
        }
    }
}

sourceSets {
    main.compileClasspath += configurations.provided
    testUnit.compileClasspath += configurations.provided
    testUnit.runtimeClasspath += configurations.provided
    testIntegration.compileClasspath += configurations.testIntConf
    testIntegration.runtimeClasspath += configurations.testIntConf
}

dependencies {
    provided "org.apache.hbase:hbase-client:${verHBase}"
    provided "org.apache.hbase:hbase-common:${verHBase}"
    compile "org.testng:testng:${verTestNG}"
    testIntegrationCompile group:'org.apache.hadoop', name:'hadoop-common', version:"${verHadoop}", classifier: 'tests'
    testIntegrationCompile group:'org.apache.hbase', name:'hbase-server', version:"${verHBase}"
    testIntegrationCompile group:'org.apache.hbase', name:'hbase-server', version:"${verHBase}", classifier: 'tests'
    testIntegrationCompile group:'org.apache.hbase', name:'hbase-hadoop-compat', version:"${verHBase}"
    testIntegrationCompile group:'org.apache.hbase', name:'hbase-hadoop-compat', version:"${verHBase}", classifier: 'tests'
    testIntegrationCompile group:'org.apache.hbase', name:'hbase-hadoop2-compat', version:"${verHBase}"
    testIntegrationCompile group:'org.apache.hbase', name:'hbase-hadoop2-compat', version:"${verHBase}", classifier: 'tests'
    testIntegrationCompile group:'org.apache.hadoop', name:'hadoop-hdfs', version:"${verHadoop}"
    testIntegrationCompile group:'org.apache.hadoop', name:'hadoop-hdfs', version:"${verHadoop}", classifier: 'tests'
}

testUnit {
    useTestNG()
    logger.info "@@@ Classpath (UNIT testing): ${classpath.getFiles().collect({it.toString()}).inject('\n') {acc, next -> acc + next + '\n'}}"
    logger.info "@@@ SystemProps (UNIT testing): ${System.getProperties().collect({it.toString()}).inject('\n') {acc, next -> acc + next + '\n'}}"
}

testIntegration {
    useTestNG()
    systemProperty "java.net.preferIPv4Stack", "true"
    logger.info "@@@ Classpath (INTEGRATION testing): ${classpath.getFiles().collect({it.toString()}).inject('\n') {acc, next -> acc + next + '\n'}}"
    logger.info "@@@ SysProps (INTEGRATION testing): ${System.getProperties().collect({it.toString()}).inject('\n') {acc, next -> acc + next + '\n'}}"
}

When I run a build via this script, I get the following output which seems to show that Guava 14.0.1 was added to the classpath for the testIntegration target, rather than replacing Guava 18.0: 当我通过这个脚本运行构建时,我得到以下输出,这似乎表明Guava 14.0.1被添加到testIntegration目标的类路径中,而不是替换 Guava 18.0:

@@@ Classpath (UNIT testing):
/home/user/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/18.0/cce0823396aa693798f8882e64213b1772032b09/guava-18.0.jar
@@@ Classpath (INTEGRATION testing):
/home/user/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/18.0/cce0823396aa693798f8882e64213b1772032b09/guava-18.0.jar
/home/user/.gradle/caches/modules-2/files-2.1/com.google.guava/guava/14.0.1/69e12f4c6aeac392555f1ea86fab82b5e5e31ad4/guava-14.0.1.jar

This behavior is probably to be expected; 这种行为可能是预期的; the API indicates that ResolutionStrategy.force(...) appends artifacts to the list to be considered. API指示ResolutionStrategy.force(...) 工件附加到要考虑的列表中。

How can I direct Gradle to eliminate Guava 18.0 from the classpath for the testIntegration target entirely? 如何指导Gradle完全从testIntegration目标的类路径中消除Guava 18.0?

I have tried changing the sourceSets section to assign the classpaths using = rather than += : 我尝试更改sourceSets部分以使用=而不是+ =分配类路径:

sourceSets {
    ...
    testIntegration.compileClasspath = configurations.testIntConf
    testIntegration.runtimeClasspath = configurations.testIntConf
}

This has the desired effect as far as eliminating Guava 18.0 (and retaining 14.0.1), but it seems to prevent Gradle from detecting the location of the testIntegration source files, for some reason, so the testIntegration tests are never compiled or executed. 就消除Guava 18.0(并保留14.0.1)而言,这具有预期的效果,但由于某种原因,它似乎阻止Gradle检测testIntegration源文件的位置,因此永远不会编译或执行testIntegration测试。

I have also tried a few variations on purging Guava from the inherited configuration, such as the following: 我还尝试了一些从继承配置中清除Guava的变体,如下所示:

configurations {
    provided
    provided {
        extendsFrom(compile)
    }
    testIntConf
    testIntConf {
        extendsFrom(provided.copy {
            exclude group:"com.google.guava", module:"guava"
        })
        resolutionStrategy {
            force "com.google.guava:guava:${verGuavaTEST}"
            forcedModules = ["com.google.guava:guava:${verGuavaTEST}"]
        }
    }
}

The above (and all other variations I've tried) do successfully eliminate the duplication of the Guava artifact in the classpath, but they seem to nullify the resolutionStrategy , as the resolved artifact is always the newer version (18.0) even in testIntegration . 以上(以及我尝试的所有其他变体)确实成功地消除了类路径中Guava工件的重复,但它们似乎使resolutionStrategy无效,因为即使在testIntegration ,已解析的工件也始终是较新的版本(18.0)。

While perhaps not the most elegant solution (and I'd still be interested in a cleaner one, if it exists), an approach which seems to work is to create a completely separate configuration which contains the newer Guava dependency only , then use FileCollection#minus to subtract that configuration from the classpath within the testIntegration target itself. 虽然也许不是最优雅的解决方案(和我仍然有兴趣在一个更清洁的一个,如果存在的话),这似乎工作的方法是创建一个完全独立的配置包含新的番石榴依赖,然后用FileCollection#minus从testIntegration目标本身的类路径中减去该配置。

Firstly, create the configuration; 首先,创建配置; I call it guava here since its sole purpose is to contain the Guava 18.0 artifact that I want to exclude from the testIntegration classpath: 我称之为guava ,因为它的唯一目的是包含我想要从testIntegration类路径中排除的Guava 18.0工件:

configurations {
    guava
    ...
}

(The configuration should contain the Guava artifacts in isolation, so it should not extendsFrom any other config.) (配置应包含在隔离的番石榴伪影,因此它应该extendsFrom任何其他配置)。

Secondly, add the artifact to be excluded from the classpath to the dependency list for the newly-created configuration. 其次,将要从类路径中排除的工件添加到新创建的配置的依赖关系列表中。 In this case, I know that the main configurations resolve com.google.guava:guava to version 18.0, so I add a dependency on that version of Guava to the guava configuration: 在这种情况下,我知道主要配置将com.google.guava:guava解析为版本18.0,因此我将该版本的Guava添加到guava配置:

dependencies {
    guava group:'com.google.guava', name:'guava', version:"${verGuava}"
    ...
}

Thirdly, invoke FileCollection#minus on classpath in the Gradle target wherein you want to force the earlier version of the dependency, in order to exclude the newer dependency. 第三,在Gradle目标中的classpath上调用FileCollection#minus ,其中要强制使用早期版本的依赖项,以便排除较新的依赖项。 My testIntegration block above is tranformed thusly: 我上面的testIntegration块因此被转换:

testIntegration {
    classpath = classpath.minus(configurations.guava);
    ...
}

So, the quick summary of how this works in the Gradle build is: 因此,在Gradle构建中如何工作的快速摘要是:

  1. Create a configuration which extendsFrom the main configuration (eg compile ), then use ResolutionStrategy#force and ResolutionStrategy#forcedModules to add the earlier version of the dependency to that configuration's dependency list. 创建一个从主配置(例如, compileextendsFrom的配置,然后使用ResolutionStrategy#force ResolutionStrategy#forcedModulesResolutionStrategy#forcedModules 早期版本的依赖项添加到该配置的依赖项列表中。
  2. Create a second configuration which does not extend from anything, intended to hold the newer version of the dependency. 创建第二个配置,该配置不会从任何内容扩展,旨在保存较新版本的依赖项。
  3. In sourceSets , append the configuration created in Step 1 to the compileClasspath and runtimeClasspath for the target where you wish to force the earlier dependency version. sourceSets ,将步骤1中创建的配置附加到您希望强制使用早期依赖项版本的目标的compileClasspathruntimeClasspath
  4. In dependencies , add the newer version of the artifact as a dependency for the configuration created in Step 2. dependencies ,添加较新版本的工件作为步骤2中创建的配置的依赖项。
  5. The classpath in the target block now contains the union of the default dependencies plus the earlier version, as a result of the actions taken in Steps 1 and 3. To remove the newer version, set classpath to classpath.minus(newerDependencyConfiguration) , where newerDependencyConfiguration is the one created in Step 2. 由于在步骤1和3中执行的操作,目标块中的classpath现在包含默认依赖项早期版本的并集。要删除较新版本,请将classpath设置为classpath.minus(newerDependencyConfiguration) ,其中newerDependencyConfiguration是在步骤2中创建的那个。

I was facing the same problem but simpler version. 我面临同样的问题,但更简单的版本。 cause I am not differentiate the integration test and unit test. 因为我没有区分集成测试和单元测试。 using this seems give the right guava dependency for test 使用它似乎给测试正确的番石榴依赖性

   configurations {
        all{
            resolutionStrategy {
                force 'com.fasterxml.jackson.core:jackson-databind:2.4.4'
            }
        }
        testCompile{
            resolutionStrategy {
                force 'com.google.guava:guava:14.0.1'
            }
        }
    }
dependencies {
 testCompile group: 'org.apache.hbase', name: 'hbase-testing-util', version: '1.2.4'
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM