英文:
How to import go modules into /*_test.go files?
问题
如何将我的函数导入到测试文件夹中?我在cmd目录中运行了go mod init
命令,它创建了一个带有module "cmd"
的go.mod文件,但是当我尝试在测试中导入它时,我无法访问函数。我在项目根目录中运行go test ./test
,出现错误:test/services_test.go:4:2: "cmd"不是可导入的包
。
myproject
├── cmd
├── main.go (package main)
├── helper.go (package main)
└── services.go (package main)
├── test
├── helper_test.go (package main)
└── services_test.go (package main)
├── go.mod (module cmd)
└── go.sum
在cmd/services.go中:
package main
func doStuff() {
// TODO
}
在test/services_test.go中:
package main
import (
"cmd"
"testing"
)
func TestdoStuff(*testing.T) {
cmd.doStuff()
}
英文:
How do I import my functions into my testing folder? I ran go mod init
in the cmd directory and it created a go.mod file with module "cmd"
, however when I try to import it in testing, I'm unable to access to functions. I am running go test ./test
in root project directory and error is: test/services_test.go:4:2: "cmd" is not an importable package;
myproject
├── cmd
├── main.go (package main)
├── helper.go (package main)
└── services.go (package main)
├── test
├── helper_test.go (package_main)
└── services_test.go (package main)
├── go.mod (module cmd)
└── go.sum
In cmd/services.go
package main
func doStuff() {
// TODO
}
In test/services_test.go
package main
import {
"cmd"
"testing"
}
func TestdoStuff (*testing.T) {
cmd.doStuff()
}
答案1
得分: 3
给定包的测试应该在该包中,这样它们可以访问该包中未导出的变量、字段和方法,而且不需要导入该包。不要将它们放在单独的test
目录中。
如果需要测试这个包,可以导入其他包,但是你将无法访问其他包中未导出的内容。在这方面,测试与任何其他文件没有区别。
英文:
The tests for a given package should be in that package so that they can see unexported variables, fields, and methods of that package, and don't need to import that package at all. Don't put them in a separate test
directory.
You can import other packages if necessary to test this one, but you won't be able to see unexported stuff from other packages. Tests are no different from any other file in that regard.
答案2
得分: 1
如其他答案中所指出的,测试文件必须与被测试的文件位于同一个目录中。
你可以查看教程创建 Go 模块,然后再查看添加测试。
以下是这些教程中的示例:
myproject
├── greetings
├── greetings.go (greetings 包)
├── greetings_test.go (greetings 包)
├── go.mod
└── go.sum
greetings.go 文件内容如下:
package greetings
import "fmt"
// Hello 返回给定名字的问候语。
func Hello(name string) string {
// 返回一个包含名字的问候语。
message := fmt.Sprintf("你好,%v。欢迎!", name)
return message
}
greetings_test.go 文件包含两个测试:
package greetings
import (
"testing"
"regexp"
)
// TestHelloName 使用一个名字调用 greetings.Hello,检查返回值是否有效。
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b`+name+`\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
// TestHelloEmpty 使用一个空字符串调用 greetings.Hello,检查是否返回错误。
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}
英文:
As pointed out in others answers, test files have to be in the same directory as the tested file.
You can check out the tutorial Create a Go Module and then Add a Test.
Here are the examples from these tutorials:
myproject
├── greetings
├── greetings.go (package greetings)
├── greetings_test.go (package greetings)
├── go.mod
└── go.sum
The greetings.go file:
package greetings
import "fmt"
// Hello returns a greeting for the named person.
func Hello(name string) string {
// Return a greeting that embeds the name in a message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
And greetings_test.go file with two tests:
package greetings
import (
"testing"
"regexp"
)
// TestHelloName calls greetings.Hello with a name, checking
// for a valid return value.
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b`+name+`\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
// TestHelloEmpty calls greetings.Hello with an empty string,
// checking for an error.
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}
答案3
得分: 0
package main
的编译产物是一个二进制文件,这个二进制文件是包的下游用户与之交互的对象。因此,验证package main
行为的测试应该针对二进制文件本身进行,而不是针对用于实现该二进制文件的各个函数进行测试。
你可以通过使用os/exec
包来运行go build cmd
(可能使用-o
标志将二进制文件输出到测试的临时目录),然后使用os/exec
包来执行生成的二进制文件来编写这样的测试。
或者,你可以使用第三方测试包,例如github.com/rogpeppe/testscript
来编写更简洁的脚本驱动测试。
另外,你还可以将任何辅助函数提取到internal
包中,并测试这些包的导出函数。
无论采用哪种方法,给定包的测试仍然应该位于与该包相同的目录中。这样,当用户运行go test cmd
时,他们可以确信cmd
实际上是可用的——如果测试位于不同的包中,他们就不会明显知道要运行go test test
来测试cmd
包。
英文:
The compiled artifact for a package main
is a binary, and that binary is what downstream users of the package will interact with. So a test that verifies the behavior of package main
should test against the binary itself, not the individual functions used to implement that binary.
You can write such a test by using the os/exec
package to run go build cmd
(perhaps using the -o
flag to output the binary to the test's temporary directory), then using the os/exec
package to execute the resulting binary.
Or, use a third-party testing package such as github.com/rogpeppe/testscript
to write more concise script-driven tests.
Or, factor out any helper-functions into internal
packages and test the exported functions of those packages.
With any of those approaches, the tests for a given package still belong in the same directory as that package. That way, when users run go test cmd
they can be confident that cmd
actually works — if the test is in a different package, they won't obviously know to run go test test
in order to test the cmd
package.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论