【问题标题】:Is it possible to call a test Func from another file to start the testing是否可以从另一个文件调用测试 Func 来开始测试
【发布时间】:2019-11-27 18:36:22
【问题描述】:

是否可以从非测试 go 文件中调用测试函数来开始执行测试?

例如,我有一个测试功能:

package API

import "testing"

func TestAPI(t *testing.T) { 
...
}

我需要从非测试 go 文件中调用它。

package main

import "../API"

API.TestAPI()

我可以这样做吗?

【问题讨论】:

标签: go


【解决方案1】:

Go 中有一些很棒的测试模式。不幸的是,您尝试测试的方式行不通。

您的单元测试应该使用命令go test <pkg 运行。永远不要从代码本身中调用测试。

Go 中通常有两种主要的单元测试形式——黑盒单元测试和白盒单元测试。

白盒测试:从内部测试未导出函数 自己打包。

黑盒测试:从外部测试导出的函数 包,模拟其他包将如何与之交互。

如果我有一个包,example,我想测试它。有一个简单的 exported 函数,它对提供的数字列表求和。 Sum 函数还使用了一个未导出实用程序函数。

example.go

package example

func Sum(nums ...int) int {
    sum := 0
    for _, num := range nums {
        sum = add(sum, num)
    }
    return sum
}

func add(a, b int) int {
    return a + b
}

example_test.go:黑盒测试

请注意,我正在测试 example 包,但测试位于 example_test 包中。添加_test 可以让Go 编译器满意,并让它知道这是example 的测试包。在这里,我们只能访问导出的变量和函数,以便我们测试外部包在导入和使用我们的example 包时会遇到的行为。

package example_test

import (
    "testing"

    "example"
)

func TestSum(t *testing.T) {
    tests := []struct {
        nums []int
        sum  int
    }{
        {nums: []int{1, 2, 3}, sum: 6},
        {nums: []int{2, 3, 4}, sum: 9},
    }

    for _, test := range tests {
        s := example.Sum(test.nums...)
        if s != test.sum {
            t.FailNow()
        }
    }
}

example_internal_test.go:白盒测试

请注意,我正在测试example 包,并且该测试也位于example 包中。这允许单元测试访问未导出的变量和函数。

package example

import "testing"

func TestAdd(t *testing.T) {
    tests := []struct {
        a   int
        b   int
        sum int
    }{
        {a: 1, b: 2, sum: 3},
        {a: 3, b: 4, sum: 7},
    }

    for _, test := range tests {
        s := add(test.a, test.b)
        if s != test.sum {
            t.FailNow()
        }
    }
}

我希望这能让您更好地了解 Go 的测试框架是如何设置和使用的。为简单起见,我没有在示例中使用任何外部库,尽管github.com/stretchr/testify 是一个非常流行且功能强大的包来帮助进行单元测试。

【讨论】:

    【解决方案2】:

    您正在尝试可能的,但不建议这样做,因为它取决于 Go 的 testing 库的内部细节,这些细节不在 Go 1 兼容保证范围内,这意味着您很可能必须为每个 Go 版本调整这种方法。

    您应该很少(如果有的话)尝试此操作。我这样做过一次,我希望能够作为正常测试运行的一套 API 集成测试,也可以从 CLI 工具运行,以测试 API 的第三方实现。现在我已经做到了,我不确定我是否会再做一次。我可能会寻找不同的方法。

    但如果你不能被劝阻,那么你需要做的是:

    1. 您的测试必须在名为 *_test.go 的文件中定义。此类文件被排除在正常编译之外。

    2. 对于您的正常测试用例,您必须触发测试从名为 *_test.go 的文件运行。

    3. 您必须手动编排非测试用例中的测试。

    详细说明:

    1. 将测试放在非测试文件中。 testing 包只是一个标准包,因此可以轻松地包含在您需要的任何地方:

      foo.go

      package foo
      
      import "testing"
      
      func SomethingTest(t *testing.T) {
        // your tests
      }
      
    2. *_test.go 文件运行测试:

      foo_test.go

      func TestSomething(t *testing.T) {
          SomethingTest(t)
      }
      
    3. 并从您的非测试文件中运行测试。在这里,您处于危险的境地,因为它需要使用不受 Go 1 兼容性保证保护的方法。您需要调用 testing.MainStart 方法,并使用手动制作的测试列表。

      这也需要实现你自己的testing.testDeps 版本,它是私有的,但是一个接口,很容易实现。你可以看到我的 Go 1.9 实现here

      tests := []testing.InternalTest{
          {
              Name: "TestSomething",
              f:     SomethingTest,
          },
      }
      m := testing.MainStart(MyTestDeps, tests, nil, nil)
      os.Exit(m.Run())
      

    这是一个非常简化的示例,并不完整。但我希望它能让你走上正确的道路。

    【讨论】:

      猜你喜欢
      • 2014-04-18
      • 2011-08-22
      • 1970-01-01
      • 2019-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多