将测试移至子文件夹并导入main包的Golang实践

将测试移至子文件夹并导入main包的Golang实践 你好。

我在根目录下构建了一个应用程序,其 *.go 文件的包设置为 main

我还在同一个“根”目录下构建了一些测试文件 *_test.go

后来,我将所有 *_test.go 文件移到了一个名为 test 的子文件夹中。我将包名改为了 test,但测试代码无法访问根目录(main 包)中的代码。

有没有办法像相对路径“向上跳一级”(../.)那样进行导入?因为我无法让它正常工作。

我花了几个小时创建了一个 go.mod 文件。我是否需要 go.mod 文件以及它所隐含的一切,比如 go mod tidy、带有包名的 requires 等等。

将测试代码与主代码分离的最佳/最简单方法是什么?

我必须说,我觉得模块结构非常令人困惑。

请帮帮我。


更多关于将测试移至子文件夹并导入main包的Golang实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

一个包的测试文件与该包位于同一文件夹中。这是Go语言中的工作方式。

更多关于将测试移至子文件夹并导入main包的Golang实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的。谢谢。那我就不担心了。

我想正确地处理它,现在我知道正确的方式是什么了 😊

此致

Stuart

除了 @NobbZ 的建议,请注意 main 包不能被其他包导入。

如果你想保持根目录中没有 _test.go 文件,可以考虑将所有包含测试的代码从主包中提取出来,放到一个库包中。

这样,你的 main 包将只包含一些启动代码和粘合代码,这些代码本身也不适合进行单元测试。

感谢您的建议,但我注意到测试文件中的任何声明在所有文件中都变得可见。

例如,一个测试方法调用一个“测试”工具方法,以避免在测试代码中重复编写。

我犯了一个错误,在测试文件中创建了一个 close(t *testing.T, name string) 方法。这导致我在使用 close(c) 关闭通道时出现了错误。当时有点奇怪,因为 VSCode 高亮了错误,但最终还是编译了。

我花了一些时间才解决这个问题,因为代码编译通过了,但运行时却出错了!

我现在已经掌握了它的规律,但我发现这可能会给代码引入错误。有没有更好的方法呢?

将测试文件移动到子目录后,确实无法直接导入 main 包。这是因为 Go 的模块系统不允许从外部导入 main 包。以下是解决方案:

方案一:重构代码结构(推荐)

将可测试的代码从 main 包中分离出来:

// 根目录/main.go
package main

import (
    "fmt"
    "yourmodule/internal" // 假设模块名为 yourmodule
)

func main() {
    result := internal.DoSomething()
    fmt.Println(result)
}
// internal/service.go
package internal

func DoSomething() string {
    return "Hello from internal package"
}
// test/service_test.go
package test

import (
    "testing"
    "yourmodule/internal"
)

func TestDoSomething(t *testing.T) {
    result := internal.DoSomething()
    if result != "Hello from internal package" {
        t.Errorf("Expected 'Hello from internal package', got %s", result)
    }
}

方案二:使用 go test-coverpkg 参数

保持测试在子目录,但通过构建标签或特定测试命令:

# 从根目录运行测试
go test ./test -coverpkg=./...

方案三:使用 _test 包模式

test 目录中,使用 package main_test 并确保有 go.mod 文件:

// test/main_test.go
package main_test

import (
    "testing"
    _ "yourmodule" // 导入主模块
)

// 测试导出的函数

必需的 go.mod 配置

是的,你需要 go.mod 文件。在根目录创建:

go mod init yourmodule
// go.mod
module yourmodule

go 1.21

对于测试子目录,如果它需要独立的模块(不推荐),可以创建:

cd test
go mod init yourmodule/test
// test/go.mod
module yourmodule/test

go 1.21

replace yourmodule => ../

require yourmodule v0.0.0

最佳实践

最简单的解决方案是:

  1. 保持测试文件与源代码在同一目录
  2. 或将可测试代码移到独立的包中
  3. 使用 internal 目录存放不希望外部导入的代码
项目结构:
├── go.mod
├── main.go
├── internal/
│   └── service.go
└── internal/
    └── service_test.go  # 测试文件与源码同目录

运行测试:

go test ./...

这种结构既保持了代码组织性,又符合 Go 的测试惯例。

回到顶部