我在解析Go应用程序中的相对文件路径时遇到问题。为此,我决定制作一个程序包,为不同的配置文件提供统一的界面。 conf软件包包含相关的数据文件,因此基本上是文件树:

1
2
3
4
5
6
7
app/conf
    + config.go
    + config.json
    + ...
app/code
    + code.go
    + code_test.go

问题是,当app/code/code_test.go中定义的测试调用app/conf包中的一个函数,而该包又试图打开app/conf/config.json时,由于工作目录位于app/code上,因此相对路径被弄乱了。

  • 我看过其他提到path/filepath包的SO答案,尤其是filepath.Abs函数,用于将相对路径转换为绝对路径。但是,这不能解决我的问题,因为绝对路径将基于错误的工作目录。

  • 一些基于GOPATH的"绝对路径"解决方案可能就足够了,但是我想在构建和导出代码时,GOPATH的意义不大。

  • 简单地将所有配置文件移植到硬编码的Go结构上也是不可行的,因为它们是跨语言使用的。

  • 仅在测试文件中有此问题吗?我问,因为他们不包括在最终版本中。因此,在构建和部署应用程序之后,将没有code_test.go来执行appconf中的功能。
  • @mkopriva对不起,我不清楚,这些函数是从实际的实现文件(在上面的示例中为code.go)调用的,但是这些函数也会从实际的main包中调用,即,不仅在测试中。
  • 然后,您可以指示用户将配置文件安装在已知位置(绝对位置还是相对于二进制位置),由您决定。或者,您可以指示您的用户以cli arg或env var或两者的形式提供配置的位置。
  • ...第三种选择是将配置"嵌入"到最终二进制文件中。 go命令不支持开箱即用,但是有第三方库可以为您执行此操作。
  • 是的,我正在考虑这种解决方案;例如指示用户定义一些环境变量等,但是我想知道是否有更好的常规解决方案对Go来说更"原生"。

依赖源中的配置文件路径不仅是单元测试中的问题,而且在生产中也将是一个问题。通常,代码将执行以下操作:

  • 配置处理程序接受io.Reader,它将从中读取配置。
  • main将打开一个文件(其路径可能是硬编码的,通过命令行传递的,通过env var传递的等),然后将其传递给config处理程序以进行读取。
  • 配置处理程序的单元测试将改为将一个配置(或多个配置,以测试不同的场景)硬编码为类似bytes.Buffer的代码,并将其传递给配置处理程序以进行读取。
  • 除了读取配置文件的代码外,对任何其他内容进行单元测试(因此,使用配置但不对其进行任何操作的任何内容)都将在代码中生成Config结构,而不是从真实或伪造文件中读取它测试线束。例如,myConf := config.Config{SomeProp:"foo", OtherProp: true},然后将其传递给被测函数。
  • 感谢Adrian,很好的回答。我一直在寻找一种将测试动态地基于配置的方法,而不是在测试中针对静态配置值进行显式测试,因为许多配置无论如何都将保持不变。但是我想这背后的动机是便利,而不是其他。
  • 为方便起见,没有理由您不能定义结构文字并在多个测试(甚至跨多个包)中重用它。
  • 一些行为测试依赖于高度个性化的ICC配置文件,该配置文件是配置的一部分,适用于运行测试的系统。因此,这些配置文件不能进行硬编码,以免测试套件变得异常脆弱。因此,尽管我认为我已经找到了一种根据建议的方式对系统部件建模的方法,但我很难理解如何在测试这些组件时避免动态配置。
  • 好的,谢谢您的帮助。这些组件在屏幕上执行图像识别,并且需要一些基本测试,但是这些测试目前还不会成为正确的单元测试。