Getting started with Go Testing
Generate beautiful HTML reports using Allure Report and your Go tests.
INFO
The main user-facing package is 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 instead. Both packages live in the official allure-go repository, which also provides testify-compatible assertion packages and HTTP evidence helpers.
Setting up
1. Prepare your project
Make sure a recent Go toolchain is installed.
The official
allure-gopackages require Go 1.25 or newer.Open a terminal and go to the project directory. For example:
bashcd /home/user/myprojectInstall Allure Report, following the installation guide.
Add the
gotestintegration:bashgo get github.com/allure-framework/allure-go/commons/gotestWrap your tests with
allure.Test. Inside the body, use the provided context to declare steps, parameters, and attachments.gopackage 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:
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:
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:
allure generate ./allure-results --output ./allure-report
allure open ./allure-reportWriting 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,
- organize tests into behavior-based and suite-based hierarchies,
- split the execution into nested steps,
- describe parameters and attachments,
- report testify assertions as steps,
- attach structured HTTP traffic evidence,
- run only selected tests through 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. Metadata discovered during execution can be added at runtime with methods on the test's *allure.Context:
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:
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:
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:
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:
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, replace the assertion imports with the Allure proxy packages from the separate github.com/allure-framework/allure-go/testify module:
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:
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:
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:
server := httptest.NewServer(httpexchange.NewHandler(a.Context(), handler))
defer server.Close()Each captured exchange becomes an attachment in the Allure HTTP Exchange format, 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 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:
{
"version": "1.0",
"tests": [
{ "id": "123" },
{ "selector": "example/login_test.go/TestLogin/logs_in_with_valid_credentials" }
]
}Then run the tests with:
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:
go get github.com/allure-framework/allure-go/commonsHelper 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:
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 for the main functions and options, or Configuration for the supported environment variables.