Gradle Java 插件

2022-08-03 14:58 更新

Java 插件向一個項目添加了 Java 編譯、 測試和 bundling 的能力。它是很多其他 Gradle 插件的基礎(chǔ)服務(wù)。

用法

要使用 Java 插件,請在構(gòu)建腳本中加入:

使用 Java 插件

build.gradle

apply plugin: 'java'  

源集

Java 插件引入了一個源集的概念。一個源集只是一組用于編譯并一起執(zhí)行的源文件。這些源文件可能包括 Java 源代碼文件和資源文件。其他有一些插件添加了在源集里包含 Groovy 和 Scala 的源代碼文件的能力。一個源集有一個相關(guān)聯(lián)的編譯類路徑和運行時類路徑。

源集的一個用途是,把源文件進行邏輯上的分組,以描述它們的目的。例如,你可能會使用一個源集來定義一個集成測試套件,或者你可能會使用單獨的源集來定義你的項目的 API 和實現(xiàn)類。

Java 插件定義了兩個標準的源集,分別是 main 和 test。main 源集包含你產(chǎn)品的源代碼,它們將被編譯并組裝成一個 JAR 文件。test 源集包含你的單元測試的源代碼,它們將被編譯并使用 JUnit 或 TestNG 來執(zhí)行。

任務(wù)

Java 插件向你的項目添加了大量的任務(wù),如下所示。

表 23.1. Java 插件-任務(wù)

任務(wù)名稱 依賴于 類型 描述
compileJava 產(chǎn)生編譯類路徑中的所有任務(wù)。這包括了用于jar任務(wù)。 JavaCompile 使用 javac 編譯產(chǎn)品中的 Java 源文件。
processResources - Copy 把生產(chǎn)資源文件拷貝到生產(chǎn)的類目錄中。
classes processResources。一些插件添加了額外的編譯任務(wù)。 Task 組裝生產(chǎn)的類目錄。
compileTestJava compile,再加上所有能產(chǎn)生測試編譯類路徑的任務(wù)。 JavaCompile 使用 javac 編譯 Java 的測試源文件。
processTestResources - Copy 把測試的資源文件拷貝到測試的類目錄中。
testClasses processTestResources。一些插件添加了額外的測試編譯任務(wù)。 Task 組裝測試的類目錄。
jar compile Jar 組裝 JAR 文件
javadoc compile Javadoc 使用 Javadoc 生成生產(chǎn)的 Java 源代碼的API文檔
test compileTest,再加上所有產(chǎn)生測試運行時類路徑的任務(wù)。 Test 使用 JUnit 或 TestNG運行單元測試。
uploadArchives 使用jar。 Upload 使用archives配置上傳包括 JAR 文件的構(gòu)件。
clean - Delete 刪除項目的 build 目錄。
TaskName - Delete 刪除由指定的任務(wù)所產(chǎn)生的輸出文件。例如, jar任務(wù)中所創(chuàng)建的 JAR 文件,test任務(wù)所創(chuàng)建的測試結(jié)果。

對于每個你添加到該項目中的源集,Java 插件將添加以下的編譯任務(wù):

表 23.2. Java 插件-源集任務(wù)

任務(wù)名稱 依賴于 類型 描述
SourceSetJava 所有產(chǎn)生源集編譯類路徑的任務(wù)。 JavaCompile 使用 javac 編譯給定的源集中的 Java 源文件。
SourceSetResources - Copy 把給定的源集的資源文件拷貝到類目錄中。
sourceSetClasses SourceSetResources。某些插件還為源集添加了額外的編譯任務(wù)。 Task 組裝給定源集的類目錄。

Java 插件還增加了大量的任務(wù)構(gòu)成該項目的生命周期:

表 23.3. Java 插件-生命周期任務(wù)

