Golang测试在子目录中

huangapple go评论88阅读模式
英文:

Golang tests in sub-directory

问题

你好!你想在Go中创建一个包,并将测试和示例作为子目录放在包中,以保持工作区的整洁。这是可能的,你可以按照以下步骤进行操作:

  1. 在你的工作区中创建一个新的目录,用于存放你的包和测试代码。例如,你可以创建一个名为"mypackage"的目录。

  2. 在"mypackage"目录中创建一个子目录,用于存放测试代码。例如,你可以创建一个名为"tests"的目录。

  3. 在"mypackage"目录中创建你的Go包文件。例如,你可以创建一个名为"mypackage.go"的文件,并在其中定义你的包。

  4. 在"tests"目录中创建你的测试文件。例如,你可以创建一个名为"mypackage_test.go"的文件,并在其中编写你的测试代码。

  5. 在你的测试文件中导入你的包,并编写相应的测试函数。

  6. 运行你的测试代码,确保测试通过。

这样,你就可以将测试代码和示例代码作为子目录放在你的包中,以保持工作区的整洁。

至于将测试代码放在与其他代码相同的位置是否更好,这主要是一种约定俗成的做法。将测试代码与其他代码放在一起可以更方便地管理和维护代码,同时也可以更容易地进行版本控制和构建。但如果你觉得将测试代码作为子目录放在包中更符合你的需求,你完全可以按照上述步骤进行操作。

英文:

I want to create a package in Go with tests and examples for the package as subdirectories to keep the workspace cleaner. Is this possible and if so how?

All the documentation always puts the testing code in the same place as the other code, is this better in some way or just convention?

答案1

得分: 372

请注意,你可以运行go test命令进行“递归”测试:你需要列出所有要测试的包

如果你在Go项目的根目录中,输入以下命令:

go test ./...

./...的表示法在“包列表描述”的“go命令”部分中有描述:

如果导入路径包含一个或多个“...”通配符,则它是一个模式,每个通配符都可以匹配任何字符串,包括空字符串和包含斜杠的字符串。

这样的模式会扩展为在GOPATH树中找到的与模式匹配的所有包目录。

作为一个特例,x/...也会匹配x及其子目录。例如,net/...会扩展为net及其子目录中的包。

如果你将_test.go文件放在子文件夹中,go test ./...命令将能够找到它们。
但是:

  • 你需要在你的测试中使用的导出变量和函数(用于测试的)前缀为你的包的名称,以便测试文件能够访问包的导出内容。
  • 你将无法访问非导出内容。

话虽如此,我仍然更喜欢将_test.go文件放在主源文件旁边:这样更容易找到。

2022年:关于代码覆盖率:

go test -coverpkg=./... ./...

参见如何绘制Go测试覆盖率随时间变化的图表,来自Frédéric G. MARANDfgmarand/gocoverstats,用于生成Go项目的CI集成的聚合覆盖率统计信息。

此外,go-cover-treemap.io很有趣。

2023年3月:正如在“为Go集成测试提供代码覆盖率”中所述:

在1.20版本中,Go的覆盖工具不再局限于包测试,而是支持从更大的集成测试中收集配置文件。

示例:

$ go build -cover -o myprogram.exe myprogram.go
$ mkdir somedata
$ GOCOVERDIR=somedata ./myprogram.exe
I say "Hello, world." and "see ya"
$ ls somedata
covcounters.c6de772f99010ef5925877a7b05db4cc.2424989.1670252383678349347
covmeta.c6de772f99010ef5925877a7b05db4cc

参见Go 1.20 Cover

正如kbolino评论中指出的:

你可以将测试放在一个单独的包中,而无需将其放在单独的目录中。
用于包foo的测试文件可以在foo_test包中,仍然位于同一个目录中,同时无法访问包foo的未导出(私有)成员。

英文:

Note that you can run go test "recursively": you need to list all the packages you want to test.

If you are in the root folder of your Go project, type:

go test ./...

The './...' notation is described in the section "Description of package lists" of the "command go":

> An import path is a pattern if it includes one or more "..." wildcards, each of which can match any string, including the empty string and strings containing slashes.
>
> Such a pattern expands to all package directories found in the GOPATH trees with names matching the patterns.
>
> As a special case, x/... matches x as well as x's subdirectories.
For example, net/... expands to net and packages in its subdirectories.


