第 二十三章. Java 插件

Chapter 23. The Java Plugin

Java 插件向project 添加了 Java 编译、 测试和捆绑的能力。它是很多其他 Gradle 插件的基础服务。
The Java plugin adds Java compilation, testing and bundling capabilities to a project. It serves as the basis for many of the other Gradle plugins.

23.1. 用法

23.1. Usage

要使用 Java 插件,请在构建脚本中加入:
To use the Java plugin, include in your build script:

示例 23.1. 使用 Java 插件
Example 23.1. Using the Java plugin

build.gradle

apply plugin: 'java'

23.2 源集

23.2. Source sets

Java 插件引入了一个 源集的概念。一个源集只是一组用于编译并一起执行的源文件。这些源文件可能包括 Java 源代码文件和资源文件。其他有一些插件添加了在源集里包含 Groovy 和 Scala 的源代码文件的能力。一个源集有一个相关联的编译类路径和运行时类路径。
The Java plugin introduces the concept of a source set . A source set is simply a group of source files which are compiled and executed together. These source files may include Java source files and resource files. Other plugins add the ability to include Groovy and Scala source files in a source set. A source set has an associated compile classpath, and runtime classpath.

源集的一个用途是,把源文件进行逻辑上的分组,以描述它们的目的。例如,你可能会使用一个源集来定义一个集成测试套件,或者你可能会使用单独的源集来定义你的项目的 API 和实现类。
One use for source sets is to group source files into logical groups which describe their purpose. For example, you might use a source set to define an integration test suite, or you might use separate source sets to define the API and implementation classes of your project.

Java 插件定义了两个标准的源集,分别是 maintestmain源集包含你产品的源代码,它们将被编译并组装成一个 JAR 文件。 test源集包含你的单元测试的源代码,它们将被编译并使用 JUnit 或 TestNG来执行。
The Java plugin defines two standard source sets, called main and test . The main source set contains your production source code, which is compiled and assembled into a JAR file. The test source set contains your unit test source code, which is compiled and executed using JUnit or TestNG.

23.3. 任务

23.3. Tasks

Java 插件向你的项目添加了大量的任务,如下所示。
The Java plugin adds a number of tasks to your project, as shown below.

表 23.1. Java 插件-任务
Table 23.1. Java plugin - tasks

任务名称
Task name
依赖于
Depends on
类型
Type
描述
Description
compileJava 产生编译类路径中的所有任务。这包括了用于 编译配置中包含的项目依赖关系的 jar任务。
All tasks which produce the compile classpath. This includes the jar task for project dependencies included in the compile configuration.
JavaCompile 使用 javac 编译产品中的 Java 源文件。
Compiles production Java source files using javac.
processResources - Copy 把生产资源文件拷贝到生产的类目录中。
Copies production resources into the production classes directory.
classes compileJavaprocessResources。一些插件添加了额外的编译任务。
compileJava and processResources . Some plugins add additional compilation tasks.
Task 组装生产的类目录。
Assembles the production classes directory.
compileTestJava compile,再加上所有能产生测试编译类路径的任务。
compile , plus all tasks which produce the test compile classpath.
JavaCompile 使用 javac 编译 Java 的测试源文件。
Compiles test Java source files using javac.
processTestResources - Copy 把测试的资源文件拷贝到测试的类目录中。
Copies test resources into the test classes directory.
testClasses compileTestJavaprocessTestResources。一些插件添加了额外的测试编译任务。
compileTestJava and processTestResources . Some plugins add additional test compilation tasks.
Task 组装测试的类目录。
Assembles the test classes directory.
jar compile Jar 组装 JAR 文件
Assembles the JAR file
javadoc compile Javadoc 使用 Javadoc 生成生产的 Java 源代码的API文档
Generates API documentation for the production Java source, using Javadoc
test compilecompileTest,再加上所有产生测试运行时类路径的任务。
compile , compileTest , plus all tasks which produce the test runtime classpath.
Test 使用 JUnit 或 TestNG运行单元测试。
Runs the unit tests using JUnit or TestNG.
uploadArchives 使用 archives的配置生成构件的任务,包括 jar
The tasks which produce the artifacts in the archives configuration, including jar .
Upload 使用 archives配置上传包括 JAR 文件的构件。
Uploads the artifacts in the archives configuration, including the JAR file.
clean - Delete 删除项目的build目录。
Deletes the project build directory.
cleanTaskName - Delete 删除由指定的任务所产生的输出文件。例如, cleanJar将删除由 jar任务中所创建的 JAR 文件, cleanTest将删除由 test任务所创建的测试结果。
Deletes the output files produced by the specified task. For example cleanJar will delete the JAR file created by the jar task, and cleanTest will delete the test results created by the test task.

对于每个你添加到该项目中的源集,Java 插件将添加以下的编译任务:
For each source set you add to the project, the Java plugin adds the following compilation tasks:

表 23.2. Java 插件-源集任务
Table 23.2. Java plugin - source set tasks

任务名称
Task name
依赖于
Depends on
类型
Type
描述
Description
compileSourceSet Java 所有产生源集编译类路径的任务。
All tasks which produce the source set's compile classpath.
JavaCompile 使用 javac 编译给定的源集中的 Java 源文件。
Compiles the given source set's Java source files using javac.
processSourceSet Resources - Copy 把给定的源集的资源文件拷贝到类目录中。
Copies the given source set's resources into the classes directory.
sourceSet Classes compile SourceSet Javaprocess SourceSet Resources。某些插件还为源集添加了额外的编译任务。
compileSourceSet Java and processSourceSet Resources . Some plugins add additional compilation tasks for the source set.
Task 组装给定源集的类目录。
Assembles the given source set's classes directory.

Java 插件还增加了大量的任务构成该项目的生命周期:
The Java plugin also adds a number of tasks which form a lifecycle for the project:

表 23.3. Java 插件-生命周期任务
Table 23.3. Java plugin - lifecycle tasks