任務(wù)名稱 依賴于 類型 描述
assemble 項目中的所有歸檔項目,包括jar任務(wù)。某些插件還向項目添加額外的歸檔任務(wù)。 Task 組裝項目中所有的歸類文件。
check 項目中的所有核查項目,包括test任務(wù)。某些插件還向項目添加額外的核查任務(wù)。 Task 執(zhí)行項目中所有的核查任務(wù)。
build assemble Task 執(zhí)行項目的完事構(gòu)建。
buildNeeded build任務(wù)。 Task 執(zhí)行項目本身及它所依賴的其他所有項目的完整構(gòu)建。
buildDependents build任務(wù)。 Task 執(zhí)行項目本身及依賴它的其他所有項目的完整構(gòu)建。
ConfigurationName 使用配置ConfigurationName生成構(gòu)件的任務(wù)。 Task 組裝指定配置的構(gòu)件。該任務(wù)由Base插件添加,并由Java插件隱式實現(xiàn)。
ConfigurationName 使用配置ConfigurationName上傳構(gòu)件的任務(wù)。 Upload 組裝并上傳指定配置的構(gòu)件。該任務(wù)由Base插件添加,并由Java插件隱式實現(xiàn)。

uploadConfigurationName 使用配置 ConfigurationName 上傳構(gòu)件的任務(wù)。 Upload 組裝并上傳指定配置的構(gòu)件。該任務(wù)由 Base 插件添加,并由 Java 插件隱式實現(xiàn)。 下圖顯示了這些任務(wù)之間的關(guān)系。

圖23.1. Java 插件 ??- 任務(wù)

Java 插件 ??- 任務(wù)

項目布局

Java 插件會假定如下所示的項目布局。這些目錄都不需要一定存在,或者是里面有什么內(nèi)容。Java 插件將會進行編譯,不管它發(fā)現(xiàn)什么,并處理缺少的任何東西。

表 23.4. Java 插件-默認項目布局

目錄 意義
src/main/java 產(chǎn)品的Java源代碼
src/main/resources 產(chǎn)品的資源
src/test/java Java 測試源代碼
src/test/resources 測試資源
sourceSet/java 給定的源集的Java源代碼
sourceSet/resources 給定的源集的資源

更改項目布局

你可以通過配置適當?shù)脑醇?,來配置項目的布局。這一點將在以下各節(jié)中詳細討論。這里是如何更改 main Java 和資源源目錄的一個簡短的例子。

自定義 Java 源代碼布局

build.gradle

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

依賴管理

Java 插件向項目添加了許多依賴配置,如下圖所示。它對一些任務(wù)指定了這些配置,如 compileJava 和 test。

表23.5. Java插件 ??- 依賴配置

名稱 繼承自 在哪些任務(wù)中使用 意義
compile - compileJava 編譯時依賴
runtime compile - 運行時依賴
testCompile compile compileTestJava 用于編譯測試的其他依賴
testRuntime runtime, testCompile test 只用于運行測試的其他依賴
archives - uploadArchives 由本項目生產(chǎn)的構(gòu)件(如jar包)。
default runtime - 本項目上的默認項目依賴配置。包含本項目運行時所需要的構(gòu)件和依賴。

圖23.2. Java 插件 ??- 依賴配置

Java 插件 ??- 依賴配置

對于每個你添加到項目中的源集,Java 插件都會添加以下的依賴配置:

表23.6. Java 插件 ??- 源集依賴配置

名稱 繼承自 在哪些任務(wù)中使用 意義
sourceSetCompile - compileSourceSetJava 給定源集的編譯時依賴
sourceSetRuntime sourceSetCompile - 給定源集的運行時依賴

常規(guī)屬性

Java 插件向項目添加了許多常規(guī)屬性,如下圖所示。您可以在構(gòu)建腳本中使用這些屬性,就像它們是 project 對象的屬性一樣。

表23.7. Java 插件 ??- 目錄屬性

