本文你将学到:

  • 🤔 什么是 Allure 和 allure-go
  • 🛠️ 如何配置你的开发环境。
  • ✍️ 编写你的第一个使用 allure-go 的测试。
  • 🚀 运行测试并生成精美的 Allure 报告。
  • 📊 解读 Allure 报告的关键部分。
  • ⚡ 如何利用 Go 的特性并行运行测试,提升效率。

准备好了吗?让我们开始 Go 测试报告的魅力之旅吧!🚀💖

🤔 什么是 Allure?

Allure Framework 是一个灵活的、支持多种语言的测试报告神器 🏆。它不仅仅是展示测试通过 ✅ 或失败 ❌,更能提供一个包含测试步骤 🚶‍♀️、日志 📝、附件 📎、历史趋势 📈、环境信息 🖥️ 等丰富内容的交互式 Web 报告。这对于理解测试细节、快速定位问题 🔍、团队协作 🤝 都非常有帮助!

🤔 什么是 allure-go

allure-go 是由 Ozon Tech 团队 👨‍💻👩‍💻 开发和维护的项目,它为 Go 语言提供了完整的 Allure 功能集成。它旨在不增加开发者过多心智负担的前提下,将 Allure 的强大报告能力带入 Go 的测试生态。你可以用它来:

  • 🗂️ 组织测试套件 (Test Suites)。
  • 📝 定义详细的测试步骤 (Steps)。
  • 🏷️ 添加丰富的元数据(如标题、描述、负责人、严重性、标签、链接等)。
  • 📄 在报告中附加各种类型的文件(文本、JSON、图片等)。
  • 💨 利用 Go 的并发特性并行执行测试。

🛠️ 准备工作:环境配置

在开始编写代码之前,确保你的开发环境满足以下条件:

  1. Go 语言环境: 安装 Go 1.18 或更高版本 🟢。
    • 检查方法:在终端输入 go version
      go version go1.24.3 windows/amd64
    • 安装指南:Go 官网下载 🔗
  1. Allure 命令行工具 (Allure Commandline): 这个工具用于将 allure-go 生成的 JSON 结果文件转换成 HTML 报告 📊。
    • 检查方法:在终端输入 allure --version
    • 安装指南:
      • macOS (Homebrew): brew install allure 🍎
      • Windows (Scoop): scoop install allure 🪟
      • Linux / 手动: 参考 Allure 官方文档 🐧 / 手动 💪
      • 检查是否成功:终端输入 allure --version,看到版本号就 OK 👌!

环境就绪!让我们开始写代码吧 ⌨️。

✍️ 你的第一个 Allure Go 测试:Hello World! 👋🌍

我们将使用 allure-go 提供的 suite(测试套件)结构来组织我们的第一个测试。这是一种常见的、结构化的方式。

1. 创建项目目录和文件 📂

在你的工作区创建一个项目目录,例如 my-allure-app,然后在里面创建一个用于存放测试代码的子目录,例如 tests。在 tests 目录中,创建一个测试文件 simple_suite_test.go

my-allure-app/
├── go.mod  (稍后生成)
└── tests/
    └── simple_suite_test.go

2. 编写测试代码 (simple_suite_test.go) 📝

// 文件名: simple_suite_test.go
package simple_test // 使用一个简单的包名

import (
	"testing" // Go 标准测试库

	// Allure Go 框架的核心包
	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/suite"
)

// --- 定义一个简单的测试套件 ---
type SimpleSuite struct {
	suite.Suite // 嵌入 allure-go 基础套件
}

// --- 一个简单的测试方法 ---
func (s *SimpleSuite) TestHelloWorld(t provider.T) {
	// 添加 Allure 元数据
	t.Epic("入门示例")
	t.Feature("基本功能")
	t.Title("简单问候测试")
	t.Description("这是一个演示 allure-go 基本用法的最简单测试。")
	t.Tags("smoke", "simple") // 添加标签

	// 添加一个测试步骤
	t.WithNewStep("执行问候并验证", func(sCtx provider.StepCtx) {
		sCtx.Log("准备生成问候语...") // 在步骤中打印日志

		greeting := "Hello, Allure!"
		expected := "Hello, Allure!"

		sCtx.Logf("生成的问候语: %s", greeting) // 带格式的日志

		// 执行断言 (会自动记录为子步骤)
		// t.Require() 中的断言如果失败,会停止当前测试
		sCtx.Require().Equal(expected, greeting, "问候语应该匹配预期值")

		sCtx.Log("验证成功!")
	})

	// 测试方法级别的日志
	t.Log("TestHelloWorld 测试完成。")
}

