쿼카러버의 기술 블로그
[golang] Unit Test 마스터하기 (step1. 테스트 전에 미리 설정이 필요할때) (testify suite패키지) 본문
[golang] Unit Test 마스터하기 (step1. 테스트 전에 미리 설정이 필요할때) (testify suite패키지)
quokkalover 2021. 12. 8. 22:18요약
golang으로 단위 테스트(unit test)를 작성할 때, 테스트에 미리 설정이 필요할 때 (예: DB연결 등)사용하는 패키지
1) testify 패키지 간략한 소개
2) Suite 패키지 기본 사용
- 메서드 정의(테스트 케이스 정의)
- Lifecycle정의 (테스트 전후 세팅)
Suite Package
testify 패키지
Golang에는 testify
라는 패키지가 있다.
Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend.
testify는 크게 3가지 기능을 제공한다.
- Easy assertion
- Mock
- Test suite interface and function
위 3가지 기능만 있으면, 대부분의 unit test를 쉽게 구현할 수 있다.
그 중에서도 이번 글에서는 Suite Package에 대해 다루어보도록 하겠다.
Suite패키지의 기본적인 사용방법
메서드 정의 (테스트 케이스 정의)
테스트를 실행하기 위해서는 suite에 대한 메서드를 정의해야 한다.
type TestSuite struct {
suite.Suite
}
func TestRunSuite(t *testing.T) {
suite.Run(t, new(TestSuite))
}
func (s *TestSuite) SetupSuite() {
// setup tests
}
func (s *TestSuite) Test1() {
// test1
}
... Test2, Test3...
위 코드에서 보이는 것처럼,
1) suite.Suite구조체를 embed하는 struct를 생성하고, 해당 struct에 대한 메서드들을 정의하면된다. (struct에 정의된 메서드들이 테스트의 대상이될 메서드들이라고 할 수 있다. )
2) SetupSuite메서드 안에서, 테스트를 실행하기 위해 필요한 세팅들을 세팅
3) suite.Run()메서드를 실행해 Suite에 정의된 메서드들이 차례대로 실행
Lifecycle 정의
먼저 먼저 테스트에 대한 Lifecycle을 정의해야 한다. Lifecycle 메서드란 테스트 실행 전후로 여러 가지 처리를하는 메서드로, Suite패키지에서 제공되는 여러 interface를 활용할 수 있다.
전처리와 후처리를 기준으로 아래와 같은 메서드들을 정의할 수 있다.
- 전처리
SetupSuite
- suite에서 전체 테스트 실행 전에 한번만 실행된다SetupTest
- suite에서 각 테스트 실행 전에 실행된다BeforeTest
- 테스트가 실행하기 전에suiteName, testName
인자를 받아 실행하는 함수이다
- 후처리
AfterTest
- 테스트가 실행후에 suiteName testName 인자를 받아 실행하는 함수이다TearDownTest
- suite에서 각 테스트 실행후에 실행된다TestDownSuite
- suite에서 모든 테스트가 실행된 후에 실행된다
정의된 메서드들이 차례대로 실행되며 이러한 lifecycle에 대해 이해하기 위해 아래와 같이 코드를 작성해볼 수 있겠다. (kenshin579님의 코드를 그대로 참조했다.)
package go_testing
import (
"fmt"
"testing"
"github.com/stretchr/testify/suite"
"gopkg.in/go-playground/assert.v1"
)
//https://brunoscheufler.com/blog/2020-04-12-building-go-test-suites-using-testify
type ExampleTestSuite struct {
suite.Suite
TestValue int
}
//suite에서 전체 테스트 실행 전에 한번만 실행된다
func (ets *ExampleTestSuite) SetupSuite() {
fmt.Println("SetupSuite :: run once")
}
//suite에서 각 테스트 실행 전에 실행된다
func (ets *ExampleTestSuite) SetupTest() {
fmt.Println("SetupTest :: run setup test")
ets.TestValue = 5
}
//테스트가 실행하기 전에 suiteName testName 인자를 받아 실행하는 함수이다
func (ets *ExampleTestSuite) BeforeTest(suiteName, testName string) {
fmt.Printf("BeforeTest :: run before test - suiteName:%s testName: %s\n", suiteName, testName)
}
//TEST ----------------------------------------
func (ets *ExampleTestSuite) TestExample1() {
fmt.Println("TestExample1")
ets.Equal(ets.TestValue, 5)
assert.Equal(ets.T(), ets.TestValue, 5)
}
func (ets *ExampleTestSuite) TestExample2() {
fmt.Println("TestExample2")
}
//TEST ----------------------------------------
//테스트가 실행후에 suiteName testName 인자를 받아 실행하는 함수이다
func (ets *ExampleTestSuite) AfterTest(suiteName, testName string) {
fmt.Printf("AfterTest :: suiteName:%s testName: %s\n", suiteName, testName)
}
//suite에서 각 테스트 실행후에 실행된다
func (ets *ExampleTestSuite) TearDownTest() {
fmt.Println("TearDownTest :: run before after test")
}
//suite에서 모든 테스트가 실행된 후에 실행된다
func (ets *ExampleTestSuite) TearDownSuite() {
fmt.Println("TearDownSuite :: run once")
}
func TestExampleTestSuite(t *testing.T) {
//특정 조건인 경우에 전체 테스트를 실행하지 않을 수 있다
if isSkip() {
t.Skip("skipping")
}
suite.Run(t, new(ExampleTestSuite))
}
func isSkip() bool {
return false
}
그 외 팁
1) t.Skip()을 통해 특정 상황에는 테스트 자체를 실행하지 않도록 할 수 있다.
- 예: db가 connect되지 않으면 테스트를 실행하지 않는다든지 등
func TestExampleTestSuite(t *testing.T) {
//특정 조건인 경우에 전체 테스트를 실행하지 않을 수 있다
if isSkip() {
t.Skip("skipping")
}
suite.Run(t, new(ExampleTestSuite))
}
func isSkip() bool {
return false
}
참고자료
https://blog.advenoh.pe.kr/go/Go-Test-Suite-Lifecycle-메서드/
https://github.com/kenshin579/tutorials-go/blob/master/go-testing/suite_test.go
'[Golang]' 카테고리의 다른 글
[Golang] go가 byte stream을 다루는 방법에 대하여 (io.Reader, io.Writer, Copy, Close, Seeker, Pipe, Buffer 등 개념 뿌시기) (0) | 2022.02.13 |
---|---|
[Golang gin] io.NopCloser란? (ioutil.ReadAll()로 읽은 content를 날리지 않는 법) (io.ReadCloser란) (2) | 2022.02.09 |
[golang] Type assertion과 Type conversion 차이 (0) | 2021.09.24 |
[golang] time.After이란? (memory leak 가능성) (0) | 2021.08.30 |
[golang] Marshal, Unmarshal 차이 (0) | 2021.08.09 |