Go에서 단위 테스트(특히 테이블 기반 테스트)를 작성할 때 표준 전역 log 패키지에 출력하는 함수들은 터미널을 순식간에 어지럽힐 수 있습니다.
수십 개의 테스트 케이스 중 단 하나만 실패하더라도, 오류를 찾기 위해 성공한 모든 케이스의 로그 출력을 일일이 스크롤해야 합니다. 이러한 노이즈는 디버깅 속도를 늦추고 테스트 출력을 읽기 어렵게 만듭니다.
흔히 겪는 시나리오를 살펴보고, 로그를 캡처하여 테스트가 실패할 때만 출력하도록 수정하는 방법을 알아보겠습니다.
입력값과 최종 결과를 로깅하는 간단한 함수가 있다고 가정해 보겠습니다.
package add
import (
"log"
)
func add(x, y int) int {
log.Printf("add %d %d", x, y)
res := x + y
log.Printf("add %d %d = %d", x, y, res)
return res
}
이제 세 가지 케이스가 포함된 표준 테이블 기반 단위 테스트를 작성합니다(마지막 케이스는 의도적으로 실패하도록 설계되었습니다).
package add
import (
"testing"
)
func TestAdd(t *testing.T) {
inputs := []struct {
x int
y int
want int
}{
{x: 1, y: 2, want: 3},
{x: 3, y: 2, want: 5},
{x: 4, y: 5, want: 0}, // 의도적으로 실패하는 케이스
}
for _, in := range inputs {
got := add(in.x, in.y)
if in.want != got {
t.Errorf("add %d %d got %d want %d", in.x, in.y, got, in.want)
}
}
}
go test를 실행하면 마지막에 실패를 보여주기 전에 통과한 모든 입력의 로그가 함께 출력됩니다.
$ go test
2020/09/05 09:01:25 add 1 2
2020/09/05 09:01:25 add 1 2 = 3
2020/09/05 09:01:25 add 3 2
2020/09/05 09:01:25 add 3 2 = 5
2020/09/05 09:01:25 add 4 5
2020/09/05 09:01:25 add 4 5 = 9
--- FAIL: TestAdd (0.00s)
add_test.go:28: add 4 5 got 9 want 0
FAIL
exit status 1
실패한 입력에서 생성된 로그만 볼 수 있다면 훨씬 좋을 것입니다. 함수에 로거를 전달(의존성 주입, Dependency Injection)하고 테스트 중에 로그를 임시 버퍼에 기록하면 이를 구현할 수 있습니다.
먼저 함수가 *log.Logger를 받도록 수정해 보겠습니다.
package add
import "log"
func add(logger *log.Logger, x, y int) int {
logger.Printf("add %d %d", x, y)
res := x + y
logger.Printf("add %d %d = %d", x, y, res)
return res
}
다음으로 테스트를 업데이트합니다. 각 테스트 케이스 반복마다 새로운 bytes.Buffer를 생성하고 여기에 새 로거를 연결합니다. 테스트가 통과하면 버퍼는 그대로 버려집니다. 테스트가 실패하면 오류 메시지와 함께 버퍼의 내용을 출력합니다!
(참고: Go에서 테이블 기반 하위 테스트를 실행하는 관용적인 방법인 t.Run을 사용하도록 테스트도 함께 개선했습니다).
package add
import (
"bytes"
"log"
"testing"
)
func TestAdd(t *testing.T) {
inputs := []struct {
name string
x int
y int
want int
}{
{name: "1+2", x: 1, y: 2, want: 3},
{name: "3+2", x: 3, y: 2, want: 5},
{name: "4+5", x: 4, y: 5, want: 0}, // 의도적으로 실패하는 케이스
}
for _, in := range inputs {
t.Run(in.name, func(t *testing.T) {
// 1. 로그를 캡처할 버퍼 생성
var buf bytes.Buffer
// 2. 버퍼에 기록하는 새 로거 생성
logger := log.New(&buf, "", log.LstdFlags)
// 3. 사용자 지정 로거를 함수에 전달
got := add(logger, in.x, in.y)
if in.want != got {
// 4. 테스트가 실패한 경우에만 버퍼 내용 출력
t.Errorf("got %d want %d\n\nExecution Logs:\n%s", got, in.want, buf.String())
}
})
}
}
이제 테스트를 실행하면 출력이 완벽하게 깔끔해지고 즉각적인 조치를 취하기 쉬워집니다. 실패와 관련된 로그만 정확히 확인할 수 있습니다.
$ go test
--- FAIL: TestAdd (0.00s)
--- FAIL: TestAdd/4+5 (0.00s)
add_test.go:35: got 9 want 0
Execution Logs:
2020/09/05 09:22:48 add 4 5
2020/09/05 09:22:48 add 4 5 = 9
FAIL
exit status 1
함수를 전역 로거로부터 분리함으로써 코드는 더욱 유연해지고, 테스트 스위트는 조용해지며, 디버깅 속도는 훨씬 빨라집니다.
카우에의 삶의 방식 오프라인 에디션을 받아보세요—🍏 건강, 💰 부, ❤️ 사랑, 🧘 의미를 최적화하기 위한 실전 가이드입니다.
더 나은 삶을 위한 새로운 에세이, 도서 요약, 실전 가이드를 발행할 때 알림을 받아보세요. 스팸은 없으며 언제든 구독을 취소할 수 있습니다.
질문, 의견 또는 제안이 있으신가요? 아래에 생각을 남겨주세요. 댓글은 GitHub Discussions(광고 및 스팸 없음)를 통해 제공됩니다—댓글이나 반응을 남기려면 아래의 GitHub으로 로그인을 클릭하세요(무료 GitHub 계정은 1분 이내에 만들 수 있습니다).
최종 업데이트: 2026. 10. 11..
면책 조항: 본 사이트의 콘텐츠는 정보 제공 및 교육 목적으로만 제공되며 의학, 심리, 재무, 투자, 세무 또는 법률 자문을 구성하지 않습니다. 여기에 제시된 생각, 큐레이션 및 의견은 전적으로 저 개인의 것이며 고용주의 입장을 대변하지 않습니다. 도서, 강연 및 아티클 요약은 독립적인 교육적 해설이며 각 저자의 지적 재산입니다. 편집, 서식 지정 및 요약을 돕기 위해 AI 도구가 사용될 수 있으며, 정확성을 기하기 위해 최선을 다하고 있으나 오류가 포함될 수 있습니다. 개인정보 처리방침: 본 사이트는 선택적 뉴스레터 구독(follow.it), 댓글(giscus / GitHub Discussions) 및 임베디드 미디어(YouTube)를 위해 제3자 서비스를 사용하며, 해당 서비스들은 각자의 개인정보 처리방침에 따라 방문자의 IP 주소와 쿠키를 처리할 수 있습니다.