// --- 套件运行器 ---
// 这是 Go testing 包识别并执行测试套件的入口函数
func TestRunSimpleSuite(t *testing.T) {
	// 使用 suite.RunSuite 运行我们定义的 SimpleSuite
	suite.RunSuite(t, new(SimpleSuite))
}

代码详解 (带 Emoji 版 😉):

  • package simple_test: 定义包名,测试文件通常使用 _test 后缀 🏷️。
  • import (...):
    • testing: Go 标准库,测试的基础 🧱。
    • github.com/ozontech/allure-go/pkg/framework/provider: 提供了 provider.T 类型,它是 allure-go 增强的测试上下文,包含了添加元数据、步骤等方法 ✨。
    • github.com/ozontech/allure-go/pkg/framework/suite: 提供了 suite.Suite 结构,用于组织测试套件 🗂️。
    • github.com/ozontech/allure-go/pkg/allure: 包含了 Allure 的数据模型和常量,如 SeverityLinkType 等 🌟。
  • type SimpleSuite struct { suite.Suite }: 定义了一个名为 SimpleSuite 的结构体,通过嵌入 suite.Suite 来继承 allure-go 套件的功能 💪。
  • func (s *SimpleSuite) TestHelloWorld(t provider.T): 定义了一个测试方法 🧪。
    • 方法必须是套件(*SimpleSuite)的成员。
    • 方法名必须以 Test 开头 ✍️。
    • 接收一个 provider.T 类型的参数 t,我们通过 t 来与 Allure 交互 🤝。
  • t.Epic(), t.Feature(), t.Title(), t.Description(), t.Tags(), t.SetSeverity(), t.Owner(): 这些方法用于给测试用例添加各种元数据,让报告更具可读性 👀。
  • t.WithNewStep("步骤名", func(sCtx provider.StepCtx) { ... }): 创建一个命名的测试步骤 🚶。步骤内的代码会在一个闭包函数中执行。sCtx 是步骤的上下文 📜。
  • sCtx.Log(), sCtx.Logf(), sCtx.WithNewParameters(): 在步骤内部记录信息和参数 📝。
  • sCtx.Require().Equal(...): 这是 testify 库提供的断言方法,allure-go 对其进行了包装 🎁。每次断言都会在 Allure 报告中自动生成一个子步骤,显示断言的操作和结果 ✅/❌。Require 在失败时会中断测试 🛑。
  • func TestRunSimpleSuite(t *testing.T): 这是 Go testing 能识别的入口函数 ▶️。
  • suite.RunSuite(t, new(SimpleSuite)): allure-go 提供的函数,用于执行指定套件 (SimpleSuite) 中的所有 Test 开头的方法 🏃‍♀️。

🚀 运行测试并生成报告 📊

现在代码写好了,让我们来运行它!

  1. 打开终端/命令行 💻,进入你的项目根目录 (my-allure-app)。
  2. 初始化 Go 模块 (如果还没有 go.mod 文件):
    go mod init my-allure-app # 将 my-allure-app 替换为你的模块名
    
  3. 下载依赖: go mod tidy 会自动分析代码并下载所有需要的库 (allure-go, testify 等) 📦。
    go mod tidy
    
  4. 运行 Go 测试: 执行 go test 命令,并指向包含测试文件的包 🎯。
    go test
    
    • ./tests/... 表示运行 tests 目录及其所有子目录下的测试 🔄。
    • 成功运行后,你应该会看到类似 PASSok testg/tests ... 的输出 ✅。
    • 关键: 在项目根目录 (my-allure-app) 下,你会发现一个新生成的 allure-results 文件夹 📁。这里面存放着测试过程中产生的 JSON 格式的原始结果文件 📄。
  1. 生成 Allure 报告: 使用 allure 命令行工具处理 allure-results ✨。
    allure generate allure-results --clean
    
    • allure generate 是生成报告的命令。
    • allure-results 是输入目录。
    • --clean (可选) 会先清除之前生成的报告 🧹。
    • 此命令会在当前目录下生成一个 allure-report 文件夹,里面是 HTML 报告 🌐。
  1. 打开 Allure 报告:
    allure open
    
    • 此命令会启动一个本地 Web 服务器,并在你的默认浏览器中打开报告!🎉

