Swift 測試支援與 設定快取 不相容。 |
原生生態系統中的測試是一個豐富的主題。有許多不同的測試函式庫和架構,以及許多不同類型的測試。所有這些都必須是建置的一部分,無論它們執行得頻繁或不頻繁。本章致力於說明 Gradle 如何處理建置之間和建置內的不同需求,並大量說明它如何在 macOS 和 Linux 上與 XCTest 整合。
它說明:- 控制測試執行方式的方法(測試執行)- 如何選擇要執行的特定測試(測試篩選)- 產生哪些測試報告以及如何影響處理程序(測試報告)- Gradle 如何找出要執行的測試(測試偵測)
但首先,我們來看看 Gradle 中原生測試的基礎知識。
基礎知識
Gradle 支援與 Swift 語言的 XCTest 測試架構深度整合,並圍繞 XCTest 任務類型進行。這會使用 macOS 上的 Xcode XCTest 或 Linux 上的 開源 Swift 核心函式庫替代方案 來執行一系列測試案例,並整理結果。然後,您可以透過 TestReport 任務類型的執行個體將這些結果轉換成報告。
為了執行,XCTest 任務類型需要三項資訊:- 在何處尋找已建置的可測試套件 (在 macOS 上) 或可執行檔 (在 Linux 上) (屬性:XCTest.getTestInstalledDirectory()) - 執行套件或可執行檔的執行指令碼 (屬性:XCTest.getRunScriptFile()) - 執行套件或可執行檔的工作目錄 (屬性:XCTest.getWorkingDirectory())
當您使用 XCTest 外掛程式 時,您將自動取得下列內容:- 類型的專用 xctest
延伸模組 SwiftXCTestSuite,用於設定測試元件及其變異- 類型的 xcTest
任務 XCTest,用於執行那些單元測試- 與主要元件的物件檔案連結的可測試套件或可執行檔
測試外掛程式適當地設定所需的資訊片段。此外,它們會將 xcTest
或 run
任務附加到 check
生命週期任務。它也會建立 testImplementation
相依性設定。僅在測試編譯、連結和執行期間需要的相依性可以新增到此設定。xctest
指令碼區塊的行為類似於 application
或 library
指令碼區塊。
XCTest 任務有許多設定選項。我們在本章節的其餘部分中涵蓋了其中相當多的選項。
測試執行
Gradle 在一個獨立的(「分岔」)程序中執行測試。
您可以透過 XCTest 任務上的多個屬性來控制測試程序的啟動方式,包括下列內容
ignoreFailures
- 預設值:false-
如果此屬性為
true
,Gradle 會在測試完成後繼續執行專案的建置,即使其中一些測試失敗。請注意,預設情況下,兩種任務類型都會執行它偵測到的每個測試,與此設定無關。 testLogging
- 預設值:未設定-
此屬性代表一組選項,用於控制記錄哪些測試事件以及記錄的層級。您也可以透過此屬性設定其他記錄行為。設定 TestLoggingContainer 以取得更多詳細資料。
請參閱 XCTest 以取得所有可用設定選項的詳細資料。
測試篩選
執行測試套件的子集是很常見的需求,例如在修正錯誤或開發新測試案例時。Gradle 提供篩選功能來執行此操作。您可以根據下列條件選取要執行的測試
-
一個簡單的類別名稱或方法名稱,例如
SomeTest
、SomeTest.someMethod
-
‘*’ 萬用字元比對
您可以在建置指令碼或透過 --tests
命令列選項啟用篩選。以下是每次執行建置時套用的部分篩選範例
xctest {
binaries.configureEach {
runTask.get().filter.includeTestsMatching("SomeIntegTest.*") // or `"Testing.SomeIntegTest.*"` on macOS
}
}
xctest {
binaries.configureEach {
runTask.get().configure {
// include all tests from test class
filter.includeTestsMatching "SomeIntegTest.*" // or `"Testing.SomeIntegTest.*"` on macOS
}
}
}
如需更多詳細資料和在建置指令碼中宣告篩選的範例,請參閱 TestFilter 參考。
命令列選項特別適用於執行單一測試方法。也可以提供多個 --tests
選項,其所有模式都會生效。下列各節有許多使用命令列選項的範例。
測試篩選目前僅支援與 XCTest 相容的篩選。這表示 macOS 和 Linux 之間的篩選會有所不同。在 macOS 上,套件基本名稱需要加在篩選之前,例如 TestBundle.SomeTest 、TestBundle.SomeTest.someMethod 請參閱 簡單名稱模式 區段,以取得有關有效篩選模式的更多資訊。
|
下列各節會探討簡單類別/方法名稱的特定案例。
簡單名稱模式
Gradle 支援簡單類別名稱,或類別名稱 + 方法名稱測試篩選。例如,下列命令列會執行 SomeTestClass
測試案例中的所有測試或其中一項
# Executes all tests in SomeTestClass
gradle xcTest --tests SomeTestClass
# or `gradle xcTest --tests TestBundle.SomeTestClass` on macOS
# Executes a single specified test in SomeTestClass
gradle xcTest --tests TestBundle.SomeTestClass.someSpecificMethod
# or `gradle xcTest --tests TestBundle.SomeTestClass.someSpecificMethod` on macOS
您也可以將命令列中定義的篩選與 持續建置 結合使用,以便在每次變更製作或測試原始檔後立即重新執行測試子集。下列範例會在每次變更觸發測試執行時執行 ‘SomeTestClass’ 測試類別中的所有測試
gradle test --continuous --tests SomeTestClass
測試報告
XCTest 任務預設會產生下列結果
-
HTML 測試報告
-
XML 測試結果,其格式與 Ant JUnit 報告任務相容,許多其他工具(例如 CI 伺服器)都支援此格式
-
由
XCTest
任務用於產生其他格式的結果的有效二進位格式
在大部分情況下,您會使用標準 HTML 報告,其中會自動包含 XCTest
任務的結果。
還有一個獨立的 TestReport 任務類型,可讓您用來產生自訂的 HTML 測試報告。它只需要 destinationDir
的值以及您想要包含在報告中的測試結果。以下是產生所有子專案的單元測試的合併報告的範例
plugins {
id("xctest")
}
extensions.configure<SwiftXCTestSuite>() {
binaries.configureEach {
// Disable the test report for the individual test task
runTask.get().reports.html.required = false
}
}
configurations.create("binaryTestResultsElements") {
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("test-report-data"))
}
tasks.withType<XCTest>() {
outgoing.artifact(binaryResultsDirectory)
}
}
plugins {
`reporting-base`
}
val testReportData by configurations.creating {
isCanBeConsumed = false
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("test-report-data"))
}
}
dependencies {
testReportData(project(":core"))
testReportData(project(":util"))
}
tasks.register<TestReport>("testReport") {
destinationDirectory = reporting.baseDirectory.dir("allTests")
// Use test results from testReportData configuration
testResults.from(testReportData)
}
plugins {
id 'xctest'
}
xctest {
binaries.configureEach {
runTask.get().configure {
// Disable the test report for the individual test task
reports.html.required = false
}
}
}
// Share the test report data to be aggregated for the whole project
configurations {
binaryTestResultsElements {
canBeResolved = false
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, 'test-report-data'))
}
tasks.withType(XCTest).configureEach {
outgoing.artifact(it.binaryResultsDirectory)
}
}
}
// A resolvable configuration to collect test reports data
plugins {
id 'reporting-base'
}
configurations {
testReportData {
canBeConsumed = false
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType, 'test-report-data'))
}
}
}
dependencies {
testReportData project(':core')
testReportData project(':util')
}
tasks.register('testReport', TestReport) {
destinationDirectory = reporting.baseDirectory.dir('allTests')
// Use test results from testReportData configuration
testResults.from(configurations.testReportData)
}
在此範例中,我們使用慣例外掛程式 myproject.xctest-conventions
來將專案的測試結果公開給 Gradle 的 變異感知相依性管理引擎。
外掛程式宣告一個可消耗的 binaryTestResultsElements
組態,代表 test
任務的二進位測試結果。在彙總專案的建置檔案中,我們宣告 testReportData
組態並相依於我們想要彙總其結果的所有專案。Gradle 會自動從每個子專案中選取二進位測試結果變異,而不是專案的 jar 檔案。最後,我們新增一個 testReport
任務,它彙總 testResultsDirs
屬性的測試結果,其中包含從 testReportData
組態解析的所有二進位測試結果。
您應該注意,TestReport 類型會合併多個測試任務的結果,並需要彙總個別測試類別的結果。這表示如果某個測試類別是由多個測試任務執行,那麼測試報告將包含該類別的執行,但要區分該類別的個別執行及其輸出可能會很困難。