集成测试(或系统测试)通常意味着有一个填充有数据的数据库,如redis、elasticsearch等,通常,我们的软件与之交互的任何基础设施都可以工作。最常见的方式是复制我们的生产基础设施,用容器实现起来相对容易,比如docker容器。我们可以为每个需要复制的服务设置和运行一个容器,我们可以使用docker-compose来编排它并创建一些makefile或只是一个简单的脚本来准备基础设施和运行集成测试。如果您的测试是独立的(它们应该是),您将必须找到在测试之间“重启”基础设施服务的方法,这很难通过单独的基础设施设置和测试(基础设施在脚本中设置),和Go文件中的测试)01dockertest如果你正在使用Go,你可以使用dockertest,一个可以在Go测试文件中管理和编排容器的库。从Go文件管理测试基础设施容器,允许我们控制每个测试中我们需要的服务(例如,一些包正在使用数据库而不是Redis,并且为这个测试运行Redis没有意义)安装dockertest要安装dockertest,只需运行:goget-ugithub.com/ory/dockertest/v3使用dockertest使用dockertest设置基础设施的最简单方法是在测试文件的TestMain函数中添加设置代码。TestMain是在包中运行测试之前调用的函数,更多信息在这里。这是如何使用dockertest设置MySQL服务的示例:packagemypackage_testimport("database/sql""fmt""log""os""testing"_"github.com/go-sql-driver/mysql""github.com/ory/dockertest/v3")vardb*sql.DBfuncTestMain(m*testing.M){//usesasensibledefaultonwindows(tcp/http)andlinux/osx(socket)pool,err:=dockertest.NewPool("")iferr!=nil{log.Fatalf("Couldnotconnecttodocker:%s",err)}//pullsanimage,createsacontainerbasedonitandrunsitresource,err:=pool.Run("mysql","5.7",[]string{"MYSQL_ROOT_PASSWORD=secret"})iferr!=nil{log.Fatalf("Couldnotstartresource:%s",err)}//指数回退-重试,因为容器中的应用程序可能还没有准备好接受连接syetiferr:=pool.Retry(func()error{varerrerrordb,err=sql.Open("mysql",fmt.Sprintf("root:secret@(localhost:%s)/mysql",resource.GetPort("3306/tcp")))iferr!=nil{returnerr}returndb。Ping()});err!=nil{log.Fatalf("Couldnotconnecttodocker:%s",err)}//RESERVEDFORDATABASEMIGRATIONScode:=m.Run()//你不能推迟这个因为os.Exit不关心deferiferr:=pool.Purge(resource);err!=nil{log.Fatalf("Couldnotpurgeresource:%s",err)}os.Exit(code)}填充数据库,现在我们有可用的数据库服务,但这个数据库是空的dockertest正在用于容器通用MySQL映像,与我们的应用程序无关。我之前写过一篇关于数据库迁移的文章,在那篇文章中,我谈到了go-migrate,一个运行数据库迁移的工具,那篇文章,我专注于将它用作CLI工具,现在将在我们的Go代码中使用它.我们将之前编写的代码添加到此代码中//RESERVEDFORDATABASEMIGRATIONS:m,err:=migrate.NewWithDatabaseInstance("file://