任务名称
Task name
依赖于
Depends on
类型
Type
描述
Description
assemble 项目中的所有归档项目,包括 jar任务。某些插件还向项目添加额外的归档任务。
All archive tasks in the project, including jar . Some plugins add additional archive tasks to the project.
Task 组装项目中所有的归类文件。
Assembles all the archives in the project.
check 项目中的所有核查项目,包括 test任务。某些插件还向项目添加额外的核查任务。
All verification tasks in the project, including test . Some plugins add additional verification tasks to the project.
Task 执行项目中所有的核查任务。
Performs all verification tasks in the project.
build checkassemble
check and assemble
Task 执行项目的完整构建。
Performs a full build of the project.
buildNeeded build任务,以及在 testRuntime配置的所有项目库依赖项的 build任务。
build and build tasks in all project lib dependencies of the testRuntime configuration.
Task 执行项目本身及它所依赖的其他所有项目的完整构建。
Performs a full build of the project and all projects it depends on.
buildDependents build任务,以及在 testRuntime配置中对此项目有库依赖的所有项目的 build任务。
build and build tasks in all projects with a project lib dependency on this project in a testRuntime configuration.
Task 执行项目本身及依赖它的其他所有项目的完整构建。
Performs a full build of the project and all projects which depend on it.
buildConfigurationName 使用配置 ConfigurationName 生成构件的任务。
The tasks which produce the artifacts in configuration ConfigurationName .
Task 组装指定配置的构件。该任务由Base插件添加,并由Java插件隐式实现。
Assembles the artifacts in the specified configuration. The task is added by the Base plugin which is implicitly applied by the Java plugin.
uploadConfigurationName 使用配置 ConfigurationName 上传构件的任务。
The tasks which uploads the artifacts in configuration ConfigurationName .
Upload 组装并上传指定配置的构件。该任务由Base插件添加,并由Java插件隐式实现。
Assembles and uploads the artifacts in the specified configuration. The task is added by the Base plugin which is implicitly applied by the Java plugin.

下图显示了这些任务之间的关系。
The following diagram shows the relationships between these tasks.

图23.1. Java插件 ​​- 任务
Figure 23.1. Java plugin - tasks

Java插件 ​​- 任务

23.4. 项目布局

23.4. Project layout

Java 插件会假定如下所示的项目布局。这些目录都不需要一定存在,或者是里面有什么内容。Java插件将会进行编译,不管它发现什么,并处理缺少的任何东西。
The Java plugin assumes the project layout shown below. None of these directories need exist or have anything in them. The Java plugin will compile whatever it finds, and handles anything which is missing.

表 23.4. Java 插件-默认项目布局
Table 23.4. Java plugin - default project layout

目录
Directory
意义
Meaning
src/main/java 产品的Java源代码
Production Java source
src/main/resources 产品的资源
Production resources
src/test/java Java 测试源代码
Test Java source
src/test/resources 测试资源
Test resources
src/sourceSet /java 给定的源集的Java源代码
Java source for the given source set
src/sourceSet /resources 给定的源集的资源
Resources for the given source set

23.4.1. 更改项目布局

23.4.1. Changing the project layout

你可以通过配置适当的源集,来配置项目的布局。这一点将在以下各节中详细讨论。这里是如何更改main Java 和资源源目录的一个简短的例子。
You configure the project layout by configuring the appropriate source set. This is discussed in more detail in the following sections. Here is a brief example which changes the main Java and resource source directories.

示例 23.2. 自定义Java 源代码布局
Example 23.2. Custom Java source layout

build.gradle

sourceSets {
    main {
        java {
            srcDir 'src/java'
        }
        resources {
            srcDir 'src/resources'
        }
    }
}

23.5. 依赖管理

23.5. Dependency management

Java插件向项目添加了许多依赖配置,如下图所示。它对一些任务指定了这些配置,如 compileJavatest
The Java plugin adds a number of dependency configurations to your project, as shown below. It assigns those configurations to tasks such as compileJava and test .

表23.5. Java插件 ​​- 依赖配置
Table 23.5. Java plugin - dependency configurations

名称
Name
继承自
Extends
在哪些任务中使用
Used by tasks
意义
Meaning
compile - compileJava 编译时依赖
Compile time dependencies
runtime compile - 运行时依赖
Runtime dependencies
testCompile compile compileTestJava 用于编译测试的其他依赖
Additional dependencies for compiling tests.
testRuntime runtime, testCompile test 只用于运行测试的其他依赖
Additional dependencies for running tests only.
archives - uploadArchives 由本项目生产的构件(如jar包)。
Artifacts (e.g. jars) produced by this project.
default runtime - 本项目上的默认项目依赖配置。包含本项目运行时所需要的构件和依赖。
The default configuration used by a project dependency on this project. Contains the artifacts and dependencies required by this project at runtime.

图23.2. Java插件 ​​- 依赖配置
Figure 23.2. Java plugin - dependency configurations

Java plugin - dependency configurations

对于每个你添加到项目中的源集,Java插件都会添加以下的依赖配置:
For each source set you add to the project, the Java plugins adds the following dependency configurations:

表23.6. Java插件 ​​- 源集依赖配置
Table 23.6. Java plugin - source set dependency configurations

名称
Name
继承自
Extends
在哪些任务中使用
Used by tasks
意义
Meaning
sourceSet Compile - compile SourceSet Java 给定源集的编译时依赖
Compile time dependencies for the given source set
sourceSet Runtime sourceSet Compile - 给定源集的运行时依赖
Runtime time dependencies for the given source set

23.6. 常规属性

23.6. Convention properties

Java插件向项目添加了许多常规属性,如下图所示。您可以在构建脚本中使用这些属性,就像它们是project对象的属性一样(见 第21.3节,“约定”)。
The Java plugin adds a number of convention properties to the project, shown below. You can use these properties in your build script as though they were properties of the project object (see Section 21.3, “Conventions” ).

表23.7. Java插件 ​​- 目录属性
Table 23.7. Java plugin - directory properties

