---
title: Go Testing reference
description: Reference documentation for the allure-go integration | Test functions | Static options | Runtime context API | Testify assertions | HTTP exchange attachments
---

# Go Testing reference

These are the main building blocks you can use to integrate Go tests with Allure by using the `github.com/allure-framework/allure-go/commons/gotest` package. Import it under the `allure` alias:

```go
import allure "github.com/allure-framework/allure-go/commons/gotest"
```

## Test functions

### `allure.Test`

`allure.Test(t, name, body, options...)` reports one named Allure test result. It creates a Go subtest via `t.Run(name, ...)`, so failures, skips, logs, cleanups, steps, and attachments stay attached to the correct result, and standard `go test -run` filtering keeps working:

```go
func TestLogin(t *testing.T) {
    allure.Test(t, "logs in with valid credentials", func(a *allure.Context) {
        // ...
    }, allure.WithOwner("qa-team"))
}
```

One Go test function may contain multiple `allure.Test` calls; each produces a separate Allure result.

### `allure.Wrap`

`allure.Wrap(t, body, options...)` reports the current Go test as exactly one Allure result. It uses `t.Name()` as the result name and does not create a child subtest:

```go
func TestLogin(t *testing.T) {
    allure.Wrap(t, func(a *allure.Context) {
        // ...
    })
}
```

`allure.Wrap` may be called only once per test, and cannot be combined with `allure.Test` on the same `*testing.T` — use `allure.Test` when one Go test should produce multiple named Allure results.

### `allure.Step`

The package-level generic `allure.Step(a, name, body)` reports a step whose body returns a typed value:

```go
session := allure.Step(a, "create session", func(a *allure.Context) string {
    return "session-1"
})
```