屬性名稱 類型 默認值 描述
reportsDirName String reports 相對于build目錄的目錄名稱,報告將生成到此目錄。
reportsDir File (read-only) reportsDirName 報告將生成到此目錄。
testResultsDirName String test-results 相對于build目錄的目錄名稱,測試報告的.xml文件將生成到此目錄。
testResultsDir File (read-only) testResultsDirName 測試報告的.xml文件將生成到此目錄。
testReportDirName String tests 相對于build目錄的目錄名稱,測試報告將生成到此目錄。
testReportDir File (read-only) testReportDirName 測試報告生成到此目錄。
libsDirName String libs 相對于build目錄的目錄名稱,類庫將生成到此目錄中。
libsDir File (read-only) libsDirName 類庫將生成到此目錄中。
distsDirName String distributions 相對于build目錄的目錄名稱,發(fā)布的文件將生成到此目錄中。
distsDir File (read-only) distsDirName 要發(fā)布的文件將生成到此目錄。
docsDirName String docs 相對于build目錄的目錄名稱,文檔將生成到此目錄。
docsDir File (read-only) docsDirName 要生成文檔的目錄。
dependencyCacheDirName String dependency-cache 相對于build目錄的目錄名稱,該目錄用于緩存源代碼的依賴信息。
dependencyCacheDir File (read-only) dependencyCacheDirName 該目錄用于緩存源代碼的依賴信息。

表 23.8. Java 插件 - 其他屬性

屬性名稱 類型 默認值 描述
sourceSets SourceSetContainer (read-only) 非空 包含項目的源集。
sourceCompatibility JavaVersion. 可以使用字符串或數(shù)字來設(shè)置,例如1.5。 當前JVM所使用的值 當編譯Java源代碼時所使用的Java版本兼容性。
targetCompatibility JavaVersion. 可以使用字符串或數(shù)字來設(shè)置,例如1.5 sourceCompatibility 要生成的類的 Java 版本。
archivesBaseName String projectName 像JAR或ZIP文件這樣的構(gòu)件的basename
manifest Manifest 一個空的清單 要包括的所有 JAR 文件的清單。

這些屬性由 JavaPluginConvention, BasePluginConvention 和 ReportingBasePluginConvention 這些類型的常規(guī)對象提供。

使用源集

你可以使用 sourceSets 屬性訪問項目的源集。這是項目的源集的容器,它的類型是 SourceSetContainer。除此之后,還有一個 sourceSets {}的腳本塊,可以傳入一個閉包來配置源集容器。源集容器的使用方式幾乎與其他容器一樣,例如 tasks。

訪問源集

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
}  

要配置一個現(xiàn)有的源集,你只需使用上面的其中一種訪問方法來設(shè)置源集的屬性。這些屬性將在下文中進行介紹。下面是一個配置 main 的 Java 和資源目錄的例子:

配置源集的源代碼目錄

build.gradle

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

源集屬性

下表列出了一些重要的源集屬性。你可以在 SourceSet 的 API 文檔中查看更多的詳細信息。

表 23.9. Java 插件 - 源集屬性

屬性名稱 類型 默認值 描述
name String (read-only) 非空 用來確定一個源集的源集名稱。
output SourceSetOutput (read-only) 非空 源集的輸出文件,包含它編譯過的類和資源。
output.classesDir File name 要生成的該源集的類的目錄。
output.resourcesDir File name 要生成的該源集的資源的目錄。
compileClasspath FileCollection SourceSet 配置。 該類路徑在編譯該源集的源文件時使用。
runtimeClasspath FileCollection SourceSet 配置。 該類路徑在執(zhí)行該源集的類時使用。
java SourceDirectorySet (read-only) 非空 該源集的Java源文件。僅包含Java源文件目錄里的.java文件,并排除其他所有文件。
java.srcDirs Set<File> name/java] 該源目錄包含了此源集的所有Java源文件。
resources SourceDirectorySet (read-only) 非空 此源集的資源文件。僅包含資源文件,并且排除在資源源目錄中找到的所有 .java文件。其他插件,如Groovy 插件,會從該集合中排除其他類型的文件。
resources.srcDirs Set<File> name/resources] 該源目錄包含了此源集的資源文件。
allJava SourceDirectorySet (read-only) java 該源集的所有.java 文件。有些插件,如Groovy 插件,會從該集合中增加其他的Java源文件。
allSource SourceDirectorySet (read-only) resources + java 該源集的所有源文件。包含所有的資源文件和Java源文件。有些插件,如Groovy 插件,會從該集合中增加其他的源文件。

