Go에서 Unit test 하기
개요
Unit test는 코드에서 특정 모듈이 정상적으로 동작하는 것을 확인하기 위해 사용된다. 이 때 Unit은 함수가 될 수도 있고 Object가 될 수 도 있고 여러 개의 object로 이루어진 componenet 또한 될 수 있다. 우선 작은 함수 단위에서 테스트를 진행한 후 더 큰 단위의 테스트를 진행하면서 완성된 프로그램을 만들게 된다. (물론 반대로도 가능하다)
Unit test -> Component test -> System test
테스트 한다는 것은 unit이 프로그래머가 의도한 대로 작동하는지 테스트하는 것을 의미한다. 이렇게 Unit test를 사용하면 다음과 같은 이점을 얻을 수 있다. Unit test를 작성하게 되면 자동으로 코드를 검증할 수 있기 때문에 생산성을 향상시킬 수 있고, 프로그래머의 요구에 따라 Unit test가 작성되기에 문서화하는데 도움이 되는 등 여러 장점을 가지게 된다.
Unit test는 활용하면 얻을 수 있는 여러 장점이 생산성 향성을 불러오기 떄문에 다양한 언어들에서 unit test를 위한 여러 툴들을 지원한다. Go 또한 그 언어들 중 하나이다. Go는 자체적으로 test라는 기능을 제공하여 쉽게 unit test를 할 수 있고 여러가지 test를 위한 라이브러리를 제공한다.
테스트할 예제 코드
우선 테스트를 하기 위한 함수를 만들어 보자. 간단하게 덧셈과 뺄셈을 하는 함수를 만들었다. 이해를 위한 코드로 함수 내용은 변경해도 상관없다.
// mymath.go
package main
func myadd(a int, b int) int {
return a + b
}
func mysub(a int, b int) int {
return a - b
}
테스트 코드
이제 테스트 하는 코드를 작성해보자. 주의할 점은 go test
를 실행하게 되면 _test.go로 끝나는 파일만 테스트하기 때문에 테스트할 파일은 반드시 이름_test.go로 명명해야 한다.
// mytest_test.go
package main
import (
"testing"
)
func TestTestName(t *testing.T) {
if myadd(1, 3) != 5 {
t.Errorf("Test Failed")
}
}
go에서는 testing라는 테스트를 위한 standard library를 제공한다. 자주 사용하는 함수로는 Errorf
와 Fatalf
가 있다. 기능을 간단하게 소개하면 다음과 같다.
Errorf: Log를 실행한 이후 Fail를 실행한다. 포맷 문자열을 출력하고 다음 테스트를 진행하는 것과 같다.
Fatalf: Log를 실행한 이후 FailNow를 실행한다. 포맷 문자열을 출력하고 다음 테스트를 진행하지 않는다.
Log는 Printf와 같고, Fail은 unit을 fail 처리한 후 계속 실행, FailNow는 fail처리한 후 실행을 멈춘다.
테스트가 여러 개일 경우
여러 개의 테스트를 수행하고 싶으면 다음과 같이 하면 된다.
package main
import (
"testing"
)
func TestTestName(t *testing.T) {
if myadd(1, 4) != 5 {
t.Errorf("Test Failed")
}
if myadd(3, 4) != 7 {
t.Errorf("Test Failed")
}
if myadd(1, 3) != 5 {
t.Errorf("Test Failed")
}
}
그런데 이렇게 할 경우 테스트를 수정하려면 고쳐야 할 코드 부분이 너무 많다. 이럴 땐 구조체 배열을 활용하면 반복된 구문을 줄여 유지보수하기 쉬워진다.
package main
import (
"testing"
)
func TestMyadd(t *testing.T) {
tests := []struct {
param1 int
param2 int
expectedResult int
}{
{1, 4, 5},
{3, 4, 7},
{1, 3, 5},
}
for _, test := range tests {
if myadd(test.param1, test.param2) != test.expectedResult {
t.Errorf("Test Failed")
}
}
}
assert를 활용한 테스트
쉽게 코드를 테스트하기 위해 assert라는 패키지가 존재한다. (사용하기 위해 설치가 필요하다) assert를 사용하면 테스트 코드를 더 직관적이고 깔끔하게 만들어 줄 수 있다.
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMyadd(t *testing.T) {
tests := []struct {
param1 int
param2 int
expectedResult int
}{
{1, 4, 5},
{1, 3, 4},
{1, 3, 5},
}
for _, test := range tests {
assert.Equalf(t, myadd(test.param1, test.param2), test.expectedResult, "Test description")
}
}