golang测试数据库清理工具插件库dbcleaner的使用

Golang测试数据库清理工具插件库dbcleaner的使用

基本介绍

DbCleaner是一个用于测试时清理数据库的Golang库,灵感来源于Ruby的database_cleaner。它使用flock系统调用确保测试可以并行运行而不会出现竞争问题。

安装

要获取该包,执行以下命令:

go get gopkg.in/khaiql/dbcleaner.v2

导入该包:

import "gopkg.in/khaiql/dbcleaner.v2"

基本用法

与testify的suite一起使用

import (
	"testing"

  	"gopkg.in/khaiql/dbcleaner.v2"
  	"gopkg.in/khaiql/dbcleaner.v2/engine"
	"github.com/stretchr/testify/suite"
)

var Cleaner = dbcleaner.New()

type ExampleSuite struct {
	suite.Suite
}

func (suite *ExampleSuite) SetupSuite() {
  	// 初始化并设置mysql清理引擎
  	mysql := engine.NewMySQLEngine("YOUR_DB_DSN")
  	Cleaner.SetEngine(mysql)
}

func (suite *ExampleSuite) SetupTest() {
  	// 在测试开始前获取表锁
  	Cleaner.Acquire("users")
}

func (suite *ExampleSuite) TearDownTest() {
  	// 测试结束后清理表数据
  	Cleaner.Clean("users")
}

func (suite *ExampleSuite) TestSomething() {
  	// 编写实际测试
  	suite.Equal(true, true)
}

func TestRunSuite(t *testing.T) {
  	suite.Run(t, new(ExampleSuite))
}

配置选项

DbCleaner提供了多种配置选项来处理可能出现的死锁问题:

type Options struct {
	Logger        logging.Logger
	LockTimeout   time.Duration
	NumberOfRetry int
	RetryInterval time.Duration
}

type Option func(opt *Options)

// SetLogger 设置日志记录器实例,默认为Noop
func SetLogger(logger logging.Logger) Option {
	return func(opt *Options) {
		opt.Logger = logger
	}
}

// SetLockTimeout 设置锁定操作的超时时间,默认为10秒
func SetLockTimeout(d time.Duration) Option {
	return func(opt *Options) {
		opt.LockTimeout = d
	}
}

// SetNumberOfRetry 设置获取表的最大重试次数,默认为5次
func SetNumberOfRetry(t int) Option {
	return func(opt *Options) {
		opt.NumberOfRetry = t
	}
}

// SetRetryInterval 设置每次重试之间的休眠时间,默认为10秒
func SetRetryInterval(d time.Duration) Option {
	return func(opt *Options) {
		opt.RetryInterval = d
	}
}

// 使用自定义配置创建Cleaner实例
cleaner := dbcleaner.New(SetNumberOfRetry(10), SetLockTimeout(5*time.Second))

支持的数据库驱动

  • postgres
  • mysql
  • sqlite3

为其他驱动编写清理器

基本上所有被database/sql包支持的驱动也都被dbcleaner支持。对于自定义驱动,实现你自己的engine.Engine接口并在dbcleaner.Cleaner实例上调用SetEngine方法。

许可证

MIT


更多关于golang测试数据库清理工具插件库dbcleaner的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang测试数据库清理工具插件库dbcleaner的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 数据库清理工具 dbcleaner 使用指南

dbcleaner 是一个用于在测试期间清理数据库的 Go 库,它可以帮助你在测试之间保持数据库的干净状态。下面我将详细介绍如何使用这个工具。

安装

首先安装 dbcleaner 包:

go get github.com/khaiql/dbcleaner

基本使用

1. 初始化 dbcleaner

import (
    "github.com/khaiql/dbcleaner"
    "github.com/khaiql/dbcleaner/helper/mysql"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    cleaner := dbcleaner.New()
    
    // 设置 MySQL 连接
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test_db?parseTime=true")
    if err != nil {
        panic(err)
    }
    
    // 添加 MySQL 数据库到 cleaner
    cleaner.SetEngine(mysql.Engine(db))
}

2. 在测试中使用

func TestSomething(t *testing.T) {
    cleaner := dbcleaner.New()
    db, _ := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test_db?parseTime=true")
    cleaner.SetEngine(mysql.Engine(db))
    
    // 在测试开始时获取锁
    cleaner.Acquire("users", "products")
    defer cleaner.Clean("users", "products") // 在测试结束时清理
    
    // 执行测试...
    _, err := db.Exec("INSERT INTO users (name) VALUES (?)", "John Doe")
    if err != nil {
        t.Fatal(err)
    }
    
    // 测试结束后,cleaner.Clean 会自动清理 users 和 products 表
}

高级用法

1. 排除某些表不被清理

cleaner := dbcleaner.New()
cleaner.SetEngine(mysql.Engine(db))

// 设置不清理的表
cleaner.SetIgnoreTables("migrations", "system_settings")

// 只清理指定的表
cleaner.Acquire("users")
defer cleaner.Clean("users")

2. 使用 PostgreSQL

import (
    "github.com/khaiql/dbcleaner/helper/postgres"
    _ "github.com/lib/pq"
)

func TestPostgres(t *testing.T) {
    cleaner := dbcleaner.New()
    db, _ := sql.Open("postgres", "user=postgres dbname=test_db sslmode=disable")
    cleaner.SetEngine(postgres.Engine(db))
    
    cleaner.Acquire("users")
    defer cleaner.Clean("users")
    
    // 测试代码...
}

3. 自定义清理策略

cleaner := dbcleaner.New()
cleaner.SetEngine(mysql.Engine(db))

// 设置自定义的清理函数
cleaner.SetTableTruncateFunc("audit_logs", func(tableName string, db *sql.DB) error {
    // 只删除最近3天的记录,而不是清空整个表
    _, err := db.Exec("DELETE FROM audit_logs WHERE created_at < NOW() - INTERVAL 3 DAY")
    return err
})

cleaner.Acquire("audit_logs")
defer cleaner.Clean("audit_logs")

最佳实践

  1. 在测试套件初始化时创建 cleaner:可以在测试的 TestMain 中初始化 cleaner,然后在各个测试用例中重复使用。
var testCleaner *dbcleaner.DBCleaner

func TestMain(m *testing.M) {
    db, _ := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test_db")
    testCleaner = dbcleaner.New()
    testCleaner.SetEngine(mysql.Engine(db))
    
    code := m.Run()
    os.Exit(code)
}

func TestUser(t *testing.T) {
    testCleaner.Acquire("users")
    defer testCleaner.Clean("users")
    // 测试代码...
}
  1. 按功能模块分组表:将相关的表放在一起清理,减少数据库操作次数。

  2. 注意外键约束:如果表有外键约束,需要按正确的顺序清理表,或者暂时禁用外键检查。

// 对于 MySQL 可以这样禁用外键检查
_, _ = db.Exec("SET FOREIGN_KEY_CHECKS = 0")
defer db.Exec("SET FOREIGN_KEY_CHECKS = 1")

注意事项

  1. dbcleaner 主要用于测试环境,不要在生产环境中使用
  2. 清理操作会删除表中的所有数据,请确保你操作的是测试数据库
  3. 对于大型表,清理操作可能会比较耗时,考虑在测试中使用内存数据库或模拟(mock)

通过合理使用 dbcleaner,你可以确保每个测试用例都在干净的数据库状态下运行,避免测试之间的相互干扰。

回到顶部