For steps without a return value, use the [`a.Step` method](#steps) instead.

### Statuses

The reported test status follows the outcome of the Go test: `passed`, `failed` (after `t.Error`, `t.Fatal`, or a failed assertion), or `skipped` (after `t.Skip`). A panic in the test body is reported as `broken` with the panic message and stack trace, and is then re-raised for `go test` to handle as usual.

## Static options

Options are passed as trailing arguments to `allure.Test` and `allure.Wrap`. They apply before the test body runs, which makes them visible to [test plan filtering](/docs/go-configuration/#allure-testplan-path). Prefer options for metadata known up front; use the [runtime context API](#runtime-context-api) for metadata discovered during execution.

### Labels

- `allure.WithLabel(name, value)`
- `allure.WithLabels(labels...)` — takes `model.Label` values
- `allure.WithTag(value)`
- `allure.WithSeverity(value)`
- `allure.WithOwner(value)`
- `allure.WithAllureID(id)`

### Hierarchies

- `allure.WithEpic(value)`
- `allure.WithFeature(value)`
- `allure.WithStory(value)`
- `allure.WithParentSuite(value)`
- `allure.WithSuite(value)`
- `allure.WithSubSuite(value)`
- `allure.WithPackage(value)`

Setting any of the `parentSuite`, `suite`, or `subSuite` labels disables the [automatic suite hierarchy](/docs/go-configuration/#automatic-labels-and-identifiers) derived from the test file path.

### Links

- `allure.WithLink(url, name, linkType)`
- `allure.WithLinks(links...)` — takes `model.Link` values
- `allure.WithIssue(name, url)`
- `allure.WithTMS(name, url)`

### Parameters

- `allure.WithParameter(name, value)`
- `allure.WithParameterOptions(name, value, options)`

`allure.ParameterOptions` controls display and history behavior:

```go
allure.WithParameterOptions("password", "qwerty", allure.ParameterOptions{
    Excluded: true,                      // do not affect the history ID
    Mode:     model.ParameterModeMasked, // model.ParameterModeDefault, Masked, or Hidden
})
```

### Descriptions and identity

- `allure.WithDescription(markdown)`
- `allure.WithDescriptionHTML(html)`
- `allure.WithDisplayName(name)` — overrides the name shown in the report
- `allure.WithTestCaseName(name)` — sets the logical test case name
- `allure.WithTestCaseID(id)` — overrides the computed test case ID
- `allure.WithHistoryID(id)` — overrides the computed history ID

### Test plan

- `allure.WithTestPlan(plan)` — uses an already loaded `*testplan.Plan` instead of `ALLURE_TESTPLAN_PATH`
- `allure.WithTestPlanPath(path)` — loads a test plan from a specific file

### Advanced

- `allure.WithWriter(writer)` — routes this test's artifacts through a custom `writer.Writer`, for example an in-memory writer in adapter tests
- `allure.WithClock(now)` — replaces the millisecond timestamp source
- `allure.WithIDGenerator(newID)` — replaces the UUID generator

## Runtime context API

The test body receives an `*allure.Context` (named `a` by convention) that combines access to the underlying `*testing.T` with Allure reporting methods.

### Bridge to `testing.T`

- `a.T()` — the underlying `*testing.T`
- `a.Name()` — the current Go test name
- `a.Helper()` — marks the caller as a test helper
- `a.Errorf(format, args...)` — fails the test and records the message as Allure status details
- `a.Fatal(args...)`, `a.Fatalf(format, args...)` — fail the test with status details and stop execution
- `a.FailNow()` — fails and stops without a message
- `a.Context()` — the `context.Context` carrying the active Allure runtime state; pass it to helper libraries such as [`httpexchange`](#http-exchange-attachments)

Failure messages reported through `a.Errorf`, `a.Fatal`, and `a.Fatalf` appear as the result's status details in the report. Calls made directly on `a.T()` still fail the test correctly but do not record status details.

### Steps

- `a.Step(name, body)` — reports `body` as a step; steps nest naturally
- `a.StepDisplayName(name)` — renames the active step
- `a.StepParameter(name, value)` — adds a parameter to the active step
- `a.StepDescription(markdown)`, `a.StepDescriptionHTML(html)` — set the active step description

```go
a.Step("submit credentials", func(a *allure.Context) {
    a.StepParameter("endpoint", "/login")
    a.Step("wait for redirect", func(a *allure.Context) {
        // ...
    })
})
```

### Metadata

- `a.Label(name, value)`
- `a.Link(url, name, linkType)`
- `a.Parameter(name, value)`
- `a.Description(markdown)`, `a.DescriptionHTML(html)`
- `a.DisplayName(name)`
- `a.TestCaseName(name)`, `a.TestCaseID(id)`, `a.HistoryID(id)`

These are the runtime counterparts of the static options. Note that runtime metadata is applied after test plan filtering, so an Allure ID needed for selection must be set with `allure.WithAllureID`.

### Attachments

- `a.Attachment(name, content, contentType)` — attaches in-memory bytes
- `a.AttachmentPath(name, path, contentType)` — attaches an existing file

Attachments are added to the active step, or to the test itself when no step is active. For in-memory attachments, the stored file's extension is derived from the content type (for example, `application/json` produces a `.json` file); file attachments keep the extension of the source file.

### Run-level diagnostics

- `a.GlobalAttachment(name, content, contentType)`, `a.GlobalAttachmentPath(name, path, contentType)` — attach evidence to the test run as a whole rather than to one test, for example a service log collected once per run
- `a.GlobalError(details)` — records a run-level error, taking a `model.StatusDetails` value

## Testify assertions

The separate module `github.com/allure-framework/allure-go/testify` provides drop-in replacements for testify's `assert` and `require` packages that report each assertion call as an Allure step:

```bash
go get github.com/allure-framework/allure-go/testify/assert
go get github.com/allure-framework/allure-go/testify/require
```

```diff
 import (
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
+	"github.com/allure-framework/allure-go/testify/assert"
+	"github.com/allure-framework/allure-go/testify/require"
 )
```

The proxy packages mirror the upstream testify API, including `assert.New(...)` / `require.New(...)` assertion objects. What is reported depends on the first argument of each call:

- passing the Allure context `a` reports the assertion as an Allure step; failed assertions add status details, including the expected and actual values,
- passing `t` or `a.T()` keeps plain testify behavior without step reporting.

```go
allure.Test(t, "loads profile", func(a *allure.Context) {
    assert.Equal(a, "alice", profile.Name) // reported as a step
    require.NoError(a, err)                // reported as a step
    assert.Equal(t, "alice", profile.Name) // plain testify, no step
})
```

Test context types from other integrations can opt into step reporting by satisfying testify's `TestingT` interface and the `commons.ContextProvider` interface (a `Context() context.Context` method).

## HTTP exchange attachments

The `github.com/allure-framework/allure-go/commons/httpexchange` package produces attachments in the [Allure HTTP Exchange format](/docs/attachments/#http-exchanges) (`application/vnd.allure.http+json`, stored with the `.httpexchange` extension), which report viewers render as structured request/response evidence.

### Capture helpers

- `httpexchange.NewTransport(ctx, base, options...)` — wraps an `http.RoundTripper`; every request sent through the client is attached to the active test or step
- `httpexchange.NewHandler(ctx, next, options...)` — wraps an `http.Handler`; every request received by the server is attached, which suits `httptest.Server` fakes

```go
client := &http.Client{
    Transport: httpexchange.NewTransport(a.Context(), http.DefaultTransport),
}

server := httptest.NewServer(httpexchange.NewHandler(a.Context(), handler))
```

Both take the Allure context from `a.Context()` and safely do nothing when no Allure test is active.

### Building exchanges manually

When the body bytes are already captured by your own code:

- `httpexchange.NewExchange(req, requestBody, resp, responseBody, options...)` — builds a complete exchange from `*http.Request` and `*http.Response` values
- `httpexchange.FromRequest(req, body, options...)`, `httpexchange.FromResponse(resp, body, options...)` — build the request or response portion separately
- `httpexchange.Attach(ctx, name, exchange)` — attaches an exchange to the active test or step
- `httpexchange.Marshal(exchange)` — serializes an exchange to JSON without attaching it

### Options

- `httpexchange.WithBodyLimit(limit)` — limits captured body values, 64 KiB by default; a negative limit captures everything, zero records body metadata without content
- `httpexchange.WithRedactedHeaders(names...)` — adds header names to redact; `Authorization`, `Proxy-Authorization`, `Cookie`, `Set-Cookie`, `X-Api-Key`, and `X-Auth-Token` are redacted by default
- `httpexchange.WithRedactedQueryParameters(names...)` — adds query parameters to redact; common token-like names such as `token`, `password`, `api_key`, and `client_secret` are redacted by default
- `httpexchange.WithRedactedFormFields(names...)` — adds URL-encoded form fields to redact; the same token-like defaults apply
- `httpexchange.WithRedactedCookies(names...)` — adds cookie names to redact; by default, all cookie values are redacted
- `httpexchange.WithAttachmentName(name)` / `httpexchange.WithAttachmentNamer(func)` — set a fixed or computed attachment name; the default is `HTTP <method> <path-and-query>`, for example `HTTP GET /orders?page=2`
- `httpexchange.WithStartStop(start, stop)` — sets explicit exchange timestamps in Unix epoch milliseconds
- `httpexchange.WithError(err)` / `httpexchange.WithErrorDetails(name, message, stack)` — record a transport-level error on the exchange

Redacted values are replaced with the `__ALLURE_REDACTED__` sentinel, which report viewers display as a redaction marker.

## Building a custom integration with `commons`

Use the `github.com/allure-framework/allure-go/commons` module when you need to integrate Allure with a custom test harness, or to write a helper library that reports into whatever Allure test is currently active.

Helper libraries only need the facade functions, which mirror the runtime context API but take a `context.Context` and return errors. All of them safely do nothing when no Allure runtime is bound to the context:

```go
import commons "github.com/allure-framework/allure-go/commons"

func instrument(ctx context.Context) error {
    if err := commons.Owner(ctx, "qa-team"); err != nil {
        return err
    }
    return commons.Step(ctx, "call login endpoint", func(ctx context.Context) error {
        return commons.Attachment(ctx, "payload", []byte(`{"ok":true}`), commons.AttachmentOptions{
            ContentType: "application/json",
        })
    })
}
```

The main facade groups are:

- labels and links: `Label`, `Labels`, `Tag`, `Severity`, `Owner`, `Epic`, `Feature`, `Story`, `ParentSuite`, `Suite`, `SubSuite`, `Package`, `AllureID`, `Link`, `Links`, `Issue`, `TMS`
- test metadata: `Parameter`, `ParameterWithOptions`, `Description`, `DescriptionHTML`, `DisplayName`, `TestCaseName`, `TestCaseID`, `HistoryID`
- steps: `Step`, `StepValue` (returns a typed value), `StartStep`, `StopStep`, `LogStep` (records an already completed step), `StepDisplayName`, `StepParameter`, `StepParameterWithOptions`, `StepDescription`, `StepDescriptionHTML`
- attachments and diagnostics: `Attachment`, `AttachmentPath`, `GlobalAttachment`, `GlobalAttachmentPath`, `GlobalError`

Adapters that manage the test lifecycle themselves build on the lower-level subpackages:

- `commons/runtime` — the context-bound message bridge; bind ownership with `runtime.WithRuntime`, `runtime.WithTest`, `runtime.WithFixture`, and `runtime.WithStep`
- `commons/writer` — result persistence: `NewFileSystemWriter` for `allure-results` directories, `NewInMemoryWriter` for tests, `NewMultiWriter` to fan out
- `commons/model` — the serializable Allure result types (`TestResult`, `StepResult`, `Label`, `Link`, `Parameter`, `Status`, `StatusDetails`, and others)
- `commons/testplan` — test plan loading and matching: `LoadFromEnv`, `LoadFile`, `Parse`, `Includes`
- `commons/ids` — stable identity helpers: `New`, `TestCaseID`, `HistoryID`
- `commons/clock` — Unix epoch-millisecond timestamp helpers
- `commons/lifecycle` — lifecycle interfaces and event hooks for adapter authors