定義新的源集

要定義一個新的源集,你只需在 sourceSets {}塊中引用它。下面是一個示例:

定義一個源集

build.gradle

sourceSets {
    intTest
}  

當您定義一個新的源集時,Java 插件會為該源集添加一些依賴配置,如表 23.6,“Java 插件 - 源集依賴項配置”所示。你可以使用這些配置來定義源集的編譯和運行時的依賴。

定義源集依賴

build.gradle

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

Java 插件還添加了大量的任務(wù),用于組裝源集的類,如表 23.2,“Java 插件 - 源設(shè)置任務(wù)”所示。例如,對于一個被叫做 intTest 的源集,你可以運行 gradle intTestClasses 來編譯 int 測試類。

編譯源集

gradle intTestClasses的輸出結(jié)果

> gradle intTestClasses
:compileIntTestJava
:processIntTestResources
:intTestClasses
BUILD SUCCESSFUL
Total time: 1 secs  

一些源集的范例

添加一個包含了源集的類的 JAR 包

示例 23.8. 為一個源集裝配一個JAR文件

build.gradle

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

為一個源集生成 Javadoc:

示例 23.9. 為一個源集生成 Javadoc:

build.gradle

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

添加一個測試套件以運行一個源集里的測試

示例 23.10. 運行源集里的測試

build.gradle

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

Javadoc

Javadoc 任務(wù)是 Javadoc 的一個實例。它支持核心的 javadoc 參數(shù)選項,以及在 Javadoc 可執(zhí)行文件的參考文檔中描述的標準 doclet 參數(shù)選項。對于支持的 Javadoc 參數(shù)選項的完整列表,請參考下面的類的 API 文檔: CoreJavadocOptions 和StandardJavadocDocletOptions。

表 23.10. Java 插件 - Javadoc 屬性

任務(wù)屬性 類型 默認值
classpath FileCollection sourceSets.main.output + sourceSets.main.compileClasspath
source FileTree. sourceSets.main.allJava
destinationDir File docsDir/javadoc
title String project的名稱和版本

清理

clean 任務(wù)是 Delete 的一個實例。它只是刪除由其 dir 屬性表示的目錄。

表 23.11. Java 插件 - Clean 性能

任務(wù)屬性 類型 默認值
dir File buildDir

資源

Java 插件使用 Copy 任務(wù)進行資源的處理。它為該 project 里的每個源集添加一個實例。你可以在16.6章節(jié),“復(fù)制文件”中找到關(guān)于 copy 任務(wù)的更多信息。

表 23.12. Java 插件-ProcessResources 屬性

任務(wù)屬性 類型 默認值
srcDirs Object. sourceSet.resources
destinationDir  16.1 章節(jié),“查找文件”中所講到的任何一種方式來設(shè)置。 sourceSet.output.resourcesDir

CompileJava

Java 插件為該 project 里的每個源集添加一個 JavaCompile 實例。一些最常見的配置選項如下所示。

表 23.13. Java 插件- Compile 屬性

任務(wù)屬性 類型 默認值
classpath FileCollection sourceSet.compileClasspath
source FileTree sourceSet.java
destinationDir File. sourceSet.output.classesDir

compile 任務(wù)委派了 Ant 的 javac 任務(wù)。將 options.useAnt 設(shè)置為 false 將繞過 Ant 任務(wù),而激活 Gradle 的直接編譯器集成。在未來的 Gradle 版本中,將把它作為默認設(shè)置。

默認情況下,Java 編譯器在 Gradle 過程中運行。將 options.fork 設(shè)置為 true 將會使編譯出現(xiàn)在一個單獨的進程中。在 Ant javac 任務(wù)中,這意味著將會為每一個 compile 任務(wù)fork 一個新的進程,而這將會使編譯變慢。相反,Gradle 的直接編譯器集成 (見上文) 將盡可能多地重用相同的編譯器進程。在這兩種情況下,使用 options.forkOptions 指定的所有fork 選項都將得到重視。

