IT TIP

Go에서 테스트 패키지를 사용하여 테스트 설정을 수행하려면 어떻게해야합니까?

itqueen 2020. 10. 15. 22:07
반응형

Go에서 테스트 패키지를 사용하여 테스트 설정을 수행하려면 어떻게해야합니까?


테스트 패키지를 사용할 때 모든 테스트의 단계를 설정하는 전체 테스트 설정 처리를 어떻게 할 수 있습니까?

Nunit의 예로서 [SetUp]속성이 있습니다.

[TestFixture]
public class SuccessTests
{
  [SetUp] public void Init()
  { /* Load test data */ }
}

Go 1.4부터 설정 / 해체를 구현할 수 있습니다 (각 테스트 전후에 함수를 복사 할 필요 없음). 설명서는 여기 기본 섹션 요약되어 있습니다 .

TestMain은 메인 고 루틴에서 실행되며 m.Run 호출과 관련하여 필요한 모든 설정 및 해체를 수행 할 수 있습니다. 그런 다음 m.Run의 결과로 os.Exit를 호출해야합니다.

테스트에 함수가 포함되어 있으면 테스트 func TestMain(m *testing.M)를 실행하는 대신이 함수가 호출 된다는 것을 알아내는 데 시간이 좀 걸렸습니다 . 이 함수에서 테스트 실행 방법을 정의 할 수 있습니다. 예를 들어 전역 설정 및 해체를 구현할 수 있습니다.

func TestMain(m *testing.M) {
    setup()
    code := m.Run() 
    shutdown()
    os.Exit(code)
}

여기에서 몇 가지 다른 예 를 찾을 수 있습니다 .

최신 릴리스에서 Go의 테스트 프레임 워크에 추가 된 TestMain 기능은 여러 테스트 사용 사례를위한 간단한 솔루션입니다. TestMain은 설정 및 종료를 수행하고, 테스트 환경을 제어하고, 자식 프로세스에서 다른 코드를 실행하거나, 테스트 코드에서 유출 된 리소스를 확인하기위한 전역 후크를 제공합니다. 대부분의 패키지에는 TestMain이 필요하지 않지만 필요할 때 추가 할 수 있습니다.


이것은 파일에 init()함수를 넣어서 얻을 수 있습니다 _test.go. 이것은 init()함수 전에 실행 됩니다.

// package_test.go
package main

func init() {
     /* load test data */
}

_test.init ()는 패키지 init () 함수보다 먼저 호출됩니다.


단위 테스트에 대한 간단한 함수가 주어지면 :

package math

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

분해 기능을 반환하는 설정 기능으로 테스트 할 수 있습니다. 그리고 setup ()을 호출 한 후 teardown ()을 지연 호출 할 수 있습니다.

package math

import "testing"

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

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

func TestAddition(t *testing.T) {
    cases := []struct {
        name     string
        a        int
        b        int
        expected int
    }{
        {"add", 2, 2, 4},
        {"minus", 0, -2, -2},
        {"zero", 0, 0, 0},
    }

    teardownTestCase := setupTestCase(t)
    defer teardownTestCase(t)

    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)
            }
        })
    }
}

Go 테스트 도구는 셸 콘솔에 로깅 문을보고합니다.

% go test -v
=== RUN   TestAddition
=== RUN   TestAddition/add
=== RUN   TestAddition/minus
=== RUN   TestAddition/zero
--- PASS: TestAddition (0.00s)
    math_test.go:6: setup test case
    --- PASS: TestAddition/add (0.00s)
        math_test.go:13: setup sub test
        math_test.go:15: teardown sub test
    --- PASS: TestAddition/minus (0.00s)
        math_test.go:13: setup sub test
        math_test.go:15: teardown sub test
    --- PASS: TestAddition/zero (0.00s)
        math_test.go:13: setup sub test
        math_test.go:15: teardown sub test
    math_test.go:8: teardown test case
PASS
ok      github.com/kare/go-unit-test-setup-teardown 0.010s
% 

이 접근 방식으로 설정 / 해체에 몇 가지 추가 매개 변수를 전달할 수 있습니다.


일반적으로 이동중인 테스트는 다른 언어와 동일한 스타일로 작성되지 않습니다. 종종 비교적 적은 수의 테스트 함수가 있지만 각각에는 테이블 기반 테스트 사례 집합이 포함됩니다. Go 팀 중 한 사람이 작성한이 기사를 참조하십시오 .

With a table-driven test, you simply put any setup code before the loop that executes the individual test-cases specified in the table, and put any cleanup code afterwards.

If you still have shared setup code between test functions, you can extract the shared setup code into a function, and use a sync.Once if it's important that it's executed exactly once (or as another answer suggests, use init(), but this has the disadvantage that the setup will be done even if the test cases aren't run (perhaps because you've limited the test cases by using go test -run <regexp>.)

I'd say if you think you need shared setup between different tests that gets executed exactly once you should have a think if you really need it, and if a table-driven test wouldn't be better.


The Go testing framework doesn't have anything equivalent to NUnit's SetUp attribute (marking a function to be called before each test in the suite). There are a few options though:

  1. Simply call your SetUp function from each test where it is needed.

  2. Use an extension to Go's testing framework that implements xUnit paradigms and concepts. Three strong options come to mind:

Each of these libraries encourage you to organize your tests into suites/fixtures similar to other xUnit frameworks, and will call the setup methods on the suite/fixture type before each of the Test* methods.

참고URL : https://stackoverflow.com/questions/23729790/how-can-i-do-test-setup-using-the-testing-package-in-go

반응형