现在,你应该能看到一个漂亮的 Allure 报告页面了!🤩

🧐 解读 Allure 报告

打开报告后,你会看到很多有用的信息:

  • Overview 📊: 报告的概览,显示测试总数、通过率、失败率、以及各种元数据(如 Epic, Feature)的分布饼图 पाई।
  • Suites 🗂️: 按测试套件(我们例子中的 SimpleSuite)和测试方法(TestHelloWorld)组织的树状结构。点击测试方法可以查看其详细信息。
  • Behaviors 🎭: 按 Epic -> Feature -> Story 组织的视图,适合从功能角度查看测试覆盖。
  • Graphs 📈: 提供各种维度的统计图表,如按状态、严重性、执行时间分布等。
  • Timeline ⏳: 显示测试用例的执行时间线,对于识别性能瓶颈和观察并行执行效果很有用。

点击我们运行的 TestHelloWorld,你会看到:

  • 左侧是测试的元数据(描述、严重性、负责人、标签等)🏷️。
  • 右侧是测试的执行细节:
    • 清晰的测试步骤("执行问候并验证")🚶‍♀️。
    • 步骤内的日志 (sCtx.Log 输出) 📝。
    • 步骤参数 📊。
    • 断言自动生成的子步骤 (Require.Equal) 及其状态 ✅。

花点时间探索一下报告的各个部分,感受它的强大之处吧!💪

⚡ 更进一步:并行测试 💨

当测试用例数量增多时 📈,顺序执行会变得很慢 🐌。Go 语言天生擅长并发 🚀,allure-go 也很好地支持了利用 Go 的 t.Parallel() 来并行执行测试用例,从而大大缩短总测试时间 ⏱️!

如何实现?

非常简单!只需要在你想并行执行的测试方法内部,调用 t.Parallel() 即可。就这么 Easy!😎

示例代码 (parallel_suite_test.go)

tests 目录下创建新文件 parallel_suite_test.go

// 文件名: parallel_suite_test.go
package parallel_test

import (
	"testing"
	"time" // 引入 time 包来模拟耗时操作

	"github.com/ozontech/allure-go/pkg/framework/provider"
	"github.com/ozontech/allure-go/pkg/framework/suite"
)

// --- 定义并行测试套件 ---
type ParallelSuite struct {
	suite.Suite // 嵌入基础套件
}

// --- 测试方法 1 ---
func (s *ParallelSuite) TestOne(t provider.T) {
	// !!! 标记此测试可以与其他 Parallel 测试并发运行 !!!
	t.Parallel()

	// 添加 Allure 元数据
	t.Epic("并发执行示例")
	t.Feature("并行测试")
	t.Title("并行测试用例 1")
	t.Description("这个测试会模拟一些耗时操作,并与其他测试并行执行。")
	t.Tags("parallel", "test1")

	t.WithNewStep("步骤 A - 测试 1", func(sCtx provider.StepCtx) {
		sCtx.Log("开始执行测试 1 的步骤 A...")
		// 模拟耗时 1 秒
		time.Sleep(1 * time.Second)
		sCtx.Log("步骤 A 完成。")
		sCtx.Require().True(true, "简单断言") // 添加一个简单断言
	})

	t.WithNewStep("步骤 B - 测试 1", func(sCtx provider.StepCtx) {
		sCtx.Log("开始执行测试 1 的步骤 B...")
		// 模拟耗时 1.5 秒
		time.Sleep(1500 * time.Millisecond)
		sCtx.Log("步骤 B 完成。")
	})

	t.Logf("并行测试用例 1 (TestOne) 完成 @ %s", time.Now().Format(time.RFC3339Nano))
}

