본문 바로가기
프로그래밍/GO

[golang] 조건문 및 루프가 있는 함수 유닛 테스트, nested function

by 남생 namsaeng 2022. 6. 9.
반응형

 

 

 

nested function in unit test
nested function in unit test

 

 

golang 유닛 테스트를 하다 보면 대상 함수에 단순히 조건문뿐만 아니라 루프가 있는 경우도 있다. 루프 안에 조건문에 대한 커버리지를 확인하기 위해서는 테스트 함수에서 루프를 빠져나갈 상태 변수를 선언해줘야 한다. 다른 객체지향 언어와 다르게 golang은 클래스가 존재하지 않지만 구조체를 클래스(e.g.1 C++: 멤버 함수, Go: Receiver / e.g.2 C++:상속, Go: Embedding)처럼 사용할 수 있다. 또한, golang에서는 nested class 특징을 nested function로 사용할 수 있다.

 

이전 포스팅을 통해 효율적인 유닛 테스트를 하기 위해서는 어댑터 패턴 기반으로 리팩터링해야 한다는 것을 알았다. 그리고 페이크 함수를 구현하여 실제 네트워크 및 파일 시스템(혹은 DB)에 접근하지 않고도 마치 해당 로직을 수행한 것과 같은 결과를 만들어 낸 것을 알았다. 위의 그림에서 TestBlocks(t *testing.T) 함수의 테스트 대상은 Blocks 함수이며, 이 Blocks 함수 안에는 루프 문이 존재한다. 여기에서 fakeBlocks는 루프 문을 간접적으로 빠져나가게 하기 위한 상태 변수이며, nested function 성질에 의해 fakeFindBlock 함수가 호출될 시에 1씩 증가한다.

 

 

<blockchain/blockchain.go>

  • 테스트 시에 FindBlock 함수는 페이크 함수인 fakeFindBlock를 호출할 것이며, fakeFindBlock은 block.PrevHash != ""인 경우와 block.PrevHash == "" 경우를 위하여 적절한 형태로 정의된다.
func Blocks(b *blockchain) []*Block {
	b.m.Lock()
	defer b.m.Unlock()
	var newBlocks []*Block
	hashCursor := b.NewestHash
	for {
		block, _ := FindBlock(hashCursor)
		newBlocks = append(newBlocks, block)
		if block.PrevHash != "" {
			hashCursor = block.PrevHash
		} else {
			break
		}
	}
	return newBlocks
}

 

 

<blockchain/blockchain_test.go>

  • block.PrevHash != "" 커버리지를 위한 조건 : fakeBlocks == 0
  • block.PrevHash == "" 커버리지를 위한 조건 : fakeBlocks == 1
func TestBlocks(t *testing.T) { // TestBlocks 테스트 함수는 한번 호출되지만, Blocks의 FindBlock으로 인해(loop) fakeFindBlock은 여러번 호출이 된다.
	fakeBlocks := 0 // fakeFindBlock이 여러번 호출, 호출 횟수 상태 저장하기 위한 변수.. 전역변수 역할
	dbStorage = fakeDB{
		fakeFindBlock: func() []byte {
			var b *Block
			if fakeBlocks == 0 {
				b = &Block{
					PrevHash: "x",
				}
			}
			if fakeBlocks == 1 {
				b = &Block{
				}
			}
			fakeBlocks++ // 안해주면 무한루프
			return utils.ToBytes(b)
		},
	}
	bc := &blockchain{}
	blocks := Blocks(bc)
	if reflect.TypeOf(blocks) != reflect.TypeOf([]*Block{}) {
		t.Error("Blocks() should return a slice of blocks")
	}

}
반응형

댓글