Go 애플리케이션에서 테스트 커버리지 시각화하기

2025. 4. 15. 03:50개발 지식

반응형

Context

테스트 커버리지는 안정성의 척도인가?

어떤 애플리케이션이든 기능이 고도화됨에 따라서 코드가 많아지고, 이 코드가 정상적으로 동작하는지를 테스트하기 위해서 우리는 많은 테스트 코드를 작성합니다.
 
그리고 우리는 테스트의 커버리지를 척도로 삼아 이 애플리케이션이 얼마나 안정적인가를 따지곤 합니다.
 
하지만 실제로 테스트 커버리지가 높다고 해서 애플리케이션이 안정적인 것은 아닙니다.
 
커버리지는 단순히 "작성된 코드 중 테스트가 실제로 실행한 부분"으로, 예외 상황이나 경계 조건까지 테스트를 하지 않으면 수치가 높아도 의미가 없습니다.
 

 

그럼에도 불구하고 커버리지가 중요한 이유

커버리지는 BMI에 비유한다면
 
BMI가 건강의 전부는 아니지만, 기초 지표로는 유용한 것처럼, 커버리지도 그런 신호등 역할을 해줍니다.
 
또한 리팩토링이나 신규 코드 추가 후 안정성을 확인하는 기준으로 커버리지가 사용되기도 합니다.
 
 
 

그럼 어떻게 커버리지를 활용해야할까?

커버리지에서 실제로 확인해야하는 것은 "실제로 중요한 로직이 테스트 되었는가"입니다.
 
예를 들어

func Grade(score int) string {
    if score >= 90 {
        return "A"
    } else if score >= 80 {
        return "B"
    } else {
        return "C"
    }
}

 
이런 코드의 경우 
 

Expect(Grade(95)).To(Equal("A"))

 
이렇게 한 줄만 테스트 해도 커버리지 수치는 100%가 나올 수 있습니다.
하지만 경계값과 다른 분기는 테스트 되지 않았으니 의미있는 커버리지가 아니죠.
 
 
그래서 이런 경계값이나 분기가 잘 테스트 되었는지를 확인하기 위해서는 시각화도구가 도움이 됩니다.
 
커버리지는 단순 수치보단
"중요한 분기와 경계값을 제대로 테스트했는가?"를 눈으로 직접 확인하는 것이 핵심이고,
그걸 도와주는 게 바로 시각화 도구입니다.
 

 

Go에서의 테스트 시각화 도구

Go에서 테스트를 실행할 때 다음과 같은 명령어로 실행할 수 있습니다.
 

go test ${fileName}

 
 
그리고 여기에서 `-cover` 옵션을 주게되면 coverage를 함께 출력해주죠.
 

go test ${fileName} -cover

 
 
하지만 이는 단순히 라인 커버리지만을 출력하기 때문에 원하는 옵션이 아닙니다.
 
 
Go에는 다른 옵션인 `-coverprofile`옵션이 있습니다.
 

go test -coverprofile=cover.out ./...

 
`-coverprofile`옵션을 통해 측정된 커버리지 정보를 cover.out 파일에 저장할 수 있습니다.
 
 
그리고 Go은 Go tool에서 이를 html로의 시각화를 지원합니다.

go tool cover -html=cover.out

 
그러면 이렇게 어디가 테스트 되었는지 알 수 있는 html 파일이 완성되게 됩니다.
 

 

package main

import "testing"

func TestGrade(t *testing.T) {
	tests := []struct {
		score    int
		expected string
	}{
		{95, "A"},
		{85, "B"},
		{75, "C"},
		{65, "C"},
		{55, "C"},
	}

	for _, test := range tests {
		result := Grade(test.score)
		if result != test.expected {
			t.Errorf("Grade(%d) = %s; expected %s", test.score, result, test.expected)
		}
	}
}

 
 

Conclusion

이 문서에서 Go에서 테스트 커버리지를 시각화하는 것을 알아보았습니다.
 
위 기능을 조금 더 발전시킨다면 codecov처럼 "현재 브랜치에서 변경된 파일들에 대한 커버리지"도 측정이 가능합니다.
 
다만 아쉬운 점은 `go test`가 Java의 JaCoCo처럼 라인 커버리지, 브랜치 커버리지 등 다양한 커버리지를 측정할 수 없다는 부분입니다.
 
그렇기에 더더욱 시각화를 해서 경계값에 대한 테스트가 필요합니다.
 
 

반응형