// --- 测试方法 2 ---
func (s *ParallelSuite) TestTwo(t provider.T) {
	// !!! 标记此测试可以与其他 Parallel 测试并发运行 !!!
	t.Parallel()

	// 添加 Allure 元数据
	t.Epic("并发执行示例")
	t.Feature("并行测试")
	t.Title("并行测试用例 2")
	t.Description("这是另一个并行执行的测试用例。")
	t.Tags("parallel", "test2")

	t.WithNewStep("步骤 X - 测试 2", func(sCtx provider.StepCtx) {
		sCtx.Log("开始执行测试 2 的步骤 X...")
		// 模拟耗时 2 秒
		time.Sleep(2 * time.Second)
		sCtx.Log("步骤 X 完成。")
	})

	t.Logf("并行测试用例 2 (TestTwo) 完成 @ %s", time.Now().Format(time.RFC3339Nano))
}

// --- 测试方法 3 (不使用 Parallel) ---
func (s *ParallelSuite) TestThreeSequential(t provider.T) {
	// !!! 这个测试没有调用 t.Parallel(),它会等待前面的并行测试完成后再顺序执行 !!!
	// 或者,如果它在所有 Parallel 测试之前被调度,其他 Parallel 测试会等它完成。
	// Go 的测试调度器会管理这些。

	t.Epic("并发执行示例")
	t.Feature("顺序测试")
	t.Title("顺序执行的测试用例 3")
	t.Description("这个测试没有标记为并行,会按顺序执行。")
	t.Tags("sequential", "test3")

	t.WithNewStep("步骤 Z - 测试 3", func(sCtx provider.StepCtx) {
		sCtx.Log("开始执行顺序测试 3 的步骤 Z...")
		// 模拟耗时 0.5 秒
		time.Sleep(500 * time.Millisecond)
		sCtx.Log("步骤 Z 完成。")
	})

	t.Logf("顺序测试用例 3 (TestThreeSequential) 完成 @ %s", time.Now().Format(time.RFC3339Nano))
}

// --- 套件运行器 ---
func TestRunParallelSuite(t *testing.T) {
	// 运行 ParallelSuite 套件
	// Go 的 testing 包会自动处理 t.Parallel() 的调度
	suite.RunSuite(t, new(ParallelSuite))
}

代码解释 (带 Emoji 版 😉):

  • 我们在 TestParallelOneTestParallelTwo 的开头调用了 t.Parallel() ✨。
  • TestSequentialThree 没有调用 t.Parallel(),它会顺序执行 🚶‍♂️。
  • 我们使用 time.Sleep() 模拟耗时操作 ⏳,以便观察并行效果。

