如何将Go模块导入到/*_test.go文件中?

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

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.

huangapple
  • 本文由 发表于 2021年8月27日 07:28:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/68946395.html
匿名

发表评论

匿名网友

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

确定