Test

test 任務(wù)是 Test 的一個實例。它會自動檢測和執(zhí)行 test 源集中的所有單元測試。測試執(zhí)行完成后,它還會生成一份報告。同時支持 JUnit 和 TestNG。可以看一看Test的完整的 API。

測試執(zhí)行

測試在單獨的 JVM 中執(zhí)行,與 main 構(gòu)建進程隔離。Test 任務(wù)的 API 可以讓你控制什么時候開始。

有大量的屬性用于控制測試進程的啟動。這包括系統(tǒng)屬性、 JVM 參數(shù)和使用的 Java 可執(zhí)行文件。

你可以指定是否要并行運行你的測試。Gradle 通過同時運行多個測試進程來提供并行測試的執(zhí)行。每個測試進程會依次執(zhí)行一個單一的測試,所以你一般不需要對你的測試做任何的配置來利用這一點。 MaxParallelForks 屬性指定在給定的時間可以運行的測試進程的最大數(shù)。它的默認值是 1,也就是說,不并行執(zhí)行測試。

測試進程程會為其將 org.gradle.test.worker 系統(tǒng)屬性設(shè)置為一個唯一標識符,這個標識符可以用于文件名稱或其他資源標識符。

你可以指定在執(zhí)行了一定數(shù)量的測試類之后,重啟那個測試進程。這是一個很有用的替代方案,讓你的測試進程可以有很大的堆內(nèi)存。forkEvery 屬性指定了要在測試進程中執(zhí)行的測試類的最大數(shù)。默認是每個測試進程中執(zhí)行的測試數(shù)量不限。

該任務(wù)有一個 ignoreFailures 屬性,用以控制測試失敗時的行為。test 會始終執(zhí)行它檢測到的每一個測試。如果 ignoreFailures 為 false,并且有測試不通過,那它會停止繼續(xù)構(gòu)建。IgnoreFailures 的默認值為 false。

testLogging 屬性可以配置哪些測試事件需要記錄,并且使用什么樣的日志級別。默認情況下,對于每個失敗的測試都只會打印一個簡潔的消息。請參閱 TestLoggingContainer,查看如何把你的測試日志打印調(diào)整為你的偏好設(shè)置。

調(diào)試

test 任務(wù)提供了一個 Test.getDebug()屬性,可以設(shè)置為啟動,使 JVM 在執(zhí)行測試之前,等待一個 debugger 連接到它的 5005 端口上。

這也可以在調(diào)用時通過--debug-vm task 選項進行啟用。

測試過濾

從 Gradle 1.10 開始,可以根據(jù)測試的名稱模式,只包含指定的測試。過濾,相對于測試類的包含或排除,是一個不同的機制。它將在接下來的段落中進行描述(-Dtest.single, test.include 和 friends)。后者基于文件,比如測試實現(xiàn)類的物理位置。file-level 的測試選擇不支持的很多有趣的情況,都可以用 test-level 過濾來做到。以下這些場景中,有一些 Gradle 現(xiàn)在就可以處理,而有一些則將在未來得到實現(xiàn):

  • 在指定的測試的方法級別上進行過濾;執(zhí)行單個測試方法
  • 基于自定義注解(以后實現(xiàn))進行過濾
  • 基于測試層次結(jié)構(gòu)進行過濾 ;執(zhí)行所有繼承了某一基類(以后實現(xiàn)) 的測試
  • 基于一些自定義的運行時的規(guī)則進行過濾,例如某個系統(tǒng)屬性或一些靜態(tài)的特定值(以后實現(xiàn))

