Golang测试被终止:运行时间过长(10分钟)

Golang测试被终止:运行时间过长(10分钟) 我在驱动程序上运行一些测试时,当执行QueryRow函数10000次时出现错误。如何解决这个问题或如何更改测试运行时间?

错误:*** 测试被终止:运行时间过长(10分钟)

代码:

	for i := 0; i < 10000; i++ {
		err := t.QueryRow("select name from foo where id = ?;", 1).Scan(&name)
		if err != nil || name != "bob" {
			t.Fatalf("on query %d: err=%v, name=%q", i, err, name)
		}
	}

更多关于Golang测试被终止:运行时间过长(10分钟)的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

你使用了什么数据库和驱动程序?

更多关于Golang测试被终止:运行时间过长(10分钟)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的…谢谢

是的!这个方法奏效了 @grzkv 谢谢。

也许你的测试确实耗时过长。你可以尝试用10个查询来测试并估算平均查询时间吗?

我在默认的MySQL实例上模拟了你的示例,但未能复现你的错误。我怀疑问题出在驱动程序上,它似乎是一个早期版本 🤔 另外我也考虑可能是某处配置了不正确的超时设置。

问题分析:这个错误是因为Go测试框架默认设置了10分钟的超时限制。当测试运行超过这个时间时会被强制终止。10000次数据库查询在常规环境下确实可能超过这个时间,特别是如果数据库连接或查询本身有延迟。

解决方案:

1. 增加测试超时时间

使用 -timeout 标志来延长测试运行时间:

go test -timeout 30m

或者在测试代码中设置超时:

func TestMain(m *testing.M) {
    // 设置30分钟超时
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
    defer cancel()
    
    var code int
    done := make(chan struct{})
    
    go func() {
        code = m.Run()
        close(done)
    }()
    
    select {
    case <-done:
        os.Exit(code)
    case <-ctx.Done():
        fmt.Println("测试超时")
        os.Exit(1)
    }
}

2. 优化测试性能

使用连接池和批量查询来提高性能:

func TestQueryPerformance(t *testing.T) {
    db, err := sql.Open("driver-name", "connection-string")
    if err != nil {
        t.Fatal(err)
    }
    defer db.Close()
    
    // 设置连接池参数
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(25)
    db.SetConnMaxLifetime(5 * time.Minute)
    
    // 使用预处理语句
    stmt, err := db.Prepare("select name from foo where id = ?")
    if err != nil {
        t.Fatal(err)
    }
    defer stmt.Close()
    
    var name string
    for i := 0; i < 10000; i++ {
        err := stmt.QueryRow(1).Scan(&name)
        if err != nil || name != "bob" {
            t.Fatalf("on query %d: err=%v, name=%q", i, err, name)
        }
    }
}

3. 并行执行测试

如果测试逻辑允许,可以使用并行执行:

func TestQueryParallel(t *testing.T) {
    t.Parallel()
    
    // 原有的测试代码
    for i := 0; i < 10000; i++ {
        err := t.QueryRow("select name from foo where id = ?;", 1).Scan(&name)
        if err != nil || name != "bob" {
            t.Fatalf("on query %d: err=%v, name=%q", i, err, name)
        }
    }
}

4. 使用子测试分批执行

将大测试分解为多个子测试:

func TestQueryInBatches(t *testing.T) {
    batchSize := 1000
    batches := 10
    
    for batch := 0; batch < batches; batch++ {
        t.Run(fmt.Sprintf("batch-%d", batch), func(t *testing.T) {
            for i := 0; i < batchSize; i++ {
                err := t.QueryRow("select name from foo where id = ?;", 1).Scan(&name)
                if err != nil || name != "bob" {
                    t.Fatalf("on query %d: err=%v, name=%q", batch*batchSize+i, err, name)
                }
            }
        })
    }
}

推荐优先使用预处理语句和连接池优化的方案,这通常能显著提升数据库查询性能。如果性能仍然不足,再考虑增加超时时间。

回到顶部