23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
소프트웨어 개발에서 테스트는 매우 중요하다. 테스트는 여러가지 단계로 나누어 수행되는데 모듈별 테스트로부터 통합테스트까지 다양한 기준점으로 나뉜 테스트들이 개발과정 곳곳에서 수행된다.
단위 모듈 관점에서 테스트 코드를 넣고 이를 주기적으로 돌리는 방식이 단위 테스트이다. (한국에서) 근 20년동안 가장 사랑받는 언어인 Java에서 사용하는 JUnit과 같은 단위테스트 방법이 가장 유명하고 이러한 테스트를 통한 개발 방법론도 있다. (TDD)
Go의 영향력이 높아지면서 Go에서도 테스트에 대한 요구들이 나오고 있고 본 페이지를 통해 그 방법을 정리하고자 한다.
Go에서 시스템적으로 정의하는 테스트 방법은 매우 간단하다. 다음의 규칙을 지켜주면 테스트 된다.
Go는 테스트 프레임워크를 내장
go test 명령을 통해 테스트
*_test.go 에대한 테스트 수행
TestXxx 형태의 임의의 매서드에 대해 테스트 진행
작성 규칙은 다음과 같다.
파일명은 <span style="font-size:16px;">\_test.go</span>로 끝난다.
함수명은 <span style="font-size:16px;">Test</span>로 시작한다.
매개변수는 <span style="font-size:16px;">t \*testing.T</span>를 받는다.
실패지점에서 <span style="font-size:16px;">t.Fail()</span>을 호출한다.
이를 통해 아래와 같이 작성한다.
package는 test
testing 모듈 import
함수 작성
입력으로 testing.T를 받고
testing.T는 오류함수 제공
Fatal() / Error() / Fail() / Log() 등 함수 지원
package test
import "testing"
func TestFoo(t *testing.T) {
// todo test code, the variable 'result' should be defined
expected := 1
actual := 0
if result != actual {
t.Fatal("원하는 결과가 아니네요.")
// t.Error()
// t.Fail()
// t.Log()
}
}기본 test를 하다보면 원하는 조건을 찾기위해 많은 if 문이 발생하는데 이를 깔끔하게 정리하도록 도와주는 것이 assert 패키지 (github.com/stretchr/testify/assert)
package test
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFoo(t *testing.T) {
// todo test code
expected := 1
actual := 0
assert.Equal(t, expected, actual, "원하는 결과가 아니네요.")
}assert 패키지는 정리된 결과값을 보여준다.
siim@adm:~/go/src/tks-client/test$ go test
--- FAIL: TestFoo (0.00s)
service_copy_test.go:12:
Error Trace: service_copy_test.go:12
Error: Not equal:
expected: 1
actual : 0
Test: TestFoo
Messages: 원하는 결과가 아니네요.
FAIL
exit status 1
FAIL github.com/openinfradev/tks-client/test 0.005s모든 테스트 실행 $ go test
*_test.go 대상으로 테스트 실행하며 상세한 수행내역( -v ) 확인 $ go test *_test.go -v\
특정 테스트 함수(TestFunctionName) 실행 $ go test -run TestFunctionName -v
하나의 함수를 테스트하기 위해 여러개의 테스트 케이스가 존재하며 일반적으로 테스트를 작성하면 하나의 테스트 함수는 하나의 테스트 케이스를 수행한다. 이런 경우 테스트 케이스의 숫자와 동일한 테스트 함수가 나오게되고 각 테스트 함수들은 동일 함수에 대한 테스트 이므로 중복된 코드들을 갖게 된다. 이러한 중복을 제거하고자 이를 통합하는 방법으로 테이블 주도 테스트가 이용되고 있다.
테이블 주도 테스트는 모든 테스트 케이스들을 테이블로 구성하고 하나의 테스트 함수에서 이 테이블을 순회하면서 테스트 한다. 이를 통해 함수 하나당 하나의 테이스 함수를 갖도록 구성할 수 있다.
이 방식은 여러 Go 언어 커뮤니티에서 권장하는 방식이다.
테스트 케이스를 구성하고 이에 대한 성공 실패를 판단에 충분한 데이터를 테이들에 포함시키는 것이 중요하다. 따라서 테스트를 위한 객체와 매개변수, 결과, 테스트를 위한 인자 등을 필요에 따라 구성하면 된다.
다음 예제는 아래와 같은 목적을 수행하기 위해 정의한 구조의 일부이다.
파라미터를 전달 - args
기대하는 출력을 전달 - out, err
불필요한 출력은 비교하지 않는다 - out_check
testcases := []struct {
args []string
out_check bool
err error
out string
}{
{[]string{"wrong"}, true, errors.New("unknown command \\"wrong\\" for \\"tks\\""), ""},
{[]string{"wrong", "cmd"}, true, errors.New("unknown command \\"wrong\\" for \\"tks\\""), ""},
{[]string{"completion", "powershell"}, false, nil, ""},
{[]string{"--config"}, true, errors.New("flag needs an argument: --config"), ""},
{[]string{"cluster", "create"}, true, errors.New("required flag(s) \\"contract-id\\", \\"csp-id\\" not set"), ""},
.........전체 케이스를 순회하면서 테스트를 진행한다.
for _, tc := range testcases {
out, err := execute(t, rootCmd, tc.args...)
is.Equal(tc.err, err)
if tc.err == nil && tc.out_check {
is.Equal(tc.out, out)
}
}본 페이지를 통해 Go에서 개발물에 대한 테스트 코드를 작성하는 방법을 알아보았다. 이 글이 Go test는 정형적인 패턴이 없는 자유로움을 갖고 있고 이로인해 테스트 케이스를 작성하는데 막연함을 갖고 있는 다른분들에게 도움이 되길 바란다.
본 내용은 팀에서 개발하고 있는 CLI툴에 대한 테스트를 구성하는 과정에서 알아보았던 내용을 다룬것으로 추가적으로 COBRA라는 CLI용 프레임워크(? 라이브러리?)에서 테스트하는 것을 최종목적으로 하고 있다. 이 내용은 다음 링크에서 확인할 수 있다.
https://heavenly-part-d73.notion.site/Go-a2c6a5b19ef34a1cadb042c047971a92
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.