属性名称
Property name
类型
Type
默认值
Default value
描述
Description
reportsDirName String reports 相对于build目录的目录名称,报告将生成到此目录。
The name of the directory to generate reports into, relative to the build directory.
reportsDir File (read-only) buildDir / reportsDirName 报告将生成到此目录。
The directory to generate reports into.
testResultsDirName String test-results 相对于build目录的目录名称,测试报告的.xml文件将生成到此目录。
The name of the directory to generate test result .xml files into, relative to the build directory.
testResultsDir File (read-only) buildDir / testResultsDirName 测试报告的.xml文件将生成到此目录。
The directory to generate test result .xml files into.
testReportDirName String tests 相对于build目录的目录名称,测试报告将生成到此目录。
The name of the directory to generate the test report into, relative to the reports directory.
testReportDir File (read-only) reportsDir / testReportDirName 测试报告生成到此目录。
The directory to generate the test report into.
libsDirName String libs 相对于build目录的目录名称,类库将生成到此目录中。
The name of the directory to generate libraries into, relative to the build directory.
libsDir File (read-only) buildDir / libsDirName 类库将生成到此目录中。
The directory to generate libraries into.
distsDirName String distributions 相对于build目录的目录名称,发布的文件将生成到此目录中。
The name of the directory to generate distributions into, relative to the build directory.
distsDir File (read-only) buildDir / distsDirName 要发布的文件将生成到此目录。
The directory to generate distributions into.
docsDirName String docs 相对于build目录的目录名称,文档将生成到此目录。
The name of the directory to generate documentation into, relative to the build directory.
docsDir File (read-only) buildDir / docsDirName 要生成文档的目录。
The directory to generate documentation into.
dependencyCacheDirName String dependency-cache 相对于build目录的目录名称,该目录用于缓存源代码的依赖信息。
The name of the directory to use to cache source dependency information, relative to the build directory.
dependencyCacheDir File (read-only) buildDir / dependencyCacheDirName 该目录用于缓存源代码的依赖信息。
The directory to use to cache source dependency information.

表 23.8. Java 插件 - 其他属性
Table 23.8. Java plugin - other properties

属性名称
Property name
类型
Type
默认值
Default value
描述
Description
sourceSets SourceSetContainer (read-only) 非空
Not null
包含项目的源集。
Contains the project's source sets.
sourceCompatibility JavaVersion . 可以使用字符串或数字来设置,例如 "1.5"1.5
JavaVersion . Can also set using a String or a Number, e.g. '1.5' or 1.5 .
当前JVM所使用的值
Value of the current used JVM
当编译Java源代码时所使用的Java版本兼容性。
Java version compatibility to use when compiling Java source.
targetCompatibility JavaVersion . 可以使用字符串或数字来设置,例如 "1.5"1.5
JavaVersion . Can also set using a String or Number, e.g. '1.5' or 1.5 .
sourceCompatibility 要生成的类的 Java 版本。
Java version to generate classes for.
archivesBaseName String projectName 像JAR或ZIP文件这样的构件的basename
The basename to use for archives, such as JAR or ZIP files.
manifest Manifest 一个空的清单
an empty manifest
要包括的所有 JAR 文件的清单。
The manifest to include in all JAR files.

这些属性由 JavaPluginConvention BasePluginConvention ReportingBasePluginConvention 这些类型的常规对象提供。
These properties are provided by convention objects of type JavaPluginConvention , BasePluginConvention and ReportingBasePluginConvention .

23.7. 使用源集

23.7. Working with source sets

你可以使用 sourceSets属性访问项目的源集。这是项目的源集的容器,它的类型是 SourceSetContainer 。除此之后,还有一个 sourceSets {}的脚本块,可以传入一个闭包来配置源集容器。源集容器的使用方式几乎与其他容器一样,例如 tasks
You can access the source sets of a project using the sourceSets property. This is a container for the project's source sets, of type SourceSetContainer . There is also a sourceSets { } script block, which you can pass a closure to configure the source set container. The source set container works pretty much the same way as other containers, such as tasks .

示例 23.3. 访问源集
Example 23.3. Accessing a source set

build.gradle

// Various ways to access the main source set
println sourceSets.main.output.classesDir
println sourceSets['main'].output.classesDir
sourceSets {
    println main.output.classesDir
}
sourceSets {
    main {
        println output.classesDir
    }
}

// Iterate over the source sets
sourceSets.all {
    println name
}

要配置一个现有的源集,你只需使用上面的其中一种访问方法来设置源集的属性。这些属性将在下文中进行介绍。下面是一个配置main 的 Java 和资源目录的例子:
To configure an existing source set, you simply use one of the above access methods to set the properties of the source set. The properties are described below. Here is an example which configures the main Java and resources directories:

示例 23.4. 配置源集的源代码目录
Example 23.4. Configuring the source directories of a source set

build.gradle

sourceSets {
    main {
        java {
            srcDir 'src/java'
        }
        resources {
            srcDir 'src/resources'
        }
    }
}

23.7.1. 源集属性

23.7.1. Source set properties

下表列出了一些重要的源集属性。你可以在 SourceSet 的 API 文档中查看更多的详细信息。
The following table lists some of the important properties of a source set. You can find more details in the API documentation for SourceSet .

表 23.9. Java 插件 - 源集属性
Table 23.9. Java plugin - source set properties

