// Copyright 2019 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[xctest_plugin]]
= XCTest

The XCTest Plugin provides the tasks, configurations and conventions for integrating with a https://developer.apple.com/documentation/xctest[XCTest testing framework on macOS] as well as https://github.com/apple/swift-corelibs-xctest[Linux's open source implementation].

[[sec:xctest_usage]]
== Usage

.Applying the XCTest Plugin
====
include::sample[dir="snippets/swift/swiftXCTest/groovy",files="build.gradle[tags=apply-plugin]"]
include::sample[dir="snippets/swift/swiftXCTest/kotlin",files="build.gradle.kts[tags=apply-plugin]"]
====

[[sec:xctest_build_varants]]
== Build variants

The XCTest Plugin understands the following dimensions.
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.

Target machines - defaults to the tested component (if present) or build host (otherwise)::
The target machine expresses which machines the application expects to run.
A target machine is identified by its operating system and architecture.
Gradle uses the target machine to decide which tool chain to choose based on availability on the host machine.

The target machine can be configured as follows:

.Configure application target machines
====
include::sample[dir="snippets/swift/swiftXCTest/groovy",files="build.gradle[tags=configure-target-machines]"]
include::sample[dir="snippets/swift/swiftXCTest/kotlin",files="build.gradle.kts[tags=configure-target-machines]"]
====

[[sec:xctest_tasks]]
== Tasks

The following diagram shows the relationships between tasks added by this plugin.

.XCTest Plugin default task graph
image::xctest-task-graph.png[]

[[sec:xctest_task_variants]]
=== Variant-dependent Tasks

The XCTest Plugin creates tasks based on the variants of the test component.
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.
The following diagrams show the relationship between variant-dependent tasks.

.XCTest Plugin variant-dependent task graph
image::xctest-variant-task-graph.png[]

`compileTest__Variant__Swift` (e.g. `compileTestSwift`)  - link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html[SwiftCompile]::
Depends on: All tasks that contribute source files to the compilation
::
Compiles Swift source files using the selected compiler.

`linkTest__Variant__` (e.g. `linkTest`) - link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html[LinkMachOBundle] (on macOS) or link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html[LinkExecutable] (on Linux)::
Depends on: All tasks which contribute to the link executable, including `link__Variant__` and `create__Variant__` tasks from projects that are resolved via project dependencies and tested component
::
Links executable from compiled object files using the selected linker.

`installTest__Variant__` (e.g. `installTest`) - link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.InstallXCTestBundle.html[InstallXCTestBundle] (on macOS) or link:{groovyDslPath}/org.gradle.nativeplatform.tasks.InstallExecutable.html[InstallExecutable] (on Linux)::
Depends on: `linkTest__Variant__` and all tasks which contribute to the runtime of the executable, including `link__Variant__` tasks from projects that are resolved via project dependencies
::
Installs the executable and all of it's runtime dependencies for easy execution.

`xcTest__Variant__` (e.g. `xcTest`) - link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html[XCTest]::
Depends on: `installTest__Variant__`
::
Run the installed executable.

[[sec:xctest_lifecycle_tasks]]
=== Lifecycle Tasks

The XCTest Plugin attaches some of its tasks to the standard lifecycle tasks documented in the <<base_plugin.adoc#,Base Plugin chapter>> — which the XCTest Plugin applies automatically:

`assemble` - Task (lifecycle)::
Aggregate task that assembles the debug variant of the tested component for the current host (if present) in the project.
For example, the <<swift_application_plugin.adoc#,Swift Application Plugin>> and <<swift_library_plugin.adoc#,Swift Library Plugin>> attach their link and create tasks to this lifecycle task.
This task is added by the <<base_plugin.adoc#,Base Plugin>>.

`test` - Task (lifecycle)::
Depends on: `xcTest__Variant__` that most closely matches the build host
::
Aggregate task of the variant that most closely match the build host for testing the component.

`check` - Task (lifecycle)::
Depends on: `test`
::
Aggregate task that performs verification tasks, such as running the tests.
Some plugins add their own verification task to `check`.
This task is added by the <<base_plugin.adoc#,Base Plugin>>.

`build` - Task (lifecycle)::
Depends on: `check`, `assemble`
::
Aggregate tasks that perform a full build of the project.
This task is added by the <<base_plugin.adoc#,Base Plugin>>.

`clean` - Delete::
Deletes the build directory and everything in it, i.e. the path specified by the `Project.getBuildDir()` project property.
This task is added by the <<base_plugin.adoc#,Base Plugin>>.

[[sec:xctest_dependency_management]]
== Dependency management

Just like the tasks created by the XCTest Plugin, the configurations are created based on the variant of the application component.
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.
The following graph describes the configurations added by the XCTest Plugin:

.XCTest Plugin configurations
image::xctest-configurations.png[]

* The configurations in white are the ones a user should use to declare dependencies
* The configurations in blue, also known as resolvable denoted by \(R), are internal to the component, for its own use

The following configurations are used to declare dependencies:

`testImplementation`::
Used for declaring implementation dependencies for all variants of the test component.
This is where you should declare dependencies of any variants.
Note this configuration inherit all dependencies declared on the tested component (library or application).

`test__Variant__ExecutableImplementation` (e.g. `testExecutableImplementation`) extends `testImplementation`::
Used for declaring implementation dependencies for a specific variant of the test component.
This is where you should declare dependencies of the specific variant.


There is no configurations that can be used by consumers for this plugin.

The following configurations are used by the test component itself:

`swiftCompileTest__Variant__` (e.g. `swiftCompileTest`) extends `test__Variant__ExecutableImplementation`::
Used for compiling the test component.
This configuration contains the compile module of the test component and is therefore used when invoking the Swift compiler to compile it.

