이야기박스
Go Test 간단하게 리뷰 본문
Go는 자체적인 내장 testing 패키지를 가지고 있습니다. 덕분에 쉽고 빠르게 테스트 코드 작성이 가능한데요. 제목처럼 한번 가볍게 알아보도록 하겠습니다.
개요
Go의 테스트 파일은 "_test" 접미사를 달고 있으면 됩니다. 즉, "*_test.go" 형식의 이름을 가지면 되는 거죠.
Go의 테스트 패키지는 크게 Example, Benchmark, Test 세 가지 기능이 있습니다. Go에서는 이 기능들을 함수 이름에 접두사로 사용하는 것을 권하고 있습니다. 예를 들어 함수의 이름이 다음과 같아지는 거죠.
Example***, Benchmark***, Test***
테스트 실행은 다음과 같은 커맨드로 진행할 수 있습니다.
# 전체 테스트 코드 실행
go test -v ./story
# 특정 테스트 함수 실행
go test -v ./story -run "{{regex}}"
그리고 다양한 테스트 옵션을 제공하고 있습니다. 각 옵션은 아래 커맨드를 통하여 자세하게 확인할 수 있습니다.
go help testflag
Example
func Example***()
예제 코드를 실행해보고 싶을 때 적절한 함수입니다.
"Output"에 대한 코멘트가 들어가야 원하는 결과를 확인해 볼 수 있습니다.
/**
go test -v ./story -run ^ExampleStory$
*/
func ExampleStory() {
fmt.Println("story.parks")
// Output: story.parks
}
실행 결과
$ go test -v ./story -run ^ExampleStory$
=== RUN ExampleStory
--- PASS: ExampleStory (0.00s)
PASS
ok _/Users/oringnam/Documents/git/story/go-test/story 0.669s
Benchmark
func Benchmark***(b *testing.B)
내가 작성한 함수의 성능이 어떤지 알고 싶을 때, 사용하는 기능입니다. 주로 반복문을 통하여 많이 사용하는 것 같습니다.
/**
go test -v ./story -run ^BenchmarkRandInt$ -bench=. -benchmem -benchtime=5s
*/
func BenchmarkRandInt(b *testing.B) {
for i := 0; i < b.N; i++ {
rand.Int()
}
}
"-benchmem" 옵션은 메모리에 대한 정보도 함께 확인할 때 사용되고, "-benchtime"은 벤치마크를 실행할 시간을 작성합니다.
실행 결과
$ go test -v ./story -run ^BenchmarkRandInt$ -bench=. -benchmem -benchtime=5s
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
BenchmarkRandInt
BenchmarkRandInt-16 443546013 13.67 ns/op 0 B/op 0 allocs/op
PASS
ok _/Users/oringnam/Documents/git/story/go-test/story 7.691s
Test
func Test***(t *testing.T)
우리가 생각하는 가장 일반적인 테스트 코드 같습니다.
"Test***" 형태로 시작한 함수는 반환 값을 가지지 않습니다.
/**
go test -v ./story -run ^TestSimpleTest$
*/
func TestSimpleTest(t *testing.T) {
story := "parks"
if story != "parks" {
t.Error("Story needs, ", story)
}
t.Log("Story has", story)
}
이런 식으로 *testing.T 값에는 로그를 출력할 수 있는 기능이 있고 이는 아래와 같이 나오게 됩니다.
실행 결과
$ go test -v ./story -run ^TestSimpleTest$
=== RUN TestSimpleTest
story_test.go:36: Story has parks
--- PASS: TestSimpleTest (0.00s)
PASS
ok _/Users/oringnam/Documents/git/story/go-test/story 0.424s
기타
환경 변수
환경 변수를 받아서 테스트하고 싶은 경우는 어떻게 할까요? 별반 다를 게 없습니다. os 패키지를 이용하고 실행 시 환경변수를 앞에 명시해주면 됩니다.
/**
go test -v ./story -run ^TestEnv$
*/
func TestEnv(t *testing.T) {
firstName := os.Getenv("FIRST")
secondName := os.Getenv("SECOND")
if firstName == "" {
firstName = "boxx"
}
if secondName == "" {
secondName = "Sstory"
}
t.Log("first name is", firstName, ", second name is", secondName)
}
$ FIRST=story SECOND=parks go test -v ./story -run ^TestEnv$
=== RUN TestEnv
story_test.go:53: first name is story , second name is parks
--- PASS: TestEnv (0.00s)
PASS
ok _/Users/oringnam/Documents/git/story/go-test/story 0.254s
중복 기능 분리
아무리 테스트 코드라도 중복되는 함수는 밖으로 빼주는 게 좋죠. 테스팅 패키지에서 이용되는 포인터 오브젝트를 넘겨주며 코드를 분리할 수 있습니다.
/**
go test -v ./story -run ^TestDuplication$
*/
func duplicatedCode(t *testing.T) int {
return rand.Int()
}
func TestDuplication(t *testing.T) {
t.Log("Pass my testing.T pointer")
retVal := duplicatedCode(t)
t.Log("Return Value is ", retVal)
}
$ go test -v ./story -run ^TestDuplication$
=== RUN TestDuplication
story_test.go:64: Pass my testing.T pointer
story_test.go:67: Return Value is 5577006791947779410
--- PASS: TestDuplication (0.00s)
PASS
ok _/Users/oringnam/Documents/git/story/go-test/story 0.439s
Main
테스트 함수에도 메인 함수가 존재합니다. 위에서는 각 테스트 코드별로 실행 명령어를 주석으로 달아두었는데, 이들을 코드화하여 일괄 실행하고 싶은 경우 사용할 수 있습니다.
/**
go test -v ./story
*/
func TestMain(m *testing.M) {
fmt.Println("## TestMain Start")
os.Setenv("FIRST", "story2")
os.Setenv("SECOND", "parks3")
exitCode := m.Run()
fmt.Println("## TestMain End")
os.Exit(exitCode)
}
주로 아래와 같이 모든 테스트 별로 공통된 작업을 먼저 실행해주고 싶을 때, 많이들 사용하는 것 같습니다.
/**
go test -v ./story
*/
func TestMain(m *testing.M) {
fmt.Println("## TestMain Start")
testInit()
exitCode := m.Run()
fmt.Println("## TestMain End")
os.Exit(exitCode)
}
func testInit() {
os.Setenv("FIRST", "story2")
os.Setenv("SECOND", "parks3")
fmt.Println("## OS ENV SETTING")
}
후기
앞으로는 종종 go에 대한 포스팅도 올리도록 하겠습니다. ㅎㅎ
'Programming Language' 카테고리의 다른 글
심심하여 시작한, Mac에서 Flutter 설치 및 실행 (0) | 2023.06.10 |
---|---|
Go. 왜 빈 struct{}를 context.Value()의 키로 사용할까? (0) | 2022.05.19 |
Go. gRPC 사용해보기 (0) | 2022.05.11 |