이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

코딩/GoLang

Golang gtest

이쿠우우 2022. 1. 2. 15:55
반응형

 

 
 

Golang gtest

 
 

 
 

gtest란?

Golang의 장점 중에 하나는 코드를 테스트하기 위해 별도의 환경을 구축할 필요가 없다는 점임.
Golang에서는 gtest를 통해 아주 간편하게 코드를 test할 수 있음.
Google Test Framework로 유닛 테스트에 사용됨.
Google Test는 Google의 특정 요구사항 및 제약사항을 기반으로 테스트 기술팀에서 개발한 
Testing 프레임워크임.
 
 

왜 Google Test를 사용해야 하나?

1. 테스트는 독립적이고 반복가능해야 합니다. gtest는 디버깅을 빠르게 할 수 있도록 테스트를 분리시켜 실행할 수 있도록 해 줌.
2. 테스트는 조직화가 잘 되어있으며 테스트되는 코드의 구조를 반영할 수 있어야 함. 
    gtest는 데이터와 서브루틴을 공유할 수 있는 테스트 케이스안에 서로 연관된 테스트들을 그룹화 시킬 수 있음.
3. 테스트는 이식과 재사용이 가능해야 합니다. gtest는 많은 OS, 컴파일러 등을 지원.
4. 테스트가 실패했을 때 가능한 한 문제에 대한 많은 정보를 제공해 주어야 함.
5. 테스트 프레임웍은 테스터를 잡다한 일에서 벗어나게 해 주어, 테스트 내용에 집중할 수 있도록 해야 함. 
    gtest는 자동으로 테스트를 추적하며, 사용자는 테스트를 실행하기 위해 테스트를 일일히 열거하지 않아도 됨.
6. 테스트는 빨라야 함. gtest를 사용하면 테스트간 의존성없이 테스트 간에 공유되는 리소스를 재사용할 수 있고, 
    set-up/tear-down 함수도 한번만 작성하면 됨.
 
 
 

 

유닛 테스트란?(Unit Test)

유닛 테스트는 개발한 가장 작은 단위 코드를 테스트하고자  작성한 코드로,
주로 특정 메소드를 실행해서 그 결과가 기대값과 일치하는지 확인하는 형태.
하나의 유닛테스트(Unit Test)는 하나의 함수의 특정 루틴을 검사함.
 

 
 

Golang gtest 실습

 
golang에서 gtest하는 방법은 아주 간단함.
아래와 같은 package를 예를 들어서 설명하겠음.
 
[실습 환경]
package

utils라는 package가 있고 아래와 같은 함수들이 있음.

 

1. gtest용 파일 생성.

utils 라는 package를 test하기 위해 아래와 같이 
utils_test.go 파일을 생성함.

그리고 package를 utils라고 명시하면
vscode는 자동으로 해당 파일은 utils package test code라는 것을 인식함.
즉 파일이름에 test가 들어가 있으면 gtest용 code라는 것을 자동으로 인지함.

상위에 보이는 run package tests를 클릭하면 
utils package의 gtest가 자동으로 실행됨.
 

2. test function 생성

 
utils package의 다양한 함수 중 Hash 함수를 예로 test 해보겠음.
 

1) utils_test.go 파일에 func TestHash() 함수를 생성

 
function 이름도 Test라는 문자가 포함되면 
vscode에서 자동으로 gtest용 function임을 인지함.
func TestHash() {
}
이와 같이 생성하면 아래와 같은 에러가 발생함

2) t *testing.T parameter 추가

모든 test function은 같은 parameter를 가져야하기 때문에 다음과 같은 parameter를 작성해줌.
그래서 상위 메세지와 같이 t *testing.T parameter를 추가해줘야함.
해당 testing.T를 사용해서 테스트에서 에러, 서브 test, test내용을 console에 출력하는 등
다양한 gtest function을 사용할 수 있음.
func TestHash(t *testing.T) {
}
 
 

2. Hash function gtest 작성

Hash 함수 코드는 아래와 같음

Hash function은 i interface parameter를 Hash 해주는 함수임.
해당 Hash function을 test하기 위해서는 2가지 확인해야함.
 
첫 번째 =  동일한 parameter(i interface)에 대해 항상 같은 hash를 return 해야함
두 번째 = 유효한 hexa decimal string을 return 해야함.
 
 

1) t *testing.T를 통해 gtest log를 확인.

첫 번째 test를 위해 먼저 Hash 함수를 통해 얻은 hash값을 알아야함.
그러기 위해 testing에 printf 처럼 console에 log를 찍어봐야함
testing.T 의 log는 아래와 같이 사용할 수 있음.
t.Log("출력 data")
func TestHash(t *testing.T) {
    s := struct{ Test string }{ Test: "test" }
    x := Hash(s)
    t.Log(x)
}
위와 같이 작성 후 아래 그림의 run test를 클릭하면