运行并行测试:

  1. 保存文件 parallel_suite_test.go 💾。
  2. 同步依赖 (如果需要): go mod tidy 📦。
  3. 运行测试 (建议加 -v 查看详细日志):
    go test  -v
    
    • 观察控制台输出 👀,你可能会看到 TestParallelOneTestParallelTwo 的日志交错出现 🔀,它们的完成时间戳可能非常接近 🤏。
    • 注意观察 go test 命令执行的总时间 ⏱️。如果测试是顺序执行的,总时间大约是 1s + 1.5s + 0.5s = 3s。但并行执行后,总时间应该会明显缩短(接近于最长并行测试的时间 1.5s 加上顺序测试的时间 0.5s,大约 2s 左右)⚡️!
    • === RUN   TestRunParallelSuite
      === RUN   TestRunParallelSuite/ParallelSuite
      === RUN   TestRunParallelSuite/ParallelSuite/Tests
      === RUN   TestRunParallelSuite/ParallelSuite/Tests/TestOne
      === PAUSE TestRunParallelSuite/ParallelSuite/Tests/TestOne
      === RUN   TestRunParallelSuite/ParallelSuite/Tests/TestThreeSequential
          main_test.go:82: 开始执行顺序测试 3 的步骤 Z...
          main_test.go:85: 步骤 Z 完成。
          main_test.go:88: 顺序测试用例 3 (TestThreeSequential) 完成 @ 2025-05-12T21:06:27.6568988+08:00
      === RUN   TestRunParallelSuite/ParallelSuite/Tests/TestTwo
      === PAUSE TestRunParallelSuite/ParallelSuite/Tests/TestTwo
      === CONT  TestRunParallelSuite/ParallelSuite/Tests/TestOne
      === CONT  TestRunParallelSuite/ParallelSuite/Tests/TestTwo
      === NAME  TestRunParallelSuite/ParallelSuite/Tests/TestOne
          main_test.go:30: 开始执行测试 1 的步骤 A...
      === NAME  TestRunParallelSuite/ParallelSuite/Tests/TestTwo
          main_test.go:60: 开始执行测试 2 的步骤 X...
      === NAME  TestRunParallelSuite/ParallelSuite/Tests/TestOne
          main_test.go:33: 步骤 A 完成。
          main_test.go:38: 开始执行测试 1 的步骤 B...
      === NAME  TestRunParallelSuite/ParallelSuite/Tests/TestTwo
          main_test.go:63: 步骤 X 完成。
          main_test.go:66: 并行测试用例 2 (TestTwo) 完成 @ 2025-05-12T21:06:29.6716268+08:00
      === NAME  TestRunParallelSuite/ParallelSuite/Tests/TestOne
          main_test.go:41: 步骤 B 完成。
          main_test.go:44: 并行测试用例 1 (TestOne) 完成 @ 2025-05-12T21:06:30.1722998+08:00
      --- PASS: TestRunParallelSuite (3.02s)
          --- PASS: TestRunParallelSuite/ParallelSuite (3.02s)
              --- PASS: TestRunParallelSuite/ParallelSuite/Tests (0.52s)
                  --- PASS: TestRunParallelSuite/ParallelSuite/Tests/TestThreeSequential (0.51s)
                  --- PASS: TestRunParallelSuite/ParallelSuite/Tests/TestTwo (2.00s)
                  --- PASS: TestRunParallelSuite/ParallelSuite/Tests/TestOne (2.50s)
      PASS
      ok      testg   3.649s
  4. 生成并查看报告:
    allure generate allure-results --clean 
    allure open
    
    • 在 Allure 报告的 Timeline ⏳ 视图中,你可以清晰地看到 TestParallelOneTestParallelTwo 的执行时间条有重叠 ⏸️⏸️,而 TestSequentialThree 则在它们之后(或之前)执行,没有重叠 ➖。

 

通过 t.Parallel(),你可以轻松地让你的 Go 测试跑得更快!💨💨💨

Allure
🏠 Overview
🚩 Categories
💼 Suites
📊 Graphs
⏱️ Timeline
🏷️ Behaviors
📦 Packages

ALLURE REPORT 5/12/2025

20:28:18 - 20:30:18 (1m 59s)

4
test cases
 
100%

SUITES 2 items total

ParallelSuite
3
SimpleSuite
1

ENVIRONMENT

There are no environment variables

FEATURES BY STORIES 2 items total

并发执行示例
2
入门示例
1

TREND

There is nothing to show

CATEGORIES 0 items total

There is nothing to show

EXECUTORS

There is no information about tests executors

总结与展望 🎓🔭

恭喜你!🥳 你已经成功入门了 allure-go,掌握了:

  • 🛠️ 配置环境和依赖。
  • ✍️ 使用 suite 结构编写测试。
  • 🏷️ 添加 Allure 元数据和测试步骤。
  • 🚀 运行测试并生成、查看 Allure 报告。
  • ⚡ 利用 t.Parallel() 实现测试并行化。

allure-go 的功能远不止这些,你还可以探索:

  • 更丰富的元数据: t.SetIssue() (关联 JIRA 等 🐞), t.SetTestCase() (关联 TestRail 等 ✅), t.SetLink() (添加文档链接 🔗) 等。
  • 附件: 使用 t.Attachment()sCtx.Attachment() 添加截图 🖼️、日志文件 📄、API 请求/响应体 <-> 等。
  • 参数化测试: allure-go 提供了强大的参数化测试功能 🔢,可以轻松实现数据驱动测试。
  • Setup/Teardown 钩子: BeforeAll ☀️, AfterAll 🌙, BeforeEach ✨, AfterEach 🧹 用于在测试套件或测试方法执行前后进行准备和清理工作。

希望这篇入门指南能帮助你开启使用 allure-go 提升 Go 项目测试质量和效率的大门🚪。建议查阅 allure-go 的官方 GitHub 仓库 获取更详细的文档和示例 📚。