go中的每个测试的测试设置和拆卸

时间:2017-02-18 01:33:01

标签: unit-testing go

我正在使用go“testing”包。像下面那样运行我的测试。

func TestMain(m *testing.M) {

   ...
   // Setup
   os.Exit(m.Run())
   // Teardown
}

这将在运行任何测试之前运行设置,并在所有测试完成后进行拆卸。我确实需要这个,因为设置设置了DB。但是,我还需要找到一种方法来运行每次测试设置/拆卸。对于我正在运行的单元测试,我想在每次测试之前清除数据库,这样就不会出现导致意外行为的数据库内容问题。

4 个答案:

答案 0 :(得分:17)

如文章" Go unit test setup and teardown"从Kare Nuorteva开始,你可以使用一个设置函数,它会让你推迟一个拆解功能。

请参阅this gist

func setupSubTest(t *testing.T) func(t *testing.T) {
    t.Log("setup sub test")
    return func(t *testing.T) {
        t.Log("teardown sub test")
    }
}

设置功能负责定义和返回拆卸功能。

对于每个测试,例如在表驱动的测试场景中:

for _, tc := range cases {
    t.Run(tc.name, func(t *testing.T) {
        teardownSubTest := setupSubTest(t)
        defer teardownSubTest(t)

        result := Sum(tc.a, tc.b)
        if result != tc.expected {
            t.Fatalf("expected sum %v, but got %v", tc.expected, result)
        }
    })
}

答案 1 :(得分:1)

如果表驱动测试模式适合您,则应坚持使用它。如果您需要更通用,更灵活的工具,请随时尝试https://github.com/houqp/gtest

这是一个简单的例子:

import (
  "strings"
  "testing"
  "github.com/houqp/gtest"
)

type SampleTests struct{}

// Setup and Teardown are invoked per test group run
func (s *SampleTests) Setup(t *testing.T)      {}
func (s *SampleTests) Teardown(t *testing.T)   {}
// BeforeEach and AfterEach are invoked per test run
func (s *SampleTests) BeforeEach(t *testing.T) {}
func (s *SampleTests) AfterEach(t *testing.T)  {}

func (s *SampleTests) SubTestCompare(t *testing.T) {
  if 1 != 1 {
    t.FailNow()
  }
}

func (s *SampleTests) SubTestCheckPrefix(t *testing.T) {
  if !strings.HasPrefix("abc", "ab") {
    t.FailNow()
  }
}

func TestSampleTests(t *testing.T) {
  gtest.RunSubTests(t, &SampleTests{})
}

答案 2 :(得分:0)

您可以考虑使用函数表subTestSetup,subTest和subTestTeardown传递结构中的db连接/其他公共项(subTestSetup可以返回此结构)。你可以重用一些/部分设置和放大器。同时拆除不同的功能&随着测试要求的增长,保持这种模块化。在调用subTest之前调用deTallTestTeardown(),以确保即使subTest存在任何问题也可以执行拆除代码。

答案 3 :(得分:0)

⚠️注意:这不是经过全面测试的解决方案;在临时测试场景中似乎效果很好。

在一个简单的情况下,我使用了自己的t.Run()实现,该实现在完成子测试后进行清理:

func Run(t *testing.T, name string, f func(*testing.T)) bool {
    result := t.Run(name, f)
    // Do the cleanup.
    return result
}

在我的测试中:

func TestSomethingWorks(t *testing.T) {
    Run(t, "scenario 1", func(t *testing.T) {
        // ...
    })

    Run(t, "scenario 2", func(t *testing.T) {
        // ...
    })
}