---
title: Go Testing
description: Learn how to integrate Allure with Go tests by using the official allure-go packages and go test to generate rich, interactive test reports.
---

# Getting started with Go Testing

[![allure-go gotest package reference](https://pkg.go.dev/badge/github.com/allure-framework/allure-go/commons/gotest.svg "allure-go gotest package reference")](https://pkg.go.dev/github.com/allure-framework/allure-go/commons/gotest)

Generate beautiful HTML reports using [Allure Report](https://allurereport.org/docs/) and your Go tests.

Info:
The main user-facing package is [`commons/gotest`](https://github.com/allure-framework/allure-go/tree/main/commons/gotest), which works with Go's built-in `testing` package. If you are building your own integration for a custom runner or helper library, use [`commons`](https://github.com/allure-framework/allure-go/tree/main/commons) instead. Both packages live in the official `allure-go` repository, which also provides [testify-compatible assertion packages](#report-testify-assertions-as-steps) and [HTTP evidence helpers](#attach-http-traffic).

## Setting up

### 1. Prepare your project

1. Make sure a recent Go toolchain is installed.

   The official `allure-go` packages require Go 1.25 or newer.

1. Open a terminal and go to the project directory. For example:

   ```bash
   cd /home/user/myproject
   ```

1. Install Allure Report, following the [installation guide](/docs/v3/install/).

1. Add the `gotest` integration:

   ```bash
   go get github.com/allure-framework/allure-go/commons/gotest
   ```

1. Wrap your tests with `allure.Test`. Inside the body, use the provided context to declare steps, parameters, and attachments.

   ```go
   package example_test

   import (
       "testing"

       allure "github.com/allure-framework/allure-go/commons/gotest"
   )

   func TestLogin(t *testing.T) {
       allure.Test(t, "logs in with valid credentials", func(a *allure.Context) {
           a.Step("submit credentials", func(a *allure.Context) {
               a.Parameter("user", "alice")
               a.Attachment("request", []byte(`{"user":"alice"}`), "application/json")
           })
           session := allure.Step(a, "create session", func(a *allure.Context) string {
               return "session-1"
           })
           a.Parameter("session", session)
       },
           allure.WithOwner("qa-team"),
           allure.WithDescription("Checks that valid credentials create a session."),
       )
   }
   ```

### 2. Run tests

Run your tests the same way as usual:

```bash
go test ./...
```

By default, the integration writes the results to an `allure-results` directory next to each test package. Go runs every test binary in its package's source directory, so in a module with multiple test packages the relative default produces several `allure-results` directories.

To collect all results in one place, set `ALLURE_RESULTS_DIR` to an absolute path before the test run:

```bash
ALLURE_RESULTS_DIR=$PWD/allure-results go test ./...
```

If the results directory already exists, the new files are added to the existing ones, so that a future report will be based on all of them.

### 3. Generate a report

After the test run, generate and open the report with the Allure CLI:

```bash
allure generate ./allure-results --output ./allure-report
allure open ./allure-report
```

## Writing tests

The Allure Go integration extends plain `go test` output with richer reporting features. You can use it to:

- add [descriptions, owners, links, and other metadata](#add-metadata),
- organize tests into [behavior-based and suite-based hierarchies](#organize-tests),
- split the execution into [nested steps](#divide-a-test-into-steps),
- describe [parameters and attachments](#add-parameters-and-attachments),
- report [testify assertions as steps](#report-testify-assertions-as-steps),
- attach [structured HTTP traffic evidence](#attach-http-traffic),
- run only selected tests through a [test plan file](#select-tests-via-a-test-plan-file).

### Add metadata

Metadata that is known before the test body runs is best passed as static `allure.With...` options, since they participate in [test plan filtering](#select-tests-via-a-test-plan-file). Metadata discovered during execution can be added at runtime with methods on the test's `*allure.Context`:

```go
func TestLogin(t *testing.T) {
    allure.Test(t, "Login works", func(a *allure.Context) {
        a.Label("layer", "web")
        a.Link("https://example.com/docs", "Related docs", "link")
    },
        allure.WithDescription("This test verifies login with a username and a password."),
        allure.WithOwner("John Doe"),
        allure.WithTag("smoke"),
        allure.WithSeverity("critical"),
        allure.WithAllureID("123"),
        allure.WithIssue("AUTH-123", "https://jira.example.com/browse/AUTH-123"),
        allure.WithTMS("TMS-456", "https://tms.example.com/cases/TMS-456"),
    )
}
```

### Organize tests

Allure supports both behavior-based and suite-based hierarchies. For example:

```go
func TestLogin(t *testing.T) {
    allure.Test(t, "Login works", func(a *allure.Context) {
        // ...
    },
        allure.WithEpic("Web interface"),
        allure.WithFeature("Authentication"),
        allure.WithStory("Login with username and password"),

        allure.WithParentSuite("UI tests"),
        allure.WithSuite("Authentication"),
        allure.WithSubSuite("Positive scenarios"),
    )
}
```

When no suite labels are set explicitly, the integration derives them automatically from the test file's path relative to the module root. Setting any of `WithParentSuite`, `WithSuite`, or `WithSubSuite` (or the equivalent runtime labels) replaces the entire derived hierarchy.

### Divide a test into steps

Use `a.Step` to report a block of code as a step. Steps can be nested:

```go
func TestLogin(t *testing.T) {
    allure.Test(t, "Login works", func(a *allure.Context) {
        a.Step("Open login page", func(a *allure.Context) {
            // ...
        })
        a.Step("Submit credentials", func(a *allure.Context) {
            a.Step("Fill the form", func(a *allure.Context) {
                // ...
            })
            a.Step("Click the button", func(a *allure.Context) {
                // ...
            })
        })
    })
}
```

When a step should produce a value, use the package-level generic `allure.Step` function:

```go
token := allure.Step(a, "Authorize", func(a *allure.Context) string {
    return "token-123"
})
```

A step that panics is reported as broken with the panic message and stack trace; a step in which the test fails or is skipped is reported with the corresponding status.

### Add parameters and attachments

Parameters and attachments are stored in the generated Allure results and rendered in the report:

```go
func TestLogin(t *testing.T) {
    allure.Test(t, "Login works", func(a *allure.Context) {
        a.Parameter("browser", "firefox")
        a.Attachment(
            "request.json",
            []byte(`{"username":"demo","rememberMe":true}`),
            "application/json",
        )
        a.AttachmentPath("server log", "./testdata/server.log", "text/plain")
    }, allure.WithParameter("environment", "staging"))
}
```

Attachments added inside a step are attached to that step. The file extension of the stored attachment is derived from the content type automatically.

### Report testify assertions as steps

If your tests use [testify](https://github.com/stretchr/testify), replace the assertion imports with the Allure proxy packages from the separate `github.com/allure-framework/allure-go/testify` module:

```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 keep the exact testify API. Pass the Allure context `a` instead of `t` to report each assertion as an Allure step:

```go
func TestProfile(t *testing.T) {
    allure.Test(t, "loads profile", func(a *allure.Context) {
        assert.Equal(a, "alice", profile.Name)
        require.NoError(a, err)
        assert.New(a).Len(profile.Roles, 2)
    })
}
```

Assertions that still receive a plain `*testing.T` behave exactly like upstream testify, without step reporting.

### Attach HTTP traffic

Use the `commons/httpexchange` package when tests need structured request and response evidence. To capture requests made by an HTTP client, wrap its transport:

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

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

To capture requests received by an `httptest.Server` fake service, wrap its handler:

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

Each captured exchange becomes an attachment in the [Allure HTTP Exchange format](/docs/attachments/#http-exchanges), showing the method, URL, headers, cookies, query parameters, status, and bodies. Common credentials such as `Authorization` headers, cookies, and token-like query parameters are redacted by default. See [Reference](/docs/go-reference/#http-exchange-attachments) for the available options.

### Select tests via a test plan file

The integration supports the standard Allure test plan mechanism via the `ALLURE_TESTPLAN_PATH` environment variable.

Create a JSON file such as:

```json
{
  "version": "1.0",
  "tests": [
    { "id": "123" },
    { "selector": "example/login_test.go/TestLogin/logs_in_with_valid_credentials" }
  ]
}
```

Then run the tests with:

```bash
ALLURE_TESTPLAN_PATH=./testplan.json go test ./...
```

Entries with `id` match tests that declare an Allure ID, for example via `allure.WithAllureID("123")`. Entries with `selector` match the test's full name, which consists of the test file's path relative to the module root and the full Go test name. Tests not selected by the plan are skipped before their body runs.

## Building a custom integration

If you need to integrate Allure with a custom Go test harness or helper library, use the `commons` module:

```bash
go get github.com/allure-framework/allure-go/commons
```

Helper libraries that run inside an active Allure test only need a `context.Context` and the `commons` facade — the calls safely do nothing when no test is active:

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

func instrument(ctx context.Context) {
    _ = commons.Step(ctx, "call login endpoint", func(ctx context.Context) error {
        return commons.Attachment(ctx, "payload", []byte(`{"ok":true}`), commons.AttachmentOptions{
            ContentType: "application/json",
        })
    })
}
```

Adapters that manage the test lifecycle themselves additionally use the `runtime`, `writer`, `model`, and `testplan` packages. See [Reference](/docs/go-reference/) for the main functions and options, or [Configuration](/docs/go-configuration/) for the supported environment variables.
