go test parallel fail

# go test 에서 테스트 함수 하나가 가끔 실패한다.
# 테스트 함수에 t.Parallel() 를 추가 후 발생 빈도가 많아졌다.
# 참고로 gotest 를 사용하면 테스트 결과가 컬러로 표시된다.
go install github.com/rakyll/gotest@latest

# 에러가 발생하는 테스트 함수는 항상 같다.
# 다음과 같이 count 옵션으로 cache 를 사용하지 않고 테스트 함수가 많이 테스트 되도록 하면 100% 발생한다.
gotest -run TestMyQuery -count 100 ./...

# 서비스 로직은 Object-Relational Mapping(ORM) 으로 gorm 을 사용해 mysql 쿼리한다.
# 서비스 로직을 테스트 하기 위한 함수는 다음과 같이 sqlmock 을 사용한다.
func TestMyQuery(t *testing.T) {
t.Parallel()
mockDB, mock, err := sqlmock.New()
if err != nil {
log.Fatal(err)
}
gormDB, _ := gorm.Open(mysql.New(mysql.Config{
Conn:                      mockDB,
SkipInitializeWithVersion: true,
}), &gorm.Config{})
... 생략 ...
        # MyQuery() 에서 수행할 조회, 업데이트등의 쿼리 명시
        # MyQuery() go 루틴에서 처리하는 쿼리들
mock.ExpectBegin()
mock.ExpectQuery("^SELECT \\* FROM `my_table` WHERE `key`=(.+) LIMIT (.+)$").WillReturnRows(AddMyTableData())
mock.ExpectExec("^UPDATE `my_table` SET (.+)$").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()

        # MyQuery() 에서 처리하는 쿼리들
mock.ExpectQuery("^SELECT \\* FROM `my_table` WHERE `key`=(.+) LIMIT (.+)$").WillReturnRows(resMyTableRows)
mock.ExpectQuery("^SELECT \\* FROM `my_history` WHERE `my_history`.`id` = (.+)$").WillReturnRows(resMyHistoryRows)
... 생략 ...
        # 테스트 대상 호출
        MyQuery()

# 테스트 실패시 MyQuery() 에서 error 를 출력해 보면 다음과 같이 테스트 함수에 명시한 expect 쿼리 순서가 맞지 않는듯 하다.
call to Query 'SELECT * FROM `my_table` WHERE `key`=? LIMIT ?' with args [{Name: Ordinal:1 Value:ysoftman_test} {Name: Ordinal:2 Value:1}], was not expected, next expectation is: ExpectedBegin => expecting database transaction Begin

# 원인은 MyQuery() 내에서 go 루틴으로 조회,업데이트하는 쿼리가 동작하고 있었고
# 다음 함수로 expect 순서 매칭을 비활성화하면 100번 반복 테스트해도 성공한다.
mock.MatchExpectationsInOrder(false)

comments:

댓글 쓰기