属性名称
Property name
类型
Type
默认值
Default value
描述
Description
name String (read-only) 非空
Not null
用来确定一个源集的源集名称。
The name of the source set, used to identify it.
output SourceSetOutput (read-only) 非空
Not null
源集的输出文件,包含它编译过的类和资源。
The output files of the source set, containing its compiled classes and resources.
output.classesDir File buildDir /classes/ name 要生成的该源集的类的目录。
The directory to generate the classes of this source set into.
output.resourcesDir File buildDir /resources/ name 要生成的该源集的资源的目录。
The directory to generate the resources of this source set into.
compileClasspath FileCollection compile SourceSet 配置。
compileSourceSet configuration.
该类路径在编译该源集的源文件时使用。
The classpath to use when compiling the source files of this source set.
runtimeClasspath FileCollection output + runtime SourceSet 配置。
output + runtimeSourceSet configuration.
该类路径在执行该源集的类时使用。
The classpath to use when executing the classes of this source set.
java SourceDirectorySet (read-only) 非空
Not null
该源集的Java源文件。仅包含Java源文件目录里的 .java文件,并排除其他所有文件。
The Java source files of this source set. Contains only .java files found in the Java source directories, and excludes all other files.
java.srcDirs Set<File>. 可以使用 16.5 章节,"指定一组输入文件"中所讲到的任何一个来设置。
Set<File> . Can set using anything described in Section 16.5, “Specifying a set of input files” .
[projectDir /src/ name /java] 该源目录包含了此源集的所有Java源文件。
The source directories containing the Java source files of this source set.
resources SourceDirectorySet (read-only) 非空
Not null
此源集的资源文件。仅包含资源文件,并且排除在资源源目录中找到的所有 .java 文件。其他插件,如Groovy 插件,会从该集合中排除其他类型的文件。
The resources of this source set. Contains only resources, and excludes any .java files found in the resource source directories. Other plugins, such as the Groovy plugin, exclude additional types of files from this collection.
resources.srcDirs Set<File>. 可以使用 16.5 章节,"指定一组输入文件"中所讲到的任何一个来设置。
Set<File> . Can set using anything described in Section 16.5, “Specifying a set of input files” .
[projectDir /src/ name /resources] 该源目录包含了此源集的资源文件。
The source directories containing the resources of this source set.
allJava SourceDirectorySet (read-only) java 该源集的所有 .java 文件。有些插件,如Groovy 插件,会从该集合中增加其他的Java源文件。
All .java files of this source set. Some plugins, such as the Groovy plugin, add additional Java source files to this collection.
allSource SourceDirectorySet (read-only) resources + java 该源集的所有源文件。包含所有的资源文件和Java源文件。有些插件,如Groovy 插件,会从该集合中增加其他的源文件。
All source files of this source set. This include all resource files and all Java source files. Some plugins, such as the Groovy plugin, add additional source files to this collection.

23.7.2. 定义新的源集

23.7.2. Defining new source sets

要定义一个新的源集,你只需在 sourceSets { }块中引用它。下面是一个示例:
To define a new source set, you simply reference it in the sourceSets { } block. Here's an example:

示例 23.5. 定义一个源集
Example 23.5. Defining a source set

build.gradle

sourceSets {
    intTest
}

当您定义一个新的源集时,Java 插件会为该源集添加一些依赖配置,如 表 23.6,“Java 插件 - 源集依赖项配置”所示。你可以使用这些配置来定义源集的编译和运行时的依赖。
When you define a new source set, the Java plugin adds some dependency configurations for the source set, as shown in Table 23.6, “Java plugin - source set dependency configurations” . You can use these configurations to define the compile and runtime dependencies of the source set.

示例 23.6. 定义源集依赖
Example 23.6. Defining source set dependencies

build.gradle

sourceSets {
    intTest
}

dependencies {
    intTestCompile 'junit:junit:4.11'
    intTestRuntime 'org.ow2.asm:asm-all:4.0'
}

Java 插件还添加了大量的任务,用于组装源集的类,如 表 23.2,“Java 插件 - 源设置任务”所示。例如,对于一个被叫做 intTest的源集,你可以运行 gradle intTestClasses 来编译 int 测试类。
The Java plugin also adds a number of tasks which assemble the classes for the source set, as shown in Table 23.2, “Java plugin - source set tasks” . For example, for a source set called intTest , you can run gradle intTestClasses to compile the int test classes.

示例 23.7. 编译源集
Example 23.7. Compiling a source set

gradle intTestClasses 的输出结果
Output of gradle intTestClasses

> gradle intTestClasses
:compileIntTestJava
:processIntTestResources
:intTestClasses

BUILD SUCCESSFUL

Total time: 1 secs

23.7.3. 一些源集的范例

23.7.3. Some source set examples

添加一个包含了源集的类的JAR包
Adding a JAR containing the classes of a source set:

示例 23.8. 为一个源集装配一个JAR文件
Example 23.8. Assembling a JAR for a source set

build.gradle

task intTestJar(type: Jar) {
    from sourceSets.intTest.output
}

为一个源集生成 Javadoc:
Generating Javadoc for a source set:

示例 23.9. 为一个源集生成 Javadoc:
Example 23.9. Generating the Javadoc for a source set

build.gradle

task intTestJavadoc(type: Javadoc) {
    source sourceSets.intTest.allJava
}

添加一个测试套件以运行一个源集里的测试
Adding a test suite to run the tests in a source set:

示例 23.10. 运行源集里的测试
Example 23.10. Running tests in a source set

build.gradle

task intTest(type: Test) {
    testClassesDir = sourceSets.intTest.output.classesDir
    classpath = sourceSets.intTest.runtimeClasspath
}

23.8. Javadoc

23.8. Javadoc

Javadoc任务是 Javadoc 的一个实例。它支持核心的 javadoc 参数选项,以及在Javadoc可执行文件的 参考文档中描述的标准 doclet 参数选项。对于支持的 Javadoc 参数选项的完整列表,请参考下面的类的 API 文档: CoreJavadocOptions StandardJavadocDocletOptions
The javadoc task is an instance of Javadoc . It supports the core javadoc options and the options of the standard doclet described in the reference documentation of the Javadoc executable. For a complete list of supported Javadoc options consult the API documentation of the following classes: CoreJavadocOptions and StandardJavadocDocletOptions .

表 23.10. Java 插件 - Javadoc 属性
Table 23.10. Java plugin - Javadoc properties

任务属性
Task Property
类型
Type
默认值
Default Value
classpath FileCollection sourceSets.main.output + sourceSets.main.compileClasspath
source FileTree . 可以使用 16.5 章节,"指定一组输入文件"中所讲到的任何一种方式来设置。
FileTree . Can set using anything described in Section 16.5, “Specifying a set of input files” .
sourceSets.main.allJava
destinationDir File docsDir /javadoc
title String project的名称和版本
The name and version of the project

23.9. 清理

23.9. Clean

clean 任务是 Delete 的一个实例。它只是删除由其 dir属性表示的目录。
The clean task is an instance of Delete . It simply removes the directory denoted by its dir property.

表 23.11. Java 插件 - Clean 性能
Table 23.11. Java plugin - Clean properties

任务属性
Task Property
类型
Type
默认值
Default Value
dir File buildDir

23.10. 资源

23.10. Resources

