Go子文件夹中的测试:初学者完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Go子文件夹中的测试:解决教程中避而不谈的问题

\n\n

您是否曾经编写过Go测试,发现它们在项目根目录下运行良好,但一旦移到子文件夹中就全部失效?熟悉吗?如果是这样——您并不孤单。Stack Overflow上的问题"Golang tests in sub-directory"已经积累了数千次浏览。这并不奇怪:Go文档对此语焉不详,而初学者开发者常常感到困惑。

\n\n

在本文中,我们将探讨如何正确组织使用嵌套包的Go测试,为什么需要这样做,以及如何避免踩坑。开始吧!

\n\n

为什么子文件夹中的测试是个痛点?

\n\n

想象一下:您有一个项目,其结构如下:

\n\n
myapp/\n├── main.go\n├── go.mod\n└── utils/\n    ├── math.go\n    └── math_test.go
\n\n

您在根目录运行Go test——一切正常。但当您尝试从utils文件夹运行测试时,Go报错:"package myapp/utils is not in GOROOT"。熟悉这个错误吗?

\n\n

问题在于Go处理的是包,而不是文件夹。当您创建子文件夹时,实际上是在创建一个新的包。其中的测试需要根据项目的模块结构来运行。但让我们按顺序来。

\n\n

基础:Go如何看待测试

\n\n

在Go中,测试是后缀为_test.go的普通文件。它们可以位于:

\n
    \n
  • 同一个包中(白盒测试)——可以访问未导出的函数。
  • \n
  • 后缀为_test的独立包中(黑盒测试)——像外部用户一样测试包。
  • \n
\n\n

当您将测试放入子文件夹时,您创建了一个新的包。例如,utils文件夹就是utils包。其中的测试必须属于这个包。

\n\n

正确结构的示例

\n\n
myapp/\n├── go.mod\n├── main.go\n└── utils/\n    ├── math.go        // package utils\n    └── math_test.go   // package utils
\n\n

在math.go文件中:

\n
package utils\n\nfunc Add(a, b int) int {\n    return a + b\n}
\n\n

在math_test.go文件中:

\n
package utils\n\nimport "testing"\n\nfunc TestAdd(t *testing.T) {\n    result := Add(2, 3)\n    if result != 5 {\n        t.Errorf("Expected 5, got %d", result)\n    }\n}
\n\n

现在从项目根目录运行测试:

\n
go test ./utils/
\n\n

或者从utils文件夹:

\n
cd utils\ngo test
\n\n

一切正常!但如果您的结构更复杂呢?

\n\n

嵌套子文件夹:比看起来更深

\n\n

假设您有一个项目,结构如下:

\n\n
myapp/\n├── go.mod\n├── main.go\n└── services/\n    ├── user/\n    │   ├── user.go\n    │   └── user_test.go\n    └── order/\n        ├── order.go\n        └── order_test.go
\n\n

这里每个子文件夹都是一个独立的包。要递归运行所有测试,请使用三个点:

\n\n
go test ./...
\n\n

这个命令会找到项目中的所有包并运行它们的测试。对于CI/CD非常方便!

\n\n

如果测试与代码在同一文件夹中呢?

\n\n

有时开发者将测试放在与主代码相同的文件夹中。这对于小型项目来说是可以的。但对于大型项目,最好将测试放在单独的子文件夹中——这样结构会更清晰。

\n\n

典型错误及其解决方案

\n\n

让我们分析一下初学者在处理Golang tests in sub-directory时最常见的错误。

\n\n

错误1:"package is not in GOROOT"

\n

原因:您试图从子文件夹运行测试,但没有指定模块。Go不知道包属于哪个模块。

\n

解决方案:确保根目录下有go.mod文件

博客

书籍推荐