GO 学习笔记之五 编程(三)单元测试 ( VSCODE工具运行 )
一、目的
当本地写好了一个go文件之后,希望通过单元测试来验证写的go文件中代码逻辑是否正确,减少后期发现问题成本。本案例介绍如何在VSCODE 工具中触发执行和单点debug执行单元测试函数(注意:VSCODE工具有一个致命不好的点就是慢)
二、编写单元测试
假设:当前业务逻辑go文件为 sqldm.go,且其中有一个 NewDmDataSource 函数,现在需要对该函数进行单元测试。
其中 sqldm.go 代码如下
package sqldb import ( "database/sql" "fmt" _ "dm" "test.com/pkg/middleware/database/dbconfig" "test.com/pkg/tools/logger" ) type DmDataSource struct { dataSource *SqlDataSource } func (dmDataSource *DmDataSource) GenerateDBsn() string { return dmDataSource.generateDBsn(dmDataSource.dataSource.dbconfig) } func (dmDataSource *DmDataSource) generateDBsn(dbconfig *dbconfig.DbConfig) string { return fmt.Sprintf("dm://%s:%s@%s:%d", dbconfig.GetUsername(), dbconfig.GetPwd(), dbconfig.GetHost(), dbconfig.GetPort()) } func NewDmDataSource(dbconfigP *dbconfig.DbConfig) (*DmDataSource, error) { dmDataSource := &DmDataSource{} db, err := sql.Open(dbconfig.DmAliasDbDriver.DriverAlias, dmDataSource.generateDBsn(dbconfigP)) if err != nil { logger.Error("cannot generate datasource for postgres.[host:%s,port:%d,username:%s,dbname:%s,pwd:%s]", dbconfigP.GetHost(), dbconfigP.GetPort(), dbconfigP.GetUsername(), dbconfigP.GetDbname(), dbconfigP.GetPwd(), err) return nil, err } dmDataSource.dataSource = &SqlDataSource{dbconfigP, db} return dmDataSource, nil }
具体需要做如下工作:
1、编写单元测试文件
1) 在sqldm.go 同级目录下创建 sqldm_test.go文件(单元测试文件必须以_test.go 结尾)
2)在 sqldm_test.go 引入 testing 包
3) 所有测试函数必须以 Test 开头,创建 TestDmConn 函数,参数为 *testing.T 类型
sqldm_test.go 文件内容如下:
package sqldb import ( "testing" "test.com/pkg/middleware/database/dbconfig" ) func TestDmConn(t *testing.T) { _dbconfig, _err := dbconfig.NewDBConfig("10.19.219.160", "SYSDBA", "SYSDBA", "SYSDBA", 5236, dbconfig.Dameng) if _err != nil { t.Fatal("config for dameng is wrong", _err) } _dbconfig.SetPoolMaxIdleConns(0) _dbconfig.SetPoolMaxOpenConns(1) _pg_data_source, err := NewDmDataSource(_dbconfig) if err != nil { t.Fatal("cannot create datasource for dameng", err) } defer _pg_data_source.dataSource.getDb().Close() _err = _pg_data_source.dataSource.db.Ping() if _err != nil { t.Fatal("cannot connect dameng", _err) } t.Logf("get connction for dameng success,%v", _dbconfig) }
三、执行单元测试
1、单独运行单元测试函数
在VSCODE 中,可以通过以下方式进行单独运行该函数方法:



1.1 直接通过 Test 函数前头的 绿色箭头运行图标 执行运行
直接打开 单元测试文件,每个可执行的 Test 开头的单元测试函数前面会自动出现 绿色图标,见上图,点击 可执行该单元测试函数


1.2 直接通过 Test 函数上头的 run test 执行运行

1.3 选择 Test 开头的测试函数,右键选择"Test Function At Cursor"

效果图上图,如下:

2、执行单元测试文件(_test.go 结尾的文件)中的所有测试函数
2.1 右键文件,选择"运行函数"


3、执行某个包中的所有单元测试文件中的所有 Test开头的测试函数
3.1 右键 包所属的目录,选择"运行测试"

四、单点调试单元测试函数
1、配置 debug 可执行文件
需要先配置 launch.json文件,左侧菜单点击 debug 图标,然后点击顶部的 设置图标,选择添加配置,自动生成右侧的 launch.json文件内容,此时需要将 program 值调整成 main函数所在go文件

2、使用 单元测试函数上方的 debug test

当程序执行到断点处,会停止下来,可以点击顶部的调试debug图标,进行相应的操作。
3、选中 Test 函数 右键选择 "Debug Test At Cursor"


五、遇到的问题
1、执行单元测试报 “exit status 0xc0000135”,windows界面弹框爆出来的错误如下图

VSCODE终端上执行结果如下:

1.1 原因
该问题是由于无法加载需要的DLL导致的。
分析思路:在该工程中有加载 C++ 库 调用其中提供的方法的逻辑,go 编写中 是去加载当前运行程序所在同级目录下的一个子目录(lib)下的dll文件。当正式运行时,通过打包的确是会将这个lib放到运行程序二进制成果物同级下,但是 单元测试则不会。
通过 go test -x -run ^TestGetLastExecution$ ./internal/monitor/ 命令 (-x 表示输出详细信息),不通过 VSCODE 提供的菜单方式执行 单元测试,可以看到如下详细信息:

从中可以看出,go test 实际是编译了整个工程,且生成 test.exe 这个可执行程序,将其放在服务器上的一个临时目录中,在该目录中执行了这个 test.exe 程序,根据上述分析 需要加载 test.exe 所在同级目录中的lib下的dll ,基于此,必须要想办法设置这个dll 路径才能解决。
1.2 解决办法
方案1:切换到CMD终端
- 关闭当前 PowerShell 窗口。
- 打开 CMD(命令提示符):
- 按
Win + R,输入cmd回车。
- 按
- 在 CMD 中执行:
set PATH=%PATH%;E:\gowork\lib\ go test -v -run ^TestYourFuncName$ ./...
方案2:在PowerShell中正确设置PATH
PowerShell 的语法与 CMD 不同,需使用 $env:PATH:
# 临时添加PATH(仅当前会话有效) $env:PATH += ";E:\gowork\lib" # 验证是否添加成功 echo $env:PATH # 运行测试 go test -v -run ^TestYourFuncName$ ./...

从上可以看到 已经可以执行了,不报 0xc0000135 错误了。
方案3:VSCODE上临时添加PATH(仅当前会话有效)
1.3 技巧
1.3.1 验证DLL是否可加载
# 检查文件是否存在 Test-Path "E:\gowork\src\git\USTA-brs\code\brsweb\identify_lib\win64\yourlib.dll" # 查看DLL依赖项(需安装Visual Studio或dumpbin工具) dumpbin /dependents E:\gowork\src\git\USTA-brs\code\brsweb\identify_lib\win64\yourlib.dll

浙公网安备 33010602011771号