If you keep your _test.go files in a subfolder, the 'go test ./...' command will be able to pick them up.
But:

  • you will need to prefix your exported variables and functions (used in your tests) with the name of your package, in order for the test file to be able to access the package exported content.
  • you wouldn't access non-exported content.

That being said, I would still prefer to keep the _test.go file right beside the main source file: it is easier to find.


2022: For code coverage:

go test -coverpkg=./... ./...

See "How to plot Go test coverage over time" from Frédéric G. MARAND and fgmarand/gocoverstats to produce aggregate coverage statistics for CI integration of Go projects.

Also, go-cover-treemap.io is fun.


March 2023: As documented in "Code coverage for Go integration tests":

> With the 1.20 release, Go’s coverage tooling is no longer limited to package tests, but supports collecting profiles from larger integration tests.

Example:

$ go build -cover -o myprogram.exe myprogram.go
$ mkdir somedata
$ GOCOVERDIR=somedata ./myprogram.exe
I say "Hello, world." and "see ya"
$ ls somedata
covcounters.c6de772f99010ef5925877a7b05db4cc.2424989.1670252383678349347
covmeta.c6de772f99010ef5925877a7b05db4cc

See Go 1.20 Cover.


As noted by kbolino in the comments:

> You can put your tests in a separate package without putting them in a separate directory.
Test files for package foo can be in package foo_test and still be in the same directory, while also not having any access to unexported (private) members of package foo.

答案2

得分: 23

基于VonC的答案进行修改,

这个答案在go1.11版本中有效。尚未在更高版本的go中进行测试。

对于那些喜欢将测试放在子文件夹(比如test)中的人来说,运行

go test ./...

将尝试运行每个文件夹中的测试,即使其中某些文件夹不包含任何测试,因此在非测试文件夹的报告中会有一个?

相反,运行

go test ./.../test

将只针对你的test文件夹,从而得到一个只关注你的测试文件夹的干净报告。

注意

请注意,使用测试子文件夹将阻止覆盖率报告的计算。Go的哲学是将测试文件留在包文件夹中。

英文:

EDITED

Built on VonC's answer,

This answer is valid in go1.11. No yet tested in upper go versions.

For those of you who like to keep their tests in a sub-folder, say test, then running

go test ./...

will attempt to run tests in every folder, even those that do not contain any test, thus having a ? in the subsequent report for non-test folders.

Running

go test ./.../test

instead will target only your test folders, thus having a clean report focused on your tests folders only.

CAUTION

Please be mindful that using test sub-folders will prevent coverage report computation. The phylosophy of go is to leave test files in the package folders.

答案3

得分: 20

将你的测试与代码放在同一个目录中,文件名为file_test.go,其中"file"是你正在测试的源代码文件的名称。这是一种约定,根据我的经验,我发现这是最好的做法。

如果go test工具对你来说还不够自动化,你可以考虑使用**GoConvey**,它有一个Web界面,可以自动更新和运行传统的Go测试,以及基于行为的GoConvey测试(比传统的Go测试更具自我说明性)。

英文:

Put your tests alongside your code in the same directory in a file called file_test.go where "file" is the name of the source code file you're testing. This is convention and I've found it to be best in my own experience.

If the go test tool isn't quite automated enough for you, you might look into GoConvey, which has a web UI that will automatically update and run traditional Go tests as well as GoConvey tests (which are based on behavior, and are more self-documenting than traditional Go tests).

答案4

得分: -7

我通常不进行测试,但你可以将文件分组到目录中,并使用导入语句进行引用。

如果文件在一级目录外,可以使用以下导入语句:
import "./models"

如果文件在一级目录外并且在一级目录内,可以使用以下导入语句:
import "../models"

例如,对于以下文件结构:
./models/todo.go
./test/todo_test.go

如果你想要从todo_test.go中测试todo.go,你需要在todo_test.go中使用以下导入语句:
import "../models"

英文:

I normally don't do test, but you can group your file into directories and use import like

import "./models" if is one level out
import "../models if is one level out and one level in

For example, for:
./models/todo.go
./test/todo_test.go

to test todo.go from todo_test.go,
your import in the todo_test.go will be

import "../models"

huangapple
  • 本文由 发表于 2013年10月6日 00:50:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/19200235.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定