`nativeLinkTest__Variant__` (e.g. `nativeLinkTest`) extends `test__Variant__ExecutableImplementation`::
Used for linking the test component.
This configuration contains the libraries of the test component and is therefore used when invoking the Swift linker to link it.

`nativeRuntimeTest__Variant__` (e.g. `nativeRuntimeTest`) extends `test__Variant__ExecutableImplementation`::
Used for executing the test component.
This configuration contains the runtime libraries of the test component.

[[sec:xctest_conventions]]
== Conventions

The XCTest Plugin adds conventions for sources and tasks, shown below.

[[sec:xctest_layout]]
=== Project layout

The XCTest Plugin assumes the project layout shown below.
None of these directories needs to exist or have anything in them.
The XCTest Plugin will compile whatever it finds, and handles anything which is missing.

`src/test/swift`::
Swift source with extension of `.swift`

You <<building_swift_projects.adoc#sec:custom_swift_source_set_paths,configure the project layout>> by configuring the `source` on the `xctest` script block.

[[sec:xctest_compile_task]]
=== `compileTest__Variant__Swift` Task

The XCTest Plugin adds a link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html[SwiftCompile] instance for each variant of the test component to build (e.g. `compileTestSwift`).
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.
Some of the most common configuration options are shown below.

[horizontal]
link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:compilerArgs[compilerArgs]:: []

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:debuggable[debuggable]:: `true`

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:modules[modules]:: `configurations.swiftCompileTest__Variant__`

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:macros[macros]:: []

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:objectFileDir[objectFileDir]:: `$buildDir/obj/test/__variant__`

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:optimized[optimized]:: `false`

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:source[source]:: `xctest.swiftSource`

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:targetPlatform[targetPlatform]:: derived from the `TargetMachine` of the binary

link:{groovyDslPath}/org.gradle.language.swift.tasks.SwiftCompile.html#org.gradle.language.swift.tasks.SwiftCompile:toolChain[toolChain]:: <<building_swift_projects.adoc#sec:swift_supported_tool_chain,automatically selected based on target machine>>

[[sec:xctest_link_task]]
=== `linkTest__Variant__` Task

The XCTest Plugin adds a link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html[LinkMachOBundle] instance on macOS or link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html[LinkExecutable] instance on Linux for each variant of the test component - e.g. `linkTest`.
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.
Some of the most common configuration options are shown below.

==== macOS

[horizontal]
link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:debuggable[debuggable]:: `true`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:libs[libs]:: `configurations.nativeLinkTest__Variant__`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:linkedFile[linkedFile]:: `$buildDir/exe/test/__variant__/module`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:linkerArgs[linkerArgs]:: []

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:source[source]:: `compile__Variant__Swift.objects` (if present) + `compileTest__Variant__Swift.objects`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:targetPlatform[targetPlatform]:: derived from the `TargetMachine` of the binary

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkMachOBundle.html#org.gradle.nativeplatform.tasks.LinkMachOBundle:toolChain[toolChain]:: <<building_swift_projects.adoc#sec:swift_supported_tool_chain,automatically selected based on target machine>>

==== Linux

[horizontal]
link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:debuggable[debuggable]:: `true`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:libs[libs]:: `configurations.nativeLinkTest__Variant__`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:linkedFile[linkedFile]:: `$buildDir/exe/test/__variant__/baseName`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:linkerArgs[linkerArgs]:: []

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:source[source]:: `compile__Variant__Swift.objects` (if present) + `compileTest__Variant__Swift.objects`

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:targetPlatform[targetPlatform]:: derived from the `TargetMachine` of the binary

link:{groovyDslPath}/org.gradle.nativeplatform.tasks.LinkExecutable.html#org.gradle.nativeplatform.tasks.LinkExecutable:toolChain[toolChain]:: <<building_swift_projects.adoc#sec:swift_supported_tool_chain,automatically selected based on target machine>>

[[sec:xctest_install_task]]
=== `installTest__Variant__` Task

The XCTest Plugin adds a link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.InstallXCTestBundle.html[InstallXCTestBundle] instance on macOS or link:{groovyDslPath}/org.gradle.nativeplatform.tasks.InstallExecutable.html[InstallExecutable] instance on Linux for each variant of the test component - e.g. `installTest`.
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.
There is no need to configure any properties on the task.

[[sec:xctest_run_task]]
=== `xcTest__Variant__` Task

The XCTest Plugin adds a link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html[XCTest] instance for each variant of the test component - e.g. `xcTest`.
Read the <<building_swift_projects.adoc#sec:introducing_build_variants-swift,introduction to build variants>> for more information.
Some of the most common configuration options are shown below.

[horizontal]
link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html#org.gradle.nativeplatform.test.xctest.tasks.XCTest:binResultDir[binResultDir]:: `$buildDir/test-results/xctest/__variant__/`

link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html#org.gradle.nativeplatform.test.xctest.tasks.XCTest:ignoreFailures[ignoreFailures]:: `false`

link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html#org.gradle.nativeplatform.test.xctest.tasks.XCTest:reports[reports]:: `$buildDir/reports/tests/xctest/__variant__/` (HTML only)

link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html#org.gradle.nativeplatform.test.xctest.tasks.XCTest:runScriptFile[runScriptFile]:: `$buildDir/install/test/__variant__/__xctest.module__`

link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html#org.gradle.nativeplatform.test.xctest.tasks.XCTest:testInstallDirectory[testInstallDirectory]:: `$buildDir/install/test/__variant__/`

link:{groovyDslPath}/org.gradle.nativeplatform.test.xctest.tasks.XCTest.html#org.gradle.nativeplatform.test.xctest.tasks.XCTest:workingDirectory[workingDirectory]:: `$buildDir/install/test/__variant__/`
