Golang测试包日志 - 如何集成到集中管理工具

Golang测试包日志 - 如何集成到集中管理工具 你好,

我是自动化团队的一员。我们正在使用 testing 包来运行大量的测试用例。

我们的目标是收集每个测试用例的日志,并将其存储在对象存储(如 S3 或 Google Storage)中。这样我们就可以创建一个日志链接,并通过网页浏览器访问它。

现在问题来了,如果我们使用 log 包,我们可以将输出设置到一个文件并生成日志。一旦测试用例执行完成,就将文件传输到 S3 或 Google Storage。

但是使用 testing 包时,T.log("") 只会在测试执行期间将日志打印到控制台,而且还需要使用 verbose 命令。

然而,在我们现有的测试套件中,我们只使用 testing 包的 T.log("") 命令来打印日志。切换到 log 包并不容易,因为那样在执行测试时不会在控制台打印任何日志。

请问有人能就如何处理这种情况提供一些想法吗?

附注:我是 Go 语言的新手。


更多关于Golang测试包日志 - 如何集成到集中管理工具的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang测试包日志 - 如何集成到集中管理工具的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你可以通过实现一个自定义的 testing.TB 接口来捕获 T.Log() 的输出,同时保持控制台输出。以下是一个示例:

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "os"
    "testing"
)

// LogCapture 实现 testing.TB 接口
type LogCapture struct {
    testing.TB
    buf *bytes.Buffer
    tee io.Writer
}

func (lc *LogCapture) Log(args ...interface{}) {
    // 写入缓冲区用于后续存储
    fmt.Fprint(lc.buf, args...)
    lc.buf.WriteByte('\n')
    
    // 同时输出到控制台
    fmt.Fprint(lc.tee, args...)
    fmt.Fprintln(lc.tee)
    
    // 调用原始 Log 方法(如果需要)
    lc.TB.Log(args...)
}

func (lc *LogCapture) Logf(format string, args ...interface{}) {
    // 写入缓冲区
    fmt.Fprintf(lc.buf, format, args...)
    lc.buf.WriteByte('\n')
    
    // 输出到控制台
    fmt.Fprintf(lc.tee, format, args...)
    fmt.Fprintln(lc.tee)
    
    lc.TB.Logf(format, args...)
}

// 获取捕获的日志内容
func (lc *LogCapture) GetLogs() string {
    return lc.buf.String()
}

// 示例测试函数
func TestExample(t *testing.T) {
    // 创建捕获器
    buf := &bytes.Buffer{}
    lc := &LogCapture{
        TB:  t,
        buf: buf,
        tee: io.MultiWriter(os.Stdout), // 输出到控制台
    }
    
    // 使用捕获器记录日志
    lc.Log("测试开始")
    lc.Logf("参数: %d, %s", 123, "test")
    
    // 模拟测试逻辑
    if 1+1 != 2 {
        lc.Fatal("数学错误")
    }
    
    lc.Log("测试完成")
    
    // 这里可以添加上传到 S3 的逻辑
    logs := lc.GetLogs()
    fmt.Printf("捕获的日志:\n%s", logs)
    
    // 示例上传函数(需要实现具体逻辑)
    // uploadToS3("test-log.txt", logs)
}

// 辅助函数:创建带日志捕获的测试
func RunTestWithCapture(t *testing.T, testFunc func(t *testing.T)) {
    buf := &bytes.Buffer{}
    lc := &LogCapture{
        TB:  t,
        buf: buf,
        tee: io.MultiWriter(os.Stdout),
    }
    
    // 运行测试
    testFunc(lc)
    
    // 处理日志
    logs := lc.GetLogs()
    if logs != "" {
        // 这里添加你的存储逻辑
        log.Printf("测试日志已捕获,长度: %d 字节", len(logs))
        // saveLogsToStorage(t.Name(), logs)
    }
}

func TestAnother(t *testing.T) {
    RunTestWithCapture(t, func(t *testing.T) {
        t.Log("这是另一个测试")
        t.Logf("数值: %v", 42)
    })
}

对于测试套件的集成,你可以在 TestMain 中设置全局处理器:

func TestMain(m *testing.M) {
    // 创建全局日志文件
    logFile, _ := os.Create("test-run.log")
    defer logFile.Close()
    
    // 设置多输出:控制台 + 文件
    multiWriter := io.MultiWriter(os.Stdout, logFile)
    
    // 包装测试运行
    os.Exit(testMainWithCapture(m, multiWriter))
}

func testMainWithCapture(m *testing.M, output io.Writer) int {
    // 保存原始 testing.Verbose 等设置
    return m.Run()
}

要上传到云存储,添加类似这样的函数:

func uploadLogsToS3(testName, logs string) error {
    // 实现你的 S3 上传逻辑
    // 例如使用 aws-sdk-go
    filename := fmt.Sprintf("%s-%s.log", testName, time.Now().Format("20060102-150405"))
    
    // 伪代码示例:
    // sess := session.Must(session.NewSession())
    // uploader := s3manager.NewUploader(sess)
    // _, err := uploader.Upload(&s3manager.UploadInput{
    //     Bucket: aws.String("your-bucket"),
    //     Key:    aws.String(filename),
    //     Body:   strings.NewReader(logs),
    // })
    
    return nil
}

这种方法允许你:

  1. 保持现有的 T.Log() 调用方式不变
  2. 同时输出到控制台和缓冲区
  3. 在测试完成后获取所有日志内容
  4. 将日志上传到云存储

你只需要在测试初始化时包装 testing.T 对象,现有的测试代码无需修改。

回到顶部