Java 插件使用 Copy 任务进行资源的处理。它为该project里的每个源集添加一个实例。你可以在 16.6章节,“复制文件”中找到关于copy任务的更多信息。
The Java plugin uses the Copy task for resource handling. It adds an instance for each source set in the project. You can find out more about the copy task in Section 16.6, “Copying files” .

表 23.12. Java 插件-ProcessResources 属性
Table 23.12. Java plugin - ProcessResources properties

任务属性
Task Property
类型
Type
默认值
Default Value
srcDirs Object. 可以使用 16.5 章节,"指定一组输入文件"中所讲到的任何一个来设置。
Object . Can set using anything described in Section 16.5, “Specifying a set of input files” .
sourceSet .resources
destinationDir File. 可以使用 16.1 章节,“查找文件”中所讲到的任何一种方式来设置。
File . Can set using anything described in Section 16.1, “Locating files” .
sourceSet .output.resourcesDir

23.11. CompileJava

23.11. CompileJava

Java 插件为该project里的每个源集添加一个 JavaCompile 实例。一些最常见的配置选项如下所示。
The Java plugin adds a JavaCompile instance for each source set in the project. Some of the most common configuration options are shown below.

表 23.13. Java 插件- Compile属性
Table 23.13. Java plugin - Compile properties

任务属性
Task Property
类型
Type
默认值
Default Value
classpath FileCollection sourceSet .compileClasspath
source FileTree . 可以使用 16.5 章节,"指定一组输入文件"中所讲到的任何一种方式来设置。
FileTree . Can set using anything described in Section 16.5, “Specifying a set of input files” .
sourceSet .java
destinationDir File . sourceSet .output.classesDir

compile任务委派了Ant 的 javac 任务。将 options.useAnt设置为 false将绕过 Ant 任务,而激活 Gradle 的直接编译器集成。在未来的 Gradle 版本中,将把它作为默认设置。
The compile task delegates to Ant's javac task. Setting options.useAnt to false activates Gradle's direct compiler integration, bypassing the Ant task. In a future Gradle release, this will become the default.

默认情况下,Java 编译器在 Gradle 过程中运行。将 options.fork设置为 true将会使编译出现在一个单独的进程中。在 Ant javac 任务中,这意味着将会为每一个compile任务fork一个新的进程,而这将会使编译变慢。相反,Gradle 的直接编译器集成 (见上文) 将尽可能多地重用相同的编译器进程。在这两种情况下,使用 options.forkOptions指定的所有fork选项都将得到重视。
By default, the Java compiler runs in the Gradle process. Setting options.fork to true causes compilation to occur in a separate process. In the case of the Ant javac task, this means that a new process will be forked for each compile task, which can slow down compilation. Conversely, Gradle's direct compiler integration (see above) will reuse the same compiler process as much as possible. In both cases, all fork options specified with options.forkOptions will be honored.

23.12. Test

23.12. Test

test任务是 Test 的一个实例。它会自动检测和执行 test源集中的所有单元测试。测试执行完成后,它还会生成一份报告。同时支持 JUnit 和 TestNG。可以看一看 Test 的完整的 API。
The test task is an instance of Test . It automatically detects and executes all unit tests in the test source set. It also generates a report once test execution is complete. JUnit and TestNG are both supported. Have a look at Test for the complete API.

23.12.1. 测试执行

23.12.1. Test execution

测试在单独的 JVM中执行,与main构建进程隔离。 Test 任务的 API 可以让你控制什么时候开始。
Tests are executed in a separate JVM, isolated from the main build process. The Test task's API allows you some control over how this happens.

有大量的属性用于控制测试进程的启动。这包括系统属性、 JVM 参数和使用的 Java 可执行文件。
There are a number of properties which control how the test process is launched. This includes things such as system properties, JVM arguments, and the Java executable to use.

你可以指定是否要并行运行你的测试。Gradle 通过同时运行多个测试进程来提供并行测试的执行。每个测试进程会依次执行一个单一的测试,所以你一般不需要对你的测试做任何的配置来利用这一点。 maxParallelForks属性指定在给定的时间可以运行的测试进程的最大数。它的默认值是 1,也就是说,不并行执行测试。
You can specify whether or not to execute your tests in parallel. Gradle provides parallel test execution by running multiple test processes concurrently. Each test process executes only a single test at a time, so you generally don't need to do anything special to your tests to take advantage of this. The maxParallelForks property specifies the maximum number of test processes to run at any given time. The default is 1, that is, do not execute the tests in parallel.

测试进程程会为其将 org.gradle.test.worker系统属性设置为一个唯一标识符,这个标识符可以用于文件名称或其他资源标识符。
The test process sets the org.gradle.test.worker system property to a unique identifier for that test process, which you can use, for example, in files names or other resource identifiers.

你可以指定在执行了一定数量的测试类之后,重启那个测试进程。这是一个很有用的替代方案,让你的测试进程可以有很大的堆内存。 forkEvery属性指定了要在测试进程中执行的测试类的最大数。默认是每个测试进程中执行的测试数量不限。
You can specify that test processes should be restarted after it has executed a certain number of test classes. This can be a useful alternative to giving your test process a very large heap. The forkEvery property specifies the maximum number of test classes to execute in a test process. The default is to execute an unlimited number of tests in each test process.

该任务有一个 ignoreFailures属性,用以控制测试失败时的行为。test 会始终执行它检测到的每一个测试。如果 ignoreFailures为 false,并且有测试不通过,那它会停止继续构建。 IgnoreFailures的默认值为 false。
The task has an ignoreFailures property to control the behavior when tests fail. Test always executes every test that it detects. It stops the build afterwards if ignoreFailures is false and there are failing tests. The default value of ignoreFailures is false.

testLogging属性可以配置哪些测试事件需要记录,并且使用什么样的日志级别。默认情况下,对于每个失败的测试都只会打印一个简洁的消息。请参阅 TestLoggingContainer ,查看如何把你的测试日志打印调整为你的偏好设置。
The testLogging property allows to configure which test events are going to be logged and at which detail level. By default, a concise message will be logged for every failed test. See TestLoggingContainer for how to tune test logging to your preferences.

23.12.2. 调试

23.12.2. Debugging

