Gorm 테스트에서 피드 삽입과 병렬 실행을 좋게 합니다

Gorm 테스트에서 피드를 삽입하고 병행 실행하고 싶습니다


내용은 대체로 다음과 같은 두 가지가 있다
  • Dao 패키지에 대한 동시 테스트
  • 테스트 시작 시 피드를 삽입하는 좋은 느낌
  • 샘플 코드.
    https://github.com/tanimutomo/gorm-txdb

    동시에 Dao Package 테스트 수행


    Dao 등 DB 관련 패키지 테스트에서는 데이터베이스라는 공유 리소스를 활용해야 하기 때문에 대개 병렬 실행이 불가능합니다.
    여기, 참고DATA-DG/go-txdb로 DB 연결을 포함한 테스트를 쉽게 쓰기, 이용DATA-DOG/go-txdb으로 상당히 좋은 느낌을 해결했습니다.
    이 글은 txdb를 상세하게 설명하지 않습니다.
    txdb에 관해서는 보고서나 위의 글을 보십시오.
    이 글은 gorm에서 txdb를 사용할 때의 방법에 중점을 두고 있다.

    테스트 시작 시 좋은 느낌에 피드를 삽입합니다


    나는 테스트 데이터를 모든 테스트에 삽입하는 느낌이 매우 좋다고 생각하지만, 나는 몇 가지 선택이 있다고 생각한다.
    나는 사용하기 시작했다go-testfixtures/testfixtures.yaml 파일이 너무 많이 늘어나는 것을 싫어하고 표 내용을 delete 처리하는 것이 번거롭기 때문에 sql 파일을 직접 실행할 수 있는tanimutomo/sqlfile을 만들어서 사용했다.
    하지만 SQL은 사람한테는 쓰기 어려워요.
    그래서 저는 많은 생각을 했습니다. *gorm.DB.Create 제가 발견한 방법의 매개 변수는 interface{}입니다. []interface{}{...}는 피드만 정의하면 테스트 데이터를 정의할 수 있고 삽입 처리를 할 수 있다고 생각합니다.

    테스트 코드


    한 마디로 하면 실제 데이터의 테스트 코드가 비교적 빠를 것 같아서 싣겠습니다.
    https://github.com/tanimutomo/gorm-txdb/blob/main/pkg/dao/user_test.go
    Get 및 Create 방법 및 하위 테스트는 모두 t.Parallel()로 병행됩니다.
    이번 간은 각 테스트 함수의 여기에 있다.
    // pkg/dao/user_test.go
    
    package dao
    
    import (
    	"testing"
    
    	"github.com/stretchr/testify/assert"
    	"github.com/tanimutomo/gorm-txdb/pkg/entity"
    )
    
    func TestUserDao_Get(t *testing.T) {
    	t.Parallel()
    
    	seeds := []interface{}{
    		&entity.User{ID: int64(1), Name: "foo"},
    	}
    	db, err := prepare("user_dao_get", seeds)
    	if err != nil {
    		t.Fatal(err)
    	}
    	d := NewUser(db)
    
    	tests := []struct {
    		name   string
    		give   int64
    		wantID int64
    		err    bool
    	}{
    		{
    			name:   "success",
    			give:   int64(1),
    			wantID: int64(1),
    		},
    		{
    			name: "not found",
    			give: int64(2),
    			err:  true,
    		},
    	}
    	for _, tt := range tests {
    		tt := tt
    		t.Run(tt.name, func(t *testing.T) {
    			t.Parallel()
    
    			got, aerr := d.Get(tt.give)
    			if tt.err {
    				assert.Error(t, aerr)
    			} else {
    				assert.NoError(t, aerr)
    				assert.Equal(t, tt.wantID, got.ID)
    			}
    		})
    	}
    }
    
    func TestUserDao_Create(t *testing.T) {
    	t.Parallel()
    
    	seeds := []interface{}{
    		&entity.User{Name: "exist"},
    	}
    	db, err := prepare("user_dao_create", seeds)
    	if err != nil {
    		t.Fatal(err)
    	}
    	d := NewUser(db)
    
    	tests := []struct {
    		name string
    		give string
    		err  bool
    	}{
    		{
    			name: "success",
    			give: "non exist",
    		},
    		{
    			name: "duplicated",
    			give: "exist",
    			err:  true,
    		},
    	}
    	for _, tt := range tests {
    		tt := tt
    		t.Run(tt.name, func(t *testing.T) {
    			t.Parallel()
    
    			aerr := d.Create(tt.give)
    			if tt.err {
    				assert.Error(t, aerr)
    			} else {
    				assert.NoError(t, aerr)
    				assert.NoError(t, db.First(&entity.User{}, "name = ?", tt.give).Error)
    			}
    		})
    	}
    }
    

    설명


    다음은 위의 코드와gorm의 txdb 설정에 대해 간단한 설명을 드리겠습니다.

    txdb를 통해 등록된 DB 호출


    테스트 함수 중*gorm.DB을 얻기 위해prepare(テストデータベース名(テストごとに個別の名前にする), seeds) 함수라고 부른다.
    함수는 이렇다.
    	seeds := []interface{}{
    		&entity.User{ID: int64(1), Name: "foo"},
    	}
    	db, err := prepare("user_dao_get", seeds)
    	if err != nil {
    		t.Fatal(err)
    	}
    	d := NewUser(db)
    
    prepare 함수를 읽으면서prepare(...) 이런 느낌이에요.
    	db, err := prepare("user_dao_get", seeds)
    	if err != nil {
    		t.Fatal(err)
    	}
    
    일반적인 Gorm DB의 초기화와 다른 점은 다음과 같다.
    여기에 txdb로 등록된 Track을 드라이버로 mysql에 로그인합니다. (오류가 있으면 알려주십시오.)
    여기mysql.NewTest 변수에서 각 테스트는 개별적으로 정의된 이름이기 때문에 이곳의 테스트는 다른 거래에서 실행된다. 마치 다른 DB를 처리하는 것과 같이 업데이트 시스템 처리를 포함하는 테스트가 있어도 병행화할 수 있다.
    package dao
    
    import (
    	"github.com/tanimutomo/gorm-txdb/pkg/mysql"
    	"gorm.io/gorm"
    )
    
    func prepare(name string, seeds []interface{}) (*gorm.DB, error) {
    	db, err := mysql.NewTest(name)
    	if err != nil {
    		return nil, err
    	}
    	for _, s := range seeds {
    		if err := db.Create(s).Error; err != nil {
    			return nil, err
    		}
    	}
    	return db, nil
    }
    

    모든 테스트에 테스트 데이터를 삽입하여 기분이 좋아지도록 하다


    테스트 함수 중name을 얻기 위해*gorm.DB라고 부른다.
    seeds는 prepare(testDBName, seeds)로 정의됩니다.
    seeds에 미리 삽입할 모든 데이터를 넣습니다.
    방금 보듯이 함수는 이렇습니다. []interface{}{ Gormのモデルs }를 전보로 전송하여 prepare(...)로 삽입합니다.
    여기에 삽입된 데이터는 txdb에서 정의한 DB에 기록됩니다.
  • 기타 테스트에 영향을 미치지 않음
  • 테스트 종료 후 자동 삭제
  • package mysql
    
    import (
    	"fmt"
    
    	"gorm.io/driver/mysql"
    	"gorm.io/gorm"
    	"gorm.io/gorm/logger"
    
    	"github.com/DATA-DOG/go-txdb"
    	"github.com/tanimutomo/gorm-txdb/pkg/config"
    )
    
    func NewTest(name string) (*gorm.DB, error) {
    	dsn := fmt.Sprintf(
    		"%s:%s@(%s:%s)/%s?charset=utf8mb4&parseTime=true",
    		config.RDS.User, config.RDS.Password,
    		config.RDS.Host, config.RDS.Port,
    		config.RDS.Database,
    	)
    
    	txdb.Register(name, "mysql", dsn)
    	dialector := mysql.New(mysql.Config{
    		DriverName: name,
    		DSN:        dsn,
    	})
    
    	return gorm.Open(dialector, &gorm.Config{
    		Logger: logger.Default.LogMode(logger.Info),
    	})
    }
    

    총결산


    Gorm과 txdb를 이용하여Dao의 테스트를 병행화하고 좋은 느낌에 피드 데이터를 넣는 방법을 썼습니다.
    저도 실험 중이에요. 더 좋은 방법을 아는 사람이 있으면 알려주세요.
    또 잘못된 점이 있으면 지적해 주십시오.
    우리 함께 아름다운 시험 생활을 보내자!📑

    좋은 웹페이지 즐겨찾기