Swift Testing

Add the SPM package and depend on TraceraTesting:

.package(url: "https://github.com/tracera-dev/tracera-swift.git", from: "0.1.0"),
// …
.product(name: "TraceraTesting", package: "tracera-swift"),

Requires Swift ≥ 6 (macOS 15 / Xcode 16; see Autotest adapters).

Environment variables and run mode: Autotest adapters.

Bind testCaseId and autotestName

Preferred declarative bind:

@Test("checkout", .traceraId(42))
func checkout() {
  // …
}

@Test("login as {user}", .traceraId(42), arguments: ["alice", "bob"])
func login(user: String) {
  // …
}

When the id is not a compile-time constant, open a pin with .tracera and bind imperatively:

@Test("checkout", .tracera)
func checkout() {
  Tracera.testCase(42)
  // Tracera.testCase(42, "e2e/checkout")
}

Skip

Use skip("reason") so the reason is added to the result as comment:

@Test("checkout", .traceraId(42))
func checkout() throws {
  try skip("needs a seeded account")
}

Steps

Use Tracera.step("…") { … } (sync or async). Steps inside setup / teardown go to Setup / Teardown; other steps go to Test.

@Test("checkout", .traceraId(10))
func checkout() throws {
  try setup("open shop") {}
  try Tracera.step("add item") {
    Tracera.step("nested leaf") {}
  }
  try teardown("close shop") {}
}

Comments, errors, and attachments

Limits and allowed MIME types: Autotest adapters.

Tracera.comment, Tracera.error, and attachments are added to the open step, or to the result when no step is open. Tracera.attachmentFile takes a file path; Tracera.attachmentBytes takes a name and bytes (MIME type is optional). Attachments upload when the result is reported.

Tracera.comment("result-level note")
Tracera.error("result-level error")
Tracera.attachmentFile("Fixtures/screenshot.png")
Tracera.step("open login") {
  Tracera.comment("step note")
  Tracera.attachmentBytes("body.json", data: Data(#"{"ok":true}"#.utf8), mimeType: "application/json")
}

If you start a Task and call Tracera APIs there (steps, comments, errors, attachments), call getContext() in the test first and run the worker with runWithContext — otherwise those calls are not reported:

let ctx = getContext()
Task {
  await runWithContext(ctx) {
    Tracera.step("worker") { /* ... */ }
  }
}

Parameterized

Each arguments row is a separate case. Put placeholders such as {user} or {0} in the @Test("…") title, or in .traceraId(…, name:), so each row gets its own autotestName:

@Test("login as {user}", .traceraId(7), arguments: ["alice", "bob"])
func login(user: String) {
  Tracera.step("sign in") { /* ... */ }
}