test任务提供了一个 Test.getDebug() 属性,可以设置为启动,使JVM在执行测试之前,等待一个debugger连接到它的5005端口上。
The test task provides a Test.getDebug() property that can be set to launch to make the JVM wait for a debugger to attach to port 5005 before proceeding with test execution.

这也可以在调用时通过 --debug-vm task 选项进行启用。
This can also be enabled at invocation time via the --debug-jvm task option.

23.12.3. 测试过滤

23.12.3. Test filtering

从Gradle 1.10 开始,可以根据测试的名称模式,只包含指定的测试。过滤,相对于测试类的包含或排除,是一个不同的机制。它将在接下来的段落中进行描述( -Dtest.singletest.include和friends)。后者基于文件,比如测试实现类的物理位置。file-level 的测试选择不支持的很多有趣的情况,都可以用 test-level 过滤来做到。以下这些场景中,有一些Gradle现在就可以处理,而有一些则将在未来得到实现:
Starting with Gradle 1.10, it is possible to include only specific tests, based on the test name pattern. Filtering is a different mechanism than test class inclusion / exclusion that will be described in the next few paragraphs ( -Dtest.single , test.include and friends). The latter is based on files, e.g. the physical location of the test implementation class. File-level test selection does not support many interesting scenarios that are possible with test-level filtering. Some of them Gradle handles now and some will be satisfied in the future releases:

  • 在指定的测试的方法级别上进行过滤;执行单个测试方法
    Filtering at the level of specific test methods; executing a single test method
  • 基于自定义注解(以后实现)进行过滤
    Filtering based on custom annotations (future)
  • 基于测试层次结构进行过滤;执行所有继承了某一基类(以后实现)的测试
    Filtering based on test hierarchy; executing all tests that extend ceratain base class (future)
  • 基于一些自定义的运行时的规则进行过滤,例如某个系统属性或一些静态的特定值(以后实现)
    Filtering based on some custom runtime rule, e.g. particular value of a system property or some static state (future)

测试过滤功能具有以下的特征:
Test filtering feature has following characteristic:

  • 支持完整的限定类名称或完整的限定的方法名称,例如“org.gradle.SomeTest”、“org.gradle.SomeTest.someMethod”
    Fully qualified class name or fully qualified method name is supported, e.g. "org.gradle.SomeTest", "org.gradle.SomeTest.someMethod"
  • 通配符 “*” 支付匹配任何字符
    Wildcard '*' is supported for matching any characters
  • 提供了“--tests”的命令行选项,以方便地设置测试过滤器。这对“单一测试方法的执行”的经典用例特别有用。当使用该命令行选项选项时,在构建脚本中声明的列入过滤器的测试将会被忽略。
    Command line option "--tests" is provided to conveniently set the test filter. Especially useful for the classic 'single test method execution' use case. When the command line option is used, the inclusion filters declared in the build script are ignored.
  • Gradle 尽最大努力对有着特定的测试框架 API 的局限的测试进行过滤。一些高级的、 综合的测试可能不完全符合过滤条件。然而,绝大多数的测试和用例都会被很好地处理。
    Gradle tries best to filter the tests given limitations of particular test framework API. Some advanced, synthetic tests may not be fully compatible with filtering. However, vast majority of tests and use cases should be handled neatly.
  • 测试过滤将会取代基于文件的测试选择。后者可能在将来会被完全地取代掉。我们将会继续改进测试过滤的API,并添加更多种类的过滤器。
    Test filtering supersedes the file-based test selection. The latter may be completely replaced in future. We will grow the the test filtering api and add more kinds of filters.

示例 23.11. 在构建脚本中过滤测试
Example 23.11. Filtering tests in the build script

build.gradle

test {
    filter {
        //include specific method in any of the tests
        includeTestsMatching "*UiCheck"

        //include all tests from package
        includeTestsMatching "org.gradle.internal.*"

        //include all integration tests
        includeTestsMatching "*IntegTest"
    }
}



有关更多的详细信息和示例,请参阅 TestFilter 的文档。
For more details and examples please see the TestFilter reference.

使用命令行选项的一些示例:
Some examples of using the command line option:

  • gradle test --tests org.gradle.SomeTest.someSpecificFeature

  • gradle test --tests *SomeTest.someSpecificFeature

  • gradle test --tests *SomeSpecificTest

  • gradle test --tests all.in.specific.package*

  • gradle test --tests *IntegTest

  • gradle test --tests *IntegTest*ui*

  • gradle someTestTask --tests *UiTest someOtherTestTask --tests *WebTest*ui

23.12.4. 通过系统属性执行单一的测试

23.12.4. Single test execution via System Properties
这种机制已经被上述的“测试过滤”所取代。
This mechanism has been superseded by 'Test Filtering', described above.

设置一个 taskName.single = testNamePattern 的系统属性将会只执行匹配 testNamePattern 的那些测试。这个 taskName 可以是一个完整的多项目路径,比如“sub1:sub2:test”,或者仅是一个任务名称。 testNamePattern 将用于形成一个“**/testNamePattern*.class”的包含模式。如果这个模式无法找到任何测试,那么将会抛出一个异常。这是为了使你不会误以为测试通过。如果执行了一个以上的子项目的测试,该模式会被应用于每一个子项目中。如果在一个特定的子项目中,找不到测试用例,那么将会抛出异常。在这种情况下你可以使用路径标记法的模式,这样该模式就会只应用于特定的子项目的测试任务中。或者你可以指定要执行的任务的完整限定名称。你还可以指定多个模式。示例:
Setting a system property of taskName.single = testNamePattern will only execute tests that match the specified testNamePattern . The taskName can be a full multi-project path like ":sub1:sub2:test" or just the task name. The testNamePattern will be used to form an include pattern of "**/testNamePattern*.class". If no tests with this pattern can be found an exception is thrown. This is to shield you from false security. If tests of more than one subproject are executed, the pattern is applied to each subproject. An exception is thrown if no tests can be found for a particular subproject. In such a case you can use the path notation of the pattern, so that the pattern is applied only to the test task of a specific subproject. Alternatively you can specify the fully qualified task name to be executed. You can also specify multiple patterns. Examples:

  • gradle -Dtest.single=ThisUniquelyNamedTest test

  • gradle -Dtest.single=a/b/ test

  • gradle -DintegTest.single=*IntegrationTest integTest

  • gradle -Dtest.single=:proj1:test:Customer build

  • gradle -DintegTest.single=c/d/ :proj1:integTest

