A Kotlin-first, top-level facade for the public Allure runtime API. This module keeps Kotlin dependencies out of
allure-java-commons while providing named arguments, useful defaults, and unambiguous Kotlin lambdas.
- Allure Java 3.x requires Java 17 or newer.
- This module supports Kotlin 2.0 and newer.
Gradle:
dependencies {
testImplementation(platform("io.qameta.allure:allure-bom:<allure-version>"))
testImplementation("io.qameta.allure:allure-kotlin-extensions")
testImplementation("io.qameta.allure:allure-jupiter") // or another test-framework adapter
}Maven, with allure-bom imported in dependency management:
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-kotlin-extensions</artifactId>
<scope>test</scope>
</dependency>Import individual functions or the complete facade:
import io.qameta.allure.kotlin.extensions.*
import io.qameta.allure.model.Parameter
import io.qameta.allure.model.Status
import io.qameta.allure.model.StatusDetailsThe facade covers lifecycle access, completed and executable steps, stages, labels, parameters, links, descriptions,
global errors, synchronous and asynchronous attachments, and HTTP exchange attachments. It delegates to Allure, so
the behavior and current test context are shared with Java adapters and annotations. Executable steps expose a
Kotlin-native StepScope instead of the overloaded Java Allure.StepContext.
Java overload families are represented as Kotlin APIs instead of copied literally:
- the executable
Allure.stepSAM overloads become one receiver-lambda function - the parameter overloads become one function with optional named arguments
- attachment content is the second argument and attachment metadata has defaults
getLifecycleandsetLifecyclebecome thelifecycleproperty
The original Allure class remains available for low-level interop.
Import the top-level API instead of selecting between the Java Allure.step SAM overloads:
import io.qameta.allure.kotlin.extensions.step
val orderId = step("Create order") {
parameter(name = "region", value = "eu-west")
val id = createOrder()
name("Create order $id")
id
}StepScope.parameter combines the Java overload family into one function. Its excluded and mode options can be
supplied independently with named arguments:
step("Authenticate") {
parameter(
name = "access token",
value = token,
excluded = true,
mode = Parameter.Mode.MASKED,
)
authenticate(token)
}The same function accepts a Unit-returning body. Omitting the name records the step as step:
step {
verifyOrder(orderId)
}Already-completed steps and semantic stages use the same names as the Java API:
stage("prepare data")
step("customer created")
stage("verify result")
step("optional check", Status.SKIPPED)All runtime metadata operations support Kotlin named arguments:
epic("Checkout")
feature("Payment")
story("Saved card")
suite("Web checkout")
label(name = "component", value = "billing")
parameter(
name = "access token",
value = token,
excluded = true,
mode = Parameter.Mode.MASKED,
)
link(url = "https://example.test")
link(name = "Documentation", url = "https://example.test/docs")
link(name = "Dashboard", type = "dashboard", url = "https://example.test/dashboard")
issue(name = "BUG-42", url = "https://example.test/issues/42")
tms(name = "CASE-7", url = "https://example.test/cases/7")
description("**Markdown** description")
descriptionHtml("<p>HTML description</p>")The attachment overloads put content second, provide useful defaults, and support named type and fileExtension
arguments:
import io.qameta.allure.kotlin.extensions.attachment
attachment(name = "response", content = responseBody)
attachment(
name = "screenshot",
content = screenshotBytes,
type = "image/png",
fileExtension = "png",
)Supported content types are String, ByteArray, and InputStream. A null file extension lets Allure detect it
from the media type; an empty string suppresses the extension.
Asynchronous streams and captured HTTP exchanges are available through the same facade:
attachmentAsync(
name = "worker output",
content = outputFuture,
type = "text/plain",
fileExtension = "log",
)
addHttpExchange(name = "HTTP exchange", exchange = capturedExchange)The future returned by attachmentAsync completes after the content is written. The owning executable also waits for
registered asynchronous attachments before it ends.
Most tests do not need direct lifecycle access. Integrations can use the process-wide property when necessary:
val currentLifecycle = lifecycle
lifecycle = customLifecycleReplacing the lifecycle affects the whole process and should be isolated from concurrent test execution.
Run-level failures that do not belong to a test or fixture can be reported from a throwable or explicit status details:
globalError(startupFailure)
globalError(StatusDetails().setMessage("Environment unavailable"))These functions call the Allure lifecycle synchronously and do not require AspectJ. The @Step and @Attachment
annotations remain in allure-java-commons and still require weaving.
Avoid combining @JvmOverloads with @Step or @Attachment on methods with default parameters. Kotlin copies the
annotation to generated overloads, so AspectJ can record duplicate operations. Prefer regular Kotlin default arguments
when using these annotations.
This module does not add coroutine context propagation or a suspend step API. Add
io.qameta.allure:allure-kotlin-coroutines when a step body needs to suspend or Allure context must cross coroutine
dispatcher boundaries.