測試過濾功能具有以下的特征:

  • 支持完整的限定類名稱或完整的限定的方法名稱,例如“org.gradle.SomeTest”、“org.gradle.SomeTest.someMethod”
  • 通配符 “*” 支付匹配任何字符
  • 提供了“--tests”的命令行選項,以方便地設(shè)置測試過濾器。這對“單一測試方法的執(zhí)行”的經(jīng)典用例特別有用。當使用該命令行選項選項時,在構(gòu)建腳本中聲明的列入過濾器的測試將會被忽略。
  • Gradle 盡最大努力對有著特定的測試框架 API 的局限的測試進行過濾。一些高級的、 綜合的測試可能不完全符合過濾條件。然而,絕大多數(shù)的測試和用例都會被很好地處理。
  • 測試過濾將會取代基于文件的測試選擇。后者可能在將來會被完全地取代掉。我們將會繼續(xù)改進測試過濾的 API,并添加更多種類的過濾器。

在構(gòu)建腳本中過濾測試

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"
    }
}  

有關(guān)更多的詳細信息和示例,請參閱 TestFilter 的文檔。

使用命令行選項的一些示例:

  • 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 IntegTestui*
  • gradle someTestTask --tests UiTest someOtherTestTask --tests WebTest*ui

通過系統(tǒng)屬性執(zhí)行單一的測試

這種機制已經(jīng)被上述的“測試過濾”所取代。 設(shè)置一個 taskName.single = testNamePattern 的系統(tǒng)屬性將會只執(zhí)行匹配 testNamePattern 的那些測試。這個 taskName 可以是一個完整的多項目路徑,比如“sub1:sub2:test”,或者僅是一個任務(wù)名稱。testNamePattern 將用于形成一個“*/testNamePattern.class” 的包含模式。如果這個模式無法找到任何測試,那么將會拋出一個異常。這是為了使你不會誤以為測試通過。如果執(zhí)行了一個以上的子項目的測試,該模式會被應(yīng)用于每一個子項目中。如果在一個特定的子項目中,找不到測試用例,那么將會拋出異常。在這種情況下你可以使用路徑標記法的模式,這樣該模式就會只應(yīng)用于特定的子項目的測試任務(wù)中?;蛘吣憧梢灾付ㄒ獔?zhí)行的任務(wù)的完整限定名稱。你還可以指定多個模式。示例:

  • 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

測試檢測

Test 任務(wù)通過檢查編譯過的測試類來檢測哪些類是測試類。默認情況下它會掃描所有的.class 文件。您可以設(shè)置自定義的 includes 或 excludes,這樣就只有這些類才會被掃描。根據(jù)所使用的測試框架 (JUnit 或 TestNG),會使用不同的標準進行測試類的檢測。

當使用 JUnit 時,我們掃描 JUnit 3 和 4 的測試類。如果滿足以下的任何一個條件,這個類就被認為是一個 JUnit 測試類:

  • 類或超類繼承自 TestCase 或 GroovyTestCase
  • 類或超類使用了 @RunWith 進行注解
  • 類或超類含有一個帶 @Test 注解的方法

當使用 TestNG 時,我們掃描所有帶有 @Test 注解的方法。

請注意,抽象類不會被執(zhí)行。Gradle 還將掃描測試類路徑中的 jar 文件里的繼承樹。

如果你不想要使用測試類檢測,可以通過設(shè)置 scanForTestClasses 為 false 來禁用它。這將使test任務(wù)只使用 includes / excludes 來找到測試類。如果 scanForTestClasses 為disabled,并且沒有指定 include 或 exclude 模式,則使用各自的默認值。對于 include 的默認值是 "/*Tests.class", "*/Test.class",而對于exclude它的默認值是 "/Abstract*.class"。

測試分組

JUnit 和 TestNG 可以對測試方法進行復(fù)雜的分組。

為對 Junit 測試類和方法進行分組,JUnit 4.8 引入了類別的概念。test 任務(wù)可以實現(xiàn)一個規(guī)范,讓你 include 和 exclude 想要的 JUnit 類別。

JUnit 類別

build.gradle

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

TestNG 框架有一個非常相似的概念。在 TestNG 中你可以指定不同的測試組。應(yīng)從測試執(zhí)行中 include 或 exclude 的測試組,可以在 test 任務(wù)中配置。

對 TestNG 測試分組

build.gradle

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

測試報告

