在golang测试中是否可以得到包结构的当前根作为字符串?

dm7nw8vv  于 2023-04-09  发布在  Go
关注(0)|答案(6)|浏览(130)

我正在为我的单元测试编写一个实用函数,它被多个包中的单元测试使用。这个实用函数必须读取一个特定的文件(总是同一个文件)。这里有三个不起作用的解决方案,以解释我在寻找什么和为什么。
1.硬编码绝对路径。这会失败,因为尝试测试项目的其他用户可能在绝对路径上使用了不同的前缀。
1.从定义实用函数的文件的路径硬编码相对路径。这会失败,因为导入和使用此函数的包不一定与定义实用函数的文件处于文件层次结构的同一级别,并且相对路径是相对于导入程序而不是导入的文件来解释的。
1.从每个调用者相对于调用者的包传递文件的相对路径。这实际上可以工作,但似乎非常冗长,因为现在每个调用者都必须更改以传递一个文件。
我看到了第四种解决方案,我可以在实用程序函数中硬编码一个相对于顶级包的根目录的路径。然而,我还没有找到一种方法在代码中获得根目录,尽管我怀疑有一种方法,因为导入可以从根目录解析。

那么,如何才能获得我想要的根目录呢?

我看过很多Go文档,但到目前为止还没有找到解决方案。我也看过this question,但那里的解决方案相当于上面的#3。

2izufjch

2izufjch1#

你也可以在没有C的情况下使用我的方法:

package mypackage

import (
    "path/filepath"
    "runtime"
    "fmt"
)

var (
    _, b, _, _ = runtime.Caller(0)
    basepath   = filepath.Dir(b)
)

func PrintMyPath() {
    fmt.Println(basepath)
}

https://play.golang.org/p/ifVRIq7Tx0

fxnxkyjh

fxnxkyjh2#

answer by Oleksiy的基础上,您可以在项目中创建一个名为./internal/projectpath/projectpath.go的子包,并粘贴以下内容:

package projectpath

import (
    "path/filepath"
    "runtime"
)

var (
    _, b, _, _ = runtime.Caller(0)

    // Root folder of this project
    Root = filepath.Join(filepath.Dir(b), "../..")
)

然后,您可以在任何其他包中使用projectpath.Root来拥有项目的根文件夹。

jtoj6r0c

jtoj6r0c3#

返回应用程序的根:

import (
    "path"
    "path/filepath"
    "runtime"
)  

func RootDir() string {
    _, b, _, _ := runtime.Caller(0)
    d := path.Join(path.Dir(b))
    return filepath.Dir(d)
}
unguejic

unguejic4#

转到目录:

// from Executable Directory
ex, _ := os.Executable()
fmt.Println("Executable DIR:", filepath.Dir(ex))

// Current working directory
dir, _ := os.Getwd()
fmt.Println("CWD:", dir)

// Relative on runtime DIR:
_, b, _, _ := runtime.Caller(0)
d1 := path.Join(path.Dir(b))
fmt.Println("Relative", d1)
a7qyws3x

a7qyws3x5#

下面是一个测试助手的例子,它可以获取模块(项目)的根路径,而不必将其设置为全局变量,使用go list,以防您需要在运行时生成路径。

func getRelativeRootPath(tb testing.TB) string {
    tb.Helper()

    importPath := runGoList(tb, "list", "-f", "{{.ImportPath}}")
    modulePath := runGoList(tb, "list", "-m", "-f", "{{.Path}}")
    pkgPath := runGoList(tb, "list", "-f", "{{.Dir}}")

    relativePath, err := filepath.Rel(importPath, modulePath)
    if err != nil {
        tb.Fatal(err)
    }
    return filepath.Join(pkgPath, relativePath)
}

func runGoList(tb testing.TB, arg ...string) string {
    tb.Helper()
    cmd := exec.Command("go", arg...)
    output, err := cmd.CombinedOutput()
    if err != nil {
        tb.Fatalf("runGoList: %v: %s", err, string(output))
    }
    return strings.TrimSpace(string(output))
}

这将独立于在测试使用helper的包中运行go test,或者在根级别运行go test
导入路径是引用包的路径,模块路径只包含模块本身的路径,我们在这里使用它作为参考来计算另一个包的嵌套深度,允许我们计算相对路径,例如...../..等。
最后,我们还使用runtime.Caller(0)来获取当前文件的路径,但现在可以在运行时计算项目的根路径。

alen0pnh

alen0pnh6#

是,可以查找包路径:
pathfind.go:

package main

/*
const char* GetMyPathFILE = __FILE__;
*/
import "C"
import "path/filepath"

var basepath = ""

//GetMyPath Returns the absolute directory of this(pathfind.go) file
func GetMyPath() string {
    if basepath == "" {
        g := C.GoString(C.GetMyPathFILE)
        basepath = filepath.Dir(g)
    }
    return basepath
}

你所要做的就是把这个文件复制到你的项目中。记住,这是文件的路径,而不是调用者,所以你必须把函数/文件复制到你需要函数的每个项目中。另外,如果你把这个文件和其他代码放在一个文件中,一定要遵守CGO的导入规则。

相关问题