1.概述
源代码集为我们提供了一种在Gradle项目中构建源代码的强大方法。
在本快速教程中,我们将了解如何使用它们。
2.默认来源集
在进入默认值之前,让我们首先解释什么是源集。顾名思义,源集代表源文件的逻辑分组。
我们将介绍Java项目的配置,但是这些概念也适用于其他Gradle项目类型。
2.1 默认项目布局
让我们从一个简单的项目结构开始:
source-sets
├── src
│ ├── main
│ │ └── java
│ │ ├── SourceSetsMain.java
│ │ └── SourceSetsObject.java
│ └── test
│ └── java
│ └── SourceSetsTest.java
└── build.gradle
现在让我们看一下build.gradle
:
apply plugin : "java"
description = "Source Sets example"
test {
testLogging {
events "passed", "skipped", "failed"
}
}
dependencies {
implementation('org.apache.httpcomponents:httpclient:4.5.12')
testImplementation('junit:junit:4.12')
}
Java插件假定**src/main/java
和src/test/java
为默认源目录**.
让我们设计一个简单的实用程序任务:
task printSourceSetInformation(){
doLast{
sourceSets.each { srcSet ->
println "["+srcSet.name+"]"
print "-->Source directories: "+srcSet.allJava.srcDirs+"\n"
print "-->Output directories: "+srcSet.output.classesDirs.files+"\n"
println ""
}
}
}
我们在这里仅打印一些源集属性。我们总是可以查看完整的JavaDoc以获得更多信息。
让我们运行它,看看会得到什么:
$ ./gradlew printSourceSetInformation
> Task :source-sets:printSourceSetInformation
[main]
-->Source directories: [.../source-sets/src/main/java]
-->Output directories: [.../source-sets/build/classes/java/main]
[test]
-->Source directories: [.../source-sets/src/test/java]
-->Output directories: [.../source-sets/build/classes/java/test]
注意,我们有两个默认的源集: main
和test
。
2.2 默认配置
**Java插件还会自动为我们创建一些默认的Gradle配置**。
它们遵循特殊的命名约定: <sourceSetName><configurationName>
。
我们使用它们在build.gradle
声明依赖项:
dependencies {
implementation('org.apache.httpcomponents:httpclient:4.5.12')
testImplementation('junit:junit:4.12')
}
注意,我们指定了implementation
而不是mainImplementation
。这是命名约定的例外。
默认情况下, testImplementation
配置扩展implementation
并继承其所有依赖项和输出。
让我们改进帮助程序任务,看看这是关于什么的:
task printSourceSetInformation(){
doLast{
sourceSets.each { srcSet ->
println "["+srcSet.name+"]"
print "-->Source directories: "+srcSet.allJava.srcDirs+"\n"
print "-->Output directories: "+srcSet.output.classesDirs.files+"\n"
print "-->Compile classpath:\n"
srcSet.compileClasspath.files.each {
print " "+it.path+"\n"
}
println ""
}
}
}
让我们看一下输出:
[main]
// same output as before
-->Compile classpath:
.../httpclient-4.5.12.jar
.../httpcore-4.4.13.jar
.../commons-logging-1.2.jar
.../commons-codec-1.11.jar
[test]
// same output as before
-->Compile classpath:
.../source-sets/build/classes/java/main
.../source-sets/build/resources/main
.../httpclient-4.5.12.jar
.../junit-4.12.jar
.../httpcore-4.4.13.jar
.../commons-logging-1.2.jar
.../commons-codec-1.11.jar
.../hamcrest-core-1.3.jar
test
源集在其编译类路径中main
的输出,还包括其依赖项。
接下来,让我们创建我们的单元测试:
public class SourceSetsTest {
@Test
public void whenRun_ThenSuccess() {
SourceSetsObject underTest = new SourceSetsObject("lorem","ipsum");
assertThat(underTest.getUser(), is("lorem"));
assertThat(underTest.getPassword(), is("ipsum"));
}
}
在这里,我们测试一个简单的POJO,该POJO存储两个值。我们可以直接使用它,因为**main
输出在我们的test
类路径中**。
接下来,让我们从Gradle中运行它:
./gradlew clean test
> Task :source-sets:test
com.baeldung.test.SourceSetsTest > whenRunThenSuccess PASSED
3.自定义来源集
到目前为止,我们已经看到了一些明智的默认设置。但是,实际上,我们经常需要自定义源集,尤其是对于集成测试。
那是因为我们可能只想在集成测试类路径上拥有特定的测试库。我们还可能希望独立于单元测试执行它们。
3.1 定义自定义源集
让我们为集成测试设计一个单独的源目录:
source-sets
├── src
│ └── main
│ ├── java
│ │ ├── SourceSetsMain.java
│ │ └── SourceSetsObject.java
│ ├── test
│ │ └── SourceSetsTest.java
│ └── itest
│ └── SourceSetsITest.java
└── build.gradle
接下来,让**我们使用sourceSets
构造build.gradle
**进行配置:
sourceSets {
itest {
java {
}
}
}
dependencies {
implementation('org.apache.httpcomponents:httpclient:4.5.12')
testImplementation('junit:junit:4.12')
}
// other declarations omitted
注意,我们没有指定任何自定义目录。这是因为我们的文件夹与新的源集( itest
)的名称匹配。
我们可以**srcDirs
属性包含的目录**:
sourceSets{
itest {
java {
srcDirs("src/itest")
}
}
}
从一开始就还记得我们的帮助任务吗?让我们重新运行它,看看它显示了什么:
$ ./gradlew printSourceSetInformation
> Task :source-sets:printSourceSetInformation
[itest]
-->Source directories: [.../source-sets/src/itest/java]
-->Output directories: [.../source-sets/build/classes/java/itest]
-->Compile classpath:
.../source-sets/build/classes/java/main
.../source-sets/build/resources/main
[main]
// same output as before
[test]
// same output as before
3.2 分配源集特定的依存关系
还记得默认配置吗?现在,我们还为itest
源集获取了一些配置。
让我们使用itestImplementation
分配一个新的依赖项:
dependencies {
implementation('org.apache.httpcomponents:httpclient:4.5.12')
testImplementation('junit:junit:4.12')
itestImplementation('com.google.guava:guava:29.0-jre')
}
这仅适用于集成测试。
让我们修改之前的测试并将其添加为集成测试:
public class SourceSetsItest {
@Test
public void givenImmutableList_whenRun_ThenSuccess() {
SourceSetsObject underTest = new SourceSetsObject("lorem", "ipsum");
List someStrings = ImmutableList.of("Baeldung", "is", "cool");
assertThat(underTest.getUser(), is("lorem"));
assertThat(underTest.getPassword(), is("ipsum"));
assertThat(someStrings.size(), is(3));
}
}
为了能够运行它,我们需要定义一个使用已编译输出的自定义测试任务:
// source sets declarations
// dependencies declarations
task itest(type: Test) {
description = "Run integration tests"
group = "verification"
testClassesDirs = sourceSets.itest.output.classesDirs
classpath = sourceSets.itest.runtimeClasspath
}
这些声明在配置阶段**进行评估。结果,它们的顺序很重要**。
例如,在声明此声明之前,我们无法引用itest
让我们看看如果运行测试会发生什么:
$ ./gradlew clean itest
// some compilation issues
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':source-sets:compileItestJava'.
> Compilation failed; see the compiler error output for details.
与之前的运行不同,这次我们遇到编译错误。所以发生了什么事?
这个新的源集将创建一个独立的配置。
换句话说, itestImplementation
不会继承JUnit
依赖关系,也不会获取main
的输出。
让我们在Gradle配置中解决此问题:
sourceSets{
itest {
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
java {
}
}
}
// dependencies declaration
configurations {
itestImplementation.extendsFrom(testImplementation)
itestRuntimeOnly.extendsFrom(testRuntimeOnly)
}
现在,让我们重新运行集成测试:
$ ./gradlew clean itest
> Task :source-sets:itest
com.baeldung.itest.SourceSetsItest > givenImmutableList_whenRun_ThenSuccess PASSED
测试通过。
3.3 Eclipse IDE处理
到目前为止,我们已经看到了如何直接使用Gradle处理源集。但是,大多数时候,我们将使用IDE(例如Eclipse)。
导入项目时,会遇到一些编译问题:
但是,如果我们从Gradle运行集成测试,则不会出现任何错误:
$ ./gradlew clean itest
> Task :source-sets:itest
com.baeldung.itest.SourceSetsItest > givenImmutableList_whenRun_ThenSuccess PASSED
所以发生了什么事?在这种情况下, guava
依赖项属于itestImplementation
。
不幸的是, Eclipse Buildship Gradle插件不能很好地处理这些自定义配置。
让我们**build.gradle
修复此**问题:
apply plugin: "eclipse"
// previous declarations
eclipse {
classpath {
plusConfigurations+=[configurations.itestCompileClasspath]
}
}
让我们解释一下我们在这里做了什么。我们将配置附加到Eclipse类路径中。
如果我们刷新项目,则编译问题就消失了。
但是,这种方法有一个缺点:IDE不能区分配置。
这意味着我们可以轻松地在test
源中guava
(我们特别想避免这种情况)。
4 结论
在本教程中,我们介绍了Gradle源集的基础。
然后,我们解释了定制源集如何工作以及如何在Eclipse中使用它们。
0 评论