23.12.5. 测试检测

23.12.5. Test detection

Test任务通过检查编译过的测试类来检测哪些类是测试类。默认情况下它会扫描所有的 .class文件。您可以设置自定义的includes 或 excludes,这样就只有这些类才会被扫描。根据所使用的测试框架 (JUnit 或 TestNG),会使用不同的标准进行测试类的检测。
The Test task detects which classes are test classes by inspecting the compiled test classes. By default it scans all .class files. You can set custom includes / excludes, only those classes will be scanned. Depending on the test framework used (JUnit / TestNG) the test class detection uses different criteria.

当使用 JUnit 时,我们扫描 JUnit 3 和 4 的测试类。如果满足以下的任何一个条件,这个类就被认为是一个 JUnit 测试类:
When using JUnit, we scan for both JUnit 3 and 4 test classes. If any of the following criteria match, the class is considered to be a JUnit test class:

  • 类或超类继承自 TestCaseGroovyTestCase
    Class or a super class extends TestCase or GroovyTestCase

  • 类或超类使用了 @RunWith进行注解
    Class or a super class is annotated with @RunWith

  • 类或超类含有一个带 @Test 注解的方法
    Class or a super class contain a method annotated with @Test

当使用 TestNG 时,我们扫描所有带有 @Test注解的方法。
When using TestNG, we scan for methods annotated with @Test .

请注意,抽象类不会被执行。Gradle 还将扫描测试类路径中的 jar 文件里的继承树。
Note that abstract classes are not executed. Gradle also scan up the inheritance tree into jar files on the test classpath.

如果你不想要使用测试类检测,可以通过设置 scanForTestClasses为 false 来禁用它。这将使test任务只使用includes / excludes 来找到测试类。如果 scanForTestClasses为disabled,并且没有指定 include或exclude模式,则使用各自的默认值。对于 include 的默认值是 "**/*Tests.class", "**/*Test.class",而对于exclude它的默认值是 "**/Abstract*.class"
In case you don't want to use the test class detection, you can disable it by setting scanForTestClasses to false. This will make the test task only use the includes / excludes to find test classes. If scanForTestClasses is disabled and no include or exclude patterns are specified, the respective defaults are used. For include this is "**/*Tests.class", "**/*Test.class" and the for exclude it is "**/Abstract*.class" .

23.12.6. 测试分组

23.12.6. Test grouping

JUnit 和 TestNG 可以对测试方法进行复杂的分组。
JUnit and TestNG allows sophisticated groupings of test methods.

为对Junit 测试类和方法进行分组,JUnit 4.8引入了类别的概念。 [ 9] test任务可以实现一个规范,让你include和exclude 想要的 JUnit 类别。
For grouping JUnit test classes and methods JUnit 4.8 introduces the concept of categories. [ 9 ] The test task allows the specification of the JUnit categories you want to include and exclude.

示例 23.12. JUnit 类别
Example 23.12. JUnit Categories

build.gradle

test {
    useJUnit {
        includeCategories 'org.gradle.junit.CategoryA'
        excludeCategories 'org.gradle.junit.CategoryB'
    }
}

TestNG 框架有一个非常相似的概念。在 TestNG 中你可以指定不同的测试组。 [ 10]应从测试执行中include或exclude的测试组,可以在test任务中配置。
The TestNG framework has a quite similar concept. In TestNG you can specify different test groups. [ 10 ] The test groups that should be included or excluded from the test execution can be configured in the test task.

示例 23.13. 对TestNG 测试分组
Example 23.13. Grouping TestNG tests

build.gradle

test {
    useTestNG {
        excludeGroups 'integrationTests'
        includeGroups 'unitTests'
    }
}

23.12.7. 测试报告

23.12.7. Test reporting

test任务默认情况下会生成以下结果。
The Test task generates the following results by default.

  • 一个 HTML 测试报告。
    An HTML test report.

  • 与Ant Junit report 任务兼容的 XML 格式的结果。这种格式可以被许多工具所支持,比如CI服务器。
    The results in an XML format that is compatible with the Ant JUnit report task. This format is supported by many other tools, such as CI servers.

  • 有效二进制格式的结果。这个任务会从这些二进制结果生成其他的结果。
    Results in an efficient binary format. The task generates the other results from these binary results.

您可以使用 Test.setTestReport() 方法来禁用 HTML 测试报告。目前不能禁用其他的结果。
You can disable the HTML test report using the Test.setTestReport() method. The other results currently cannot be disabled.

这里还有一个独立的 TestReport 任务类型,它可以从一个或多个 Test任务实例生成的二进制结果中生成 HTML 测试报告。要使用这个任务类型,你需要定义一个 destinationDir和要包含到报告的测试结果。这里是一个范例,从子项目的单元测试中生成一个联合报告:
There is also a stand-alone TestReport task type which can generate the HTML test report from the binary results generated by one or more Test task instances. To use this task type, you need to define a destinationDir and the test results to include in the report. Here is a sample which generates a combined report for the unit tests from subprojects:

示例 23.14. 为多个子项目创建一个单元测试报告
Example 23.14. Creating a unit test report for subprojects

build.gradle

subprojects {
    apply plugin: 'java'

    // Disable the test report for the individual test task
    test {
        reports.html.enabled = false
    }
}

task testReport(type: TestReport) {
    destinationDir = file("$buildDir/reports/allTests")
    // Include the results from the `test` task in all subprojects
    reportOn subprojects*.test
}

你应该注意到, TestReport类型组合了多个测试任务的结果,并且需要聚合各个测试类的结果。这意味着,如果一个给定的测试类被多个test任务所执行,那么测试报告将包括那个类的所有执行结果,但它难以区分那个类的每次执行和它们的输出。
You should note that the TestReport type combines the results from multiple test tasks and needs to aggregate the results of individual test classes. This means that if a given test class is executed by multiple test tasks, then the test report will include executions of that class, but it can be hard to distinguish individual executions of that class and their output.

