【发布时间】:2020-03-14 21:48:54
【问题描述】:
我想知道我仅用于测试的库是否会包含在最终构建分发中。我在 go.mod/go.sum 文件中看到了依赖项,但我无法检查最终的二进制文件。
我猜 Go 构建工具会以某种方式处理冗余代码,但我没有找到任何证据。
有人能指出我在文档中的那个地方或描述行为吗?
【问题讨论】:
标签: unit-testing go testing go-modules
我想知道我仅用于测试的库是否会包含在最终构建分发中。我在 go.mod/go.sum 文件中看到了依赖项,但我无法检查最终的二进制文件。
我猜 Go 构建工具会以某种方式处理冗余代码,但我没有找到任何证据。
有人能指出我在文档中的那个地方或描述行为吗?
【问题讨论】:
标签: unit-testing go testing go-modules
官方文档:Command go: Compile packages and dependencies:
编译包时,build 会忽略以 '_test.go' 结尾的文件。
同样来自testing的包文档:
要编写新的测试套件,请创建一个以 _test.go 结尾的文件,其中包含此处所述的 TestXxx 函数。将文件放在与正在测试的文件相同的包中。该文件将从常规包构建中排除,但会在运行“go test”命令时包含。
构建您的应用甚至不涉及测试文件。所以不,仅从测试中引用的依赖项不包含在可执行二进制文件中。
还有,测试有多难?编写一个简单的应用程序,构建它。注意编译后二进制文件的大小。
添加一个测试文件,参考一些lib。再次构建,大小不会改变。现在,如果您从应用程序中引用包并再次构建,它会增长。
例子:
package main
func main() {
println("Hello world")
}
基于 linux (Go 1.13) 构建,大小为:1,148,861 字节。
添加测试:
package main
import (
"fmt"
"testing"
"time"
)
func TestOne(t *testing.T) {
fmt.Println(time.Now())
}
大小不变。现在将这个 TestOne() 函数(以及所需的导入)添加到主应用程序:大小增加到 2,165,259 字节。
【讨论】:
我想知道我仅用于测试的库是否会是 包含在最终构建分发中。我看到依赖项 go.mod/go.sum 文件,但我无法检查最终的二进制文件。
构建二进制文件时,它包含大量附加信息,包括符号表。其中符号是代码中可识别的名称。
阅读更多关于这个https://www.grant.pizza/dissecting-go-binaries/
您可以使用readelf、objdump 或nm 等程序列出导入的包,对于类似Linux 的系统,对于Windows 系统,可执行文件格式名为PE,您将需要特定的解释器。
查看这两个会话
[mh-cbon@Host-001 pyt] $ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}
[mh-cbon@Host-001 pyt] $ go build -o bin
[mh-cbon@Host-001 pyt] $ nm bin | grep testing
使用testing 包构建的程序
[mh-cbon@Host-001 pyt] $ cat main.go
package main
import (
"fmt"
"testing"
)
func main() {
fmt.Println("hello world!")
_ = testing.T{}
}
[mh-cbon@Host-001 pyt] $ go build -o bin
[mh-cbon@Host-001 pyt] $ nm bin | grep testing
00000000004e30e0 R go.itab.*testing.benchTimeFlag,flag.Value
0000000000574b90 B testing.benchmarkMemory
00000000005614b0 D testing.benchTime
0000000000494320 T testing.(*benchTimeFlag).Set
【讨论】: