Golang中如何测试多个函数

Golang中如何测试多个函数 我创建了10个测试文件和一个主文件来调用这些文件,但文件没有按预期顺序调用。比如…

  1. 删除表
  2. 插入表
  3. 创建表

它按照上述顺序运行,但这样是不对的。如果按这个顺序运行,会产生表未创建的错误。

如何让它按照3、2、1的顺序运行?

谢谢。

7 回复

好的。这意味着在插入数据函数中,我需要创建一个表并插入数据。

谢谢。

更多关于Golang中如何测试多个函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的,所以你根本没有使用 main.go,而是运行 go test?不,你无法改变测试运行的顺序。你需要重新设计你的测试。

在一个良好的测试套件中,每个测试都不应依赖于其他测试。

你不能直接调用"文件",只能调用函数和方法。而且它们通常应该按照你指定的顺序运行。

也许你可以展示一些能重现你所观察行为的代码?

// 代码示例
func main() {
    fmt.Println("示例代码")
}

你能提供一些重现此行为的代码吗?这样我们就不需要安装和运行IBM-DB了。

乍看之下,main函数似乎是以正确的顺序运行内容的。

另外能否详细说明截图与此问题的关联性?

func main() {
    fmt.Println("hello world")
}

您的代码存在一些问题:

  • 不要多次使用数据库 open
  • db 必须是全局变量
  • 使用带参数的函数来创建表、插入数据等操作
  • 在完全了解如何使用之前不要使用 prepare
  • con 看起来更像是常量而非变量
  • 在每次 exec 调用后立即处理错误,而不是在3次调用后才处理 图片
  • 缩进代码行以提高可读性

在Go语言中,测试函数的执行顺序默认是按字母顺序或文件系统顺序,而不是按你期望的逻辑顺序。要控制测试的执行顺序,可以使用子测试(subtests)配合TestMain函数来显式定义顺序。以下是解决方案:

1. 使用子测试(Subtest)组织测试顺序

将你的测试函数重构为单个主测试函数内的子测试,并使用t.Run按指定顺序调用它们。

示例代码:

package main

import (
    "testing"
)

func TestMain(m *testing.M) {
    // 可选:在测试前后执行全局设置或清理
    m.Run()
}

func TestAllInOrder(t *testing.T) {
    // 按逻辑顺序定义子测试:创建表 -> 插入表 -> 删除表
    tests := []struct {
        name string
        fn   func(*testing.T)
    }{
        {"CreateTable", testCreateTable},
        {"InsertTable", testInsertTable},
        {"DeleteTable", testDeleteTable},
    }

    for _, tc := range tests {
        t.Run(tc.name, tc.fn)
    }
}

func testCreateTable(t *testing.T) {
    // 实现创建表的测试逻辑
    t.Log("Creating table...")
    // 示例:执行创建表操作并验证
}

func testInsertTable(t *testing.T) {
    // 实现插入数据的测试逻辑
    t.Log("Inserting into table...")
    // 示例:依赖表已存在,执行插入操作
}

func testDeleteTable(t *testing.T) {
    // 实现删除表的测试逻辑
    t.Log("Deleting table...")
    // 示例:清理表
}

2. 使用测试标志或依赖管理

如果子测试不适用(例如测试分布在多个文件中),可以通过环境变量或构建标签控制执行,但这需要手动干预。更直接的方法是将所有相关测试合并到一个包中,并使用上述子测试方法。

3. 运行测试命令

执行测试时,Go会按TestAllInOrder内定义的顺序运行子测试:

go test -v

输出将显示子测试按"CreateTable"、“InsertTable”、"DeleteTable"顺序执行。

关键点:

  • Go测试框架不保证跨文件的测试顺序,因此将依赖顺序的测试组织在同一个测试函数内。
  • 使用t.Run确保子测试按顺序执行,每个子测试会阻塞直到完成。
  • 避免在测试间共享状态(如数据库表),除非使用明确的设置/清理逻辑(如TestMain)。

如果测试涉及外部资源(如数据库),建议在TestMain中使用全局设置和清理,确保环境一致性。例如:

func TestMain(m *testing.M) {
    setup() // 例如创建测试数据库连接
    code := m.Run()
    teardown() // 清理资源
    os.Exit(code)
}

这种方法能解决你的表操作顺序问题,确保"创建表"先于"插入表"执行。

package main

import (
    "fmt"
	)
	
func Createconnection()(int){
	fmt.Println("this is Createconnection")
    return 1
	}


func Createtable( ) error{
	fmt.Println("this is Createtable")
	return nil

}
func Insert() error{
	fmt.Println("this is Insert")
	return nil
}

func Drop() error{
	fmt.Println("this is Drop")
	return nil
}

func Prepare() error{
	fmt.Println("this is Prepare")
	return nil
}

func Query() error{
	fmt.Println("this is Query")
	return nil
}

func Scan() error{
	fmt.Println("this is Scan")
	return nil
}

func Next() error{
	fmt.Println("this is Next")
	return nil
}

func Columns() error{
	fmt.Println("this is Columns")
	return nil
}



func Queryrow() error{
	fmt.Println("this is Queryrow")
	return nil
}

func Begin() error{
	fmt.Println("this is Begin")
	return nil
}

func Commit() error{
	fmt.Println("this is Commit")
	return nil
}

func Close()(error){
	fmt.Println("this is Close")
	return nil
}

func PoolOpen() (int){
	fmt.Println("this is PoolOpen")
	return 1
}
	
func main(){

	result:=Createconnection()
	if(result != 1){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}

	result1:=Createtable()
	if(result1 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}

	result2:=Insert()
	if(result2 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result3:=Drop()
	if(result3 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result4:=Prepare()
	if(result4 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result5:=Query()
	if(result5 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}

	result6:=Scan()
	if(result6 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result7:=Next()
	if(result7 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}

	result8:=Columns()
	if(result8 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}

	result9:=Queryrow()
	if(result9 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result10:=Begin()
	if(result10== nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result11:=Commit()
	if(result11 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result12:=Close()
	if(result12 == nil){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
	result13:=PoolOpen()
	if(result13 ==1){
		fmt.Println("Pass")
	} else {
		fmt.Println("fail")
	}
}

输出:

image

检查主函数中的调用顺序和输出(两者是不同的)。

屏幕截图如何相关?(来自上面的评论)

这些是主文件正在使用的测试文件。

回到顶部