是否可以从另一个文件调用测试功能以开始测试

时间:2019-11-27 06:27:07

标签: go

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

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

package API

import "testing"

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

我需要从非测试版文件中调用此文件。

package main

import "../API"

API.TestAPI()

我可以这样做吗?

2 个答案:

答案 0 :(得分:0)

Go中有一些很棒的测试模式。不幸的是,您尝试进行测试的方式无法正常工作。

您应该使用命令go test <pkg运行单元测试。绝对不要从代码内部调用测试。

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

  

白盒测试:从内部测试未导出功能   包装本身。

     

黑盒测试:从外部测试已导出功能   包,模拟其他包如何与之交互。

如果我有一个要测试的软件包example。有一个简单的导出功能,可以对提供的数字列表进行汇总。 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是一个非常流行且功能强大的软件包,可以帮助进行单元测试。

答案 1 :(得分:0)

您尝试的可能性是可能的,但不建议使用,因为它取决于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())
    

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