test 任務(wù)默認情況下會生成以下結(jié)果。

  • 一個 HTML 測試報告。
  • 與 Ant Junit report 任務(wù)兼容的 XML 格式的結(jié)果。這種格式可以被許多工具所支持,比如CI服務(wù)器。
  • 有效二進制格式的結(jié)果。這個任務(wù)會從這些二進制結(jié)果生成其他的結(jié)果。

您可以使用 Test.setTestReport()方法來禁用 HTML 測試報告。目前不能禁用其他的結(jié)果。

這里還有一個獨立的 TestReport 任務(wù)類型,它可以從一個或多個 Test 任務(wù)實例生成的二進制結(jié)果中生成 HTML 測試報告。要使用這個任務(wù)類型,你需要定義一個 destinationDir 和要包含到報告的測試結(jié)果。這里是一個范例,從子項目的單元測試中生成一個聯(lián)合報告:

為多個子項目創(chuàng)建一個單元測試報告

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
}  

你應(yīng)該注意到,TestReport 類型組合了多個測試任務(wù)的結(jié)果,并且需要聚合各個測試類的結(jié)果。這意味著,如果一個給定的測試類被多個 test 任務(wù)所執(zhí)行,那么測試報告將包括那個類的所有執(zhí)行結(jié)果,但它難以區(qū)分那個類的每次執(zhí)行和它們的輸出。

TestNG 參數(shù)化方法和報告

TestNG 支持參數(shù)化測試方法,允許一個特定的測試方法使用不同的輸入執(zhí)行多次。Gradle 會在這個方法的執(zhí)行報告中包含進它的參數(shù)值。

給定一個帶有兩個參數(shù),名為 aParameterizedTestMethod 參數(shù)化測試方法,它將使用名稱這個名稱進行報告 :aParameterizedTestMethod(toStringValueOfParam1, toStringValueOfParam2)。這使得在特定的迭代過程,很容易確定參數(shù)值。

常規(guī)值

表 23.14. Java 插件 - test 屬性

任務(wù)屬性 類型 默認值
testClassesDir File sourceSets.test.output.classesDir
classpath FileCollection sourceSets.test.runtimeClasspath
testResultsDir File testResultsDir
testReportDir File testReportDir
testSrcDirs List<File> sourceSets.test.java.srcDirs

Jar

Jar 任務(wù)創(chuàng)建一個包含類文件和項目資源的 JAR 文件。JAR 文件在 archives 依賴配置中被聲明為一個構(gòu)件。這意味著這個 JAR 文件被包含在一個依賴它的項目的類路徑中。如果你把你的項目上傳到倉庫,這個 JAR 文件會被聲明為依賴描述符的一部分。你可以在第16.8節(jié),“創(chuàng)建檔案”和第51章, 發(fā)布 artifact 中了解如何使用 archives 和配置 artifact。

Manifest

每個 jar 或 war 對象都有一個單獨的 Manifest 實例的 manifest 屬性。當生成 archive 時,相應(yīng)的 MANIFEST.MF 文件也會被寫入進去。

自定義的 MANIFEST.MF

build.gradle

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

您可以創(chuàng)建一個單獨的 Manifest 實例。它可以用于共享兩個 jar 包的 manifest 信息。

創(chuàng)建一個 manifest 對象。

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 對象的引用。

指定 archive 的單獨 MANIFEST.MF

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 會根據(jù)在 from 語句中所聲明的順序進行合并。如果基本的 manifest 和要合并的 manifest 都定義了同一個 key 的值,那么默認情況下會采用要合并的 manifest 的值。你可以通過添加 eachEntry action 來完全自定義合并行為,它可以讓你對每一項生成的 manifest 訪問它的一個 ManifestMergeDetails 實例。這個合并操作不會在 from 語句中就馬上被觸發(fā)。它是懶執(zhí)行的,不管是對于生成一個 jar 包,還是調(diào)用了 writeTo 或者 effectiveManifest

你可以很輕松地把一個 manifest 寫入磁盤中。

指定 archive 的單獨 MANIFEST.MF

build.gradle

jar.manifest.writeTo("$buildDir/mymanifest.mf")  
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號