test는 되지만 결과만 나오고 test에 대한 자세한 log는 확인되지 않음.
그래서 정확한 gtest 과정을 확인하기 위해서는 console창에서 아래와 같은 명령어를 입력해줘야함.
 
[명령어]
go test ./... -v
./...  = 모든 디렉토리의 모든 파일에 대해 테스트 한다는 것을 의미함.
-v = verbose 옵션으로 모든 과정이 출력됨.
 
해당 명령어를 실행하면 아래와 같이 log를 확인 할 수 있음
즉 Hash 함수를 실행하여 얻은 hash값을 확인 할 수 있음.

 

 

2) 첫 번째 test를 생성.

동일한 parameter(i interface)에 대해 항상 같은 hash를 return 해야함.
항목을 테스트 하기 위해 아래와 같이 작성
func TestHash(t *testing.T) {
    hash := "e005c1d727f7776a57a661d61a182816d8953c0432780beeae35e337830b1746"
    s := struct{ Test string }{ Test: "test" }
    x := Hash(s)
    if x != hash {
        t.Errorf("Expected %s, got %s", hash, x)
    }
}
상위 단계에서 확인한 hash값과 
struct s 변수를 hash 한 값이 동일하면 test 통과고
아니라면 해당 test는 fail로 error를 발생함.
 
결과를 보면 hash 값이 동일함으로 PASS가 되는 것을 확인할 수 있음

 
 

2) 두 번째 test를 생성. (sub test 생성)

첫 번째 항목은 확인했으니 이제 두 번째 항목을 test해야함.
두 번째 항목은 유효한 hexa decimal string을 return 해야함.
해당 두 번째 test를 위해 sub Test를 생성해줘야함
 
sub test의 사용법은 t.Run 함수임.
func TestHash(t *testing.T) {
    hash := "e005c1d727f7776a57a661d61a182816d8953c0432780beeae35e337830b1746"
    s := struct{ Test string }{Test: "test"}
    t.Run("Hash is always same", func(t *testing.T) {
        x := Hash(s)
        if x != hash {
            t.Errorf("Expected %s, go %s", hash, x)
        }
    })
    t.Run("Hash is hex encoded", func(t *testing.T) {
        x := Hash(s)
        _, err := hex.DecodeString(x)
        if err != nil {
            t.Error("Hash should be hex encoded")
        }
    })
}
t.Run을 통해 한 function에 대해 다양한 test를 진행할 수 있음.
첫 번째 t.Run을 통해 동일한 parameter(i interface)에 대해 항상 같은 hash를 return test를 진행했고
두 번째 t.Run을 통해 유효한 hexa decimal string을 return test를 진행함.
 

3) 결과 확인

Hash 함수에 대해 두 가지 test가 모두 통과됐음을 확인할 수 있음.

 
 

3. Cover Profile

gtest 결과를 -v 옵션을 통해 console log로 확인할 수 있지만.
이는 한 눈에 확인하기 너무 불편함.
gtest는 깔끔하게 test결과를 확인할 수 있도록 cover profile 기능을 제공하고 있음.
cover profile은 테스트 상태를 나타내는 파일임.
 
[cover profile 생성 명령어]
go test -v -coverprofile cover.out
-coverprofile cover.out = coverprofile 결과를 cover.out 파일로 생성한다는 명령어.
 
[결과 확인]
해당 명령을 실행하면 console log는 변함이 없어보임
하지만 cover.out 파일이 생성된 것을 확인할 수 있음.
해당 파일을 열어보면 해석할 수 없는 문자열을 확인할 수 있음.

이 문자열들은 테스트를 적용한 function, line을 정리해놓은 것 임.
즉 보기가 불편한 상태의 파일임.
이를 더 편하게 보기 위해 아래의 명령을 사용해야함.
 
[명령어]
go test -v -coverprofile cover.out ./... ;  go tool cover -html="cover.out"
 
[결과 확인]
html 창이 하나 열리면서 결과를 확인할 수 있음
글자 색이 초록색으로 되어있으면 test PASS고
빨간 색이라면 test가 되지 않았거나 FAIL된 항목임을 확인가능.

 

반응형

'코딩 > GoLang' 카테고리의 다른 글

golang vscode args 전달 방법  (0) 2022.01.02
godoc  (0) 2021.12.25
Golang race flag (-race)  (0) 2021.12.25
Golang web crawling 분석  (0) 2021.05.26
GoLang 개념  (0) 2020.12.04