23.12.7.1. TestNG 参数化方法和报告

23.12.7.1. TestNG parameterized methods and reporting

TestNG 支持 参数化测试方法,允许一个特定的测试方法使用不同的输入执行多次。Gradle 会在这个方法的执行报告中包含进它的参数值。
TestNG supports parameterizing test methods , allowing a particular test method to be executed multiple times with different inputs. Gradle includes the parameter values in its reporting of the test method execution.

给定一个带有两个参数,名为 aParameterizedTestMethod参数化测试方法,它将使用名称这个名称进行报告 : aParameterizedTestMethod(toStringValueOfParam1, toStringValueOfParam2)。这使得在特定的迭代过程,很容易确定参数值。
Given a parameterized test method named aParameterizedTestMethod that takes two parameters, it will be reported with the name: aParameterizedTestMethod(toStringValueOfParam1, toStringValueOfParam2) . This makes identifying the parameter values for a particular iteration easy.

23.12.8. 常规值

23.12.8. Convention values

表 23.14. Java 插件 - test属性
Table 23.14. Java plugin - test properties

任务属性
Task Property
类型
Type
默认值
Default Value
testClassesDir File sourceSets.test.output.classesDir
classpath FileCollection sourceSets.test.runtimeClasspath
testResultsDir File testResultsDir
testReportDir File testReportDir
testSrcDirs List<File> sourceSets.test.java.srcDirs

23.13. Jar

23.13. Jar

Jar任务创建一个包含类文件和项目资源的 JAR 文件。JAR 文件在 archives依赖配置中被声明为一个构件。这意味着这个JAR文件被包含在一个依赖它的项目的类路径中。如果你把你的项目上传到仓库,这个JAR 文件会被声明为依赖描述符的一部分。你可以在 第16.8节,“创建档案”第51章, 发布artifact中了解如何使用archives和配置artifact。
The jar task creates a JAR file containing the class files and resources of the project. The JAR file is declared as an artifact in the archives dependency configuration. This means that the JAR is available in the classpath of a dependent project. If you upload your project into a repository, this JAR is declared as part of the dependency descriptor. You can learn more about how to work with archives in Section 16.8, “Creating archives” and artifact configurations in Chapter 51, Publishing artifacts .

23.13.1. Manifest

23.13.1. Manifest

每个 jar 或war 对象都有一个单独的 Manifest 实例的 manifest属性。当生成archive时,相应的 MANIFEST.MF文件也会被写入进去。
Each jar or war object has a manifest property with a separate instance of Manifest . When the archive is generated, a corresponding MANIFEST.MF file is written into the archive.

示例 23.15. 自定义的MANIFEST.MF
Example 23.15. Customization of MANIFEST.MF

build.gradle

jar {
    manifest {
        attributes("Implementation-Title": "Gradle", "Implementation-Version": version)
    }
}

您可以创建一个单独的 Manifest实例。它可以用于共享两个jar包的manifest 信息。
You can create stand alone instances of a Manifest . You can use that for example, to share manifest information between jars.

示例 23.16. 创建一个manifest 对象。
Example 23.16. Creating a manifest object.

build.gradle

ext.sharedManifest = manifest {
    attributes("Implementation-Title": "Gradle", "Implementation-Version": version)
}
task fooJar(type: Jar) {
    manifest = project.manifest {
        from sharedManifest
    }
}

你可以把其他的manifest 合并到任何一个 Manifest对象中。其他的manifest可能使用文件路径来描述,像上面的例子,使用对另一个 Manifest对象的引用。
You can merge other manifests into any Manifest object. The other manifests might be either described by a file path or, like in the example above, by a reference to another Manifest object.

示例 23.17. 指定archive的单独MANIFEST.MF
Example 23.17. Separate MANIFEST.MF for a particular archive

build.gradle

task barJar(type: Jar) {
    manifest {
        attributes key1: 'value1'
        from sharedManifest, 'src/config/basemanifest.txt'
        from('src/config/javabasemanifest.txt', 'src/config/libbasemanifest.txt') {
            eachEntry { details ->
                if (details.baseValue != details.mergeValue) {
                    details.value = baseValue
                }
                if (details.key == 'foo') {
                    details.exclude()
                }
            }
        }
    }
}

Manifest会根据在 from语句中所声明的顺序进行合并。如果基本的manifest和要合并的manifest都定义了同一个key的值,那么默认情况下会采用要合并的manifest的值。你可以通过添加 eachEntry action 来完全自定义合并行为,它可以让你对每一项生成的manifest 访问它的一个 ManifestMergeDetails 实例。这个合并操作不会在from语句中就马上被触发。它是懒执行的,不管是对于生成一个jar包,还是调用了 writeTo 或者 effectiveManifest
Manifest are merged in the order they are declared by the from statement. If the based manifest and the merged manifest both define values for the same key, the merged manifest wins by default. You can fully customize the merge behavior by adding eachEntry actions in which you have access to a ManifestMergeDetails instance for each entry of the resulting manifest. The merge is not immediately triggered by the from statement. It is done lazily, either when generating the jar, or by calling writeTo or effectiveManifest

你可以很轻松地把一个manifest写入磁盘中。
You can easily write a manifest to disk.

示例 23.18. 指定archive的单独 MANIFEST.MF
Example 23.18. Separate MANIFEST.MF for a particular archive

build.gradle

jar.manifest.writeTo("$buildDir/mymanifest.mf")

23.14. 上传

23.14. Uploading

关于如何上传archives,将在 第51章, 发布artifacts中进行描述。
How to upload your archives is described in Chapter 51, Publishing artifacts .



[ 9] JUnit wiki 包含了有关如何使用 JUnit 类别的详细说明: https://github.com/junit-team/junit/wiki/Categories
[ 9 ] The JUnit wiki contains a detailed description on how to work with JUnit categories: https://github.com/junit-team/junit/wiki/Categories .

[ 10] TestNG 文档包含了有关测试组的更多详细信息: http://testng.org/doc/documentation-main.html#test-groups
[ 10 ] The TestNG documentation contains more details about test groups: http://testng.org/doc/documentation-main.html#test-groups .