이전 포스팅을 통해 조건문 및 루프가 있는 함수의 유닛 테스트를 알아보았다. 이번에는 조건문이 있는 함수를 조건문에서 호출하는 함수의 유닛 테스트이다.
https://namsaenga.tistory.com/70
getDifficulty 함수의 유닛 테스트는 조건문에 따라 3가지의 경우(b.Height가 0, b.Height%difficultyInterval이 0, 그 외)를 고려해야 한다. b.Height%difficultyInterval이 0일 때는 recalculateDifficulty 함수를 호출하는데 이 함수 내에도 조건문이 존재해 3가지의 경우를 다 테스트해야 한다. TestRecalculateDifficulty(t *testing.T) 함수가 정의되어 있다면 테스트를 위해 recalculateDifficulty(b *blockchain) int를 호출하는 것이 아닌 TestRecalculateDifficulty(t *testing.T) 함수를 호출할 것이기 때문에, 해당 함수에 3개의 커버리지를 테스트할 수 있는 서브 테스트를 만들어 준다.
func getDifficulty(b *blockchain) int {
if b.Height == 0 {
return defaultDifficulty
} else if b.Height%difficultyInterval == 0 {
return recalculateDifficulty(b)
} else {
return b.CurrentDifficulty
}
}
func recalculateDifficulty(b *blockchain) int {
allBlocks := Blocks(b)
newestBlock := allBlocks[0] // 가장 최근 블록은 allBlocks[0]
lastRecalculatedBlock := allBlocks[difficultyInterval-1] // 가장 최근 재설정된 블록
actualTime := (newestBlock.Timestamp / 60) - (lastRecalculatedBlock.Timestamp / 60)
expectedTime := difficultyInterval * blockInterval
if actualTime < (expectedTime - allowedRange) {
return b.CurrentDifficulty + 1
} else if actualTime > (expectedTime + allowedRange) {
return b.CurrentDifficulty - 1
}
return b.CurrentDifficulty
}
여기에서 첫 번째 t.Run은 recalculateDifficulty의 if actualTime < (expectedTime - allowedRange) 를 테스트하고, 두 번째 t.Run은 else, 마지막 t.Run은 else if actualTime > (expectedTime + allowedRange)를 테스트한다.
func TestRecalculateDifficulty(t *testing.T) {
t.Run("1", func(t *testing.T) {
blocks := []*Block{
{PrevHash: "x", Timestamp: 120},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "", Timestamp: 0},
}
fakeBlock := 0
dbStorage = fakeDB{
fakeFindBlock: func() []byte {
defer func() {
fakeBlock++
}()
return utils.ToBytes(blocks[fakeBlock])
},
}
bc := &blockchain{} //{Height: 5, CurrentDifficulty: 3}
got := recalculateDifficulty(bc)
t.Errorf(" recalculateDifficulty should return %d got %d", bc.CurrentDifficulty+1, got)
})
t.Run("2", func(t *testing.T) {
blocks := []*Block{
{PrevHash: "x", Timestamp: 480},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "", Timestamp: 0},
}
fakeBlock := 0
dbStorage = fakeDB{
fakeFindBlock: func() []byte {
defer func() {
fakeBlock++
}()
return utils.ToBytes(blocks[fakeBlock])
},
}
bc := &blockchain{Height: 5, CurrentDifficulty: 3}
got := recalculateDifficulty(bc)
t.Errorf(" recalculateDifficulty should return %d got %d", bc.CurrentDifficulty, got)
})
t.Run("3", func(t *testing.T) {
once = *new(sync.Once)
blocks := []*Block{
{PrevHash: "x", Timestamp: 4800},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "", Timestamp: 0},
}
fakeBlock := 0
dbStorage = fakeDB{
fakeFindBlock: func() []byte {
defer func() {
fakeBlock++
}()
return utils.ToBytes(blocks[fakeBlock])
},
}
bc := &blockchain{} //{Height: 5, CurrentDifficulty: 3}
got := recalculateDifficulty(bc)
t.Errorf(" recalculateDifficulty should return %d got %d", bc.CurrentDifficulty-1, got)
})
}
func TestGetDifficulty(t *testing.T) {
blocks := []*Block{
{PrevHash: "x", Timestamp: 720},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "x", Timestamp: 60},
{PrevHash: "", Timestamp: 0},
}
fakeBlock := 0
dbStorage = fakeDB{
fakeFindBlock: func() []byte {
defer func() {
fakeBlock++
}()
return utils.ToBytes(blocks[fakeBlock])
},
}
type test struct {
height int
want int
}
tests := []test{
{height: 0, want: defaultDifficulty},
{height: 2, want: defaultDifficulty},
{height: 5, want: 3},
}
for _, tc := range tests {
bc := &blockchain{Height: tc.height, CurrentDifficulty: defaultDifficulty}
got := getDifficulty(bc)
if got != tc.want {
t.Errorf("getDifficulty() should return %d got %d", tc.want, got)
}
}
}
'프로그래밍 > GO' 카테고리의 다른 글
[golang] 조건문 및 루프가 있는 함수 유닛 테스트, nested function (0) | 2022.06.09 |
---|---|
[golang] Adapter Pattern 기반 Unit Test(2) (0) | 2022.06.08 |
[golang] Adapter Pattern 기반 Unit Test(1) (0) | 2022.06.08 |
[golang] Unit Test 및 Interfaces 기반 테스트 (0) | 2022.06.02 |
godoc 설치 및 사용법 / go 테스트 및 커버리지 확인 (0) | 2022.05.30 |
댓글