偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

在 Go 中使用 Dockertest 進(jìn)行集成測(cè)試

開發(fā) 后端
進(jìn)行集成測(cè)試(或系統(tǒng)測(cè)試)通常意味著讓數(shù)據(jù)庫填充數(shù)據(jù),像 redis、elasticsearch 等,通常,我們的軟件與之交互的任何基礎(chǔ)設(shè)施都可以工作。

[[437314]]

進(jìn)行集成測(cè)試(或系統(tǒng)測(cè)試)通常意味著讓數(shù)據(jù)庫填充數(shù)據(jù),像 redis、elasticsearch 等,通常,我們的軟件與之交互的任何基礎(chǔ)設(shè)施都可以工作。

最常見的方法是復(fù)制我們的生產(chǎn)基礎(chǔ)設(shè)施,其實(shí)用容器來實(shí)現(xiàn)還是比較容易的,比如 docker 容器。

我們可以為需要復(fù)制的每個(gè)服務(wù)設(shè)置和運(yùn)行一個(gè)容器,我們可以使用 docker-compose 對(duì)其進(jìn)行編排并創(chuàng)建一些 makefile 或只是一個(gè)簡(jiǎn)單的腳本來準(zhǔn)備基礎(chǔ)設(shè)施并運(yùn)行集成測(cè)試。

如果你的測(cè)試是獨(dú)立的(它們應(yīng)該是獨(dú)立的),你必須找到在測(cè)試之間“重新啟動(dòng)”基礎(chǔ)設(shè)施服務(wù)的方法,這可能很難通過分離的基礎(chǔ)設(shè)施設(shè)置和測(cè)試來實(shí)現(xiàn)(基礎(chǔ)設(shè)施是在腳本中設(shè)置的,而測(cè)試在 Go 文件中)

01 dockertest

如果你使用的是 Go,則可以使用 dockertest,一個(gè)可以管理和編排 Go 測(cè)試文件中的容器的庫。

從 Go 文件管理測(cè)試基礎(chǔ)設(shè)施容器,允許我們控制在每個(gè)測(cè)試中需要的服務(wù)(例如,某些包正在使用數(shù)據(jù)庫而不是 Redis,為這個(gè)測(cè)試運(yùn)行 Redis 沒有意義)

安裝 dockertest

要安裝 dockertest,只需運(yùn)行:

  1. go get -u github.com/ory/dockertest/v3 

使用 dockertest

使用 dockertest 設(shè)置基礎(chǔ)設(shè)施的最簡(jiǎn)單方法是在測(cè)試文件的TestMain 函數(shù)中添加設(shè)置代碼。

TestMain 是在包中運(yùn)行測(cè)試之前調(diào)用的函數(shù),更多信息參考這里。

這是如何使用 dockertest 設(shè)置 MySQL 服務(wù)的示例:

  1. package mypackage_test 
  2.  
  3. import ( 
  4.  "database/sql" 
  5.  "fmt" 
  6.  "log" 
  7.  "os" 
  8.  "testing" 
  9.  
  10.  _ "github.com/go-sql-driver/mysql" 
  11.  "github.com/ory/dockertest/v3" 
  12.  
  13. var db *sql.DB 
  14.  
  15. func TestMain(m *testing.M) { 
  16.  // uses a sensible default on windows (tcp/http) and linux/osx (socket) 
  17.  pool, err := dockertest.NewPool(""
  18.  if err != nil { 
  19.   log.Fatalf("Could not connect to docker: %s", err) 
  20.  } 
  21.  
  22.  // pulls an image, creates a container based on it and runs it 
  23.  resource, err := pool.Run("mysql""5.7", []string{"MYSQL_ROOT_PASSWORD=secret"}) 
  24.  if err != nil { 
  25.   log.Fatalf("Could not start resource: %s", err) 
  26.  } 
  27.  
  28.  // exponential backoff-retry, because the application in the container might not be ready to accept connections yet 
  29.  if err := pool.Retry(func() error { 
  30.   var err error 
  31.   db, err = sql.Open("mysql", fmt.Sprintf("root:secret@(localhost:%s)/mysql", resource.GetPort("3306/tcp"))) 
  32.   if err != nil { 
  33.    return err 
  34.   } 
  35.   return db.Ping() 
  36.  }); err != nil { 
  37.   log.Fatalf("Could not connect to docker: %s", err) 
  38.  } 
  39.  
  40.   // RESERVED FOR DATABASE MIGRATIONS 
  41.  code := m.Run() 
  42.   
  43.  // You can't defer this because os.Exit doesn't care for defer 
  44.  if err := pool.Purge(resource); err != nil { 
  45.   log.Fatalf("Could not purge resource: %s", err) 
  46.  } 
  47.   
  48.  os.Exit(code) 

填充數(shù)據(jù)庫

現(xiàn)在我們有工作的數(shù)據(jù)庫服務(wù),但這個(gè)數(shù)據(jù)庫是空的。dockertest 正在為容器使用通用 MySQL 映像,并且沒有與我們的應(yīng)用程序相關(guān)的任何內(nèi)容。

之前寫了一篇關(guān)于 數(shù)據(jù)庫遷移,在那篇文章中,我談到了 go-migrate,一個(gè)運(yùn)行數(shù)據(jù)庫遷移的工具,那篇文章,我專注于作為 CLI 工具使用,現(xiàn)在將在我們的 Go 代碼中使用它。

我們將先前編寫的代碼 // RESERVED FOR DATABASE MIGRATIONS 添加到此代碼中:

  1. m, err := migrate.NewWithDatabaseInstance("file://<path-to-migration-folder>, "mysql", driver) 
  2. if err != nil { 
  3.     log.Fatalf("Error running migrations: %s", err) 
  4. err = m.Up() 
  5. if err != nil { 
  6.     log.Fatal(err.Error()) 

然后在 dockertest up 數(shù)據(jù)庫后,遷移工具填充數(shù)據(jù)庫,我們的集成測(cè)試可以使用數(shù)據(jù)庫中的相同數(shù)據(jù)運(yùn)行。

如果應(yīng)用程序有多個(gè)包(這是常見情況),我會(huì)將服務(wù)的設(shè)置代碼放在一個(gè)獨(dú)立文件中,該文件在每個(gè)包中調(diào)用:

  1. // it_utils.go 
  2. package it_utils 
  3.  
  4. func IntegrationTestSetup() (*dockertest.Pool, *[]dockertestResource { 
  5.   // Setup the services 
  6.   //return the pool and the resources 
  7.  
  8. func IntegrationTestTeardown(pool *dockertest.Pool, resources []*dockertest.Resource) { 
  9.  for _, resource := range resources { 
  10.   if err := pool.Purge(resource); err != nil { 
  11.    fmt.Printf("Could not purge resource: %s\n", err) 
  12.   } 
  13.  } 

那么在每個(gè)包的測(cè)試中我們只需要添加如下代碼:

  1. package my_package 
  2.  
  3. func TestMyTests (t *testing.T) { 
  4.     if testing.Short() { 
  5.   t.Skip() 
  6.  } 
  7.  pool, resources := itutils.IntegrationTestSetup() 
  8.  defer itutils.IntegrationTestTeardown(pool, resources) 
  9.   
  10.  t.Run("your test", func(t *testing.T) { 
  11.  ... 
  12.  } 
  13.  
  14. func TestOtherTests (t *testing.T) { 
  15.     if testing.Short() { 
  16.   t.Skip() 
  17.  } 
  18.  pool, resources := itutils.IntegrationTestSetup() 
  19.  defer itutils.IntegrationTestTeardown(pool, resources) 
  20.   
  21.  t.Run("your other test", func(t *testing.T) { 
  22.  ... 
  23.  } 

以這種方式在每個(gè)測(cè)試塊上執(zhí)行此操作,服務(wù)在新容器中運(yùn)行,從而使測(cè)試完全獨(dú)立。

作為最后一個(gè)提示,我建議將集成測(cè)試放在不同的包中以避免循環(huán)導(dǎo)入。

原文鏈接:https://sergiocarracedo.es/integration-tests-in-golang-with-dockertest/

本文轉(zhuǎn)載自微信公眾號(hào)「幽鬼」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系幽鬼公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: 幽鬼
相關(guān)推薦

2023-10-28 16:22:21

Go接口

2023-11-27 19:39:46

Goprotobuf

2009-06-22 10:29:11

集成測(cè)試Spring

2009-06-08 20:04:06

EclipseJUnit4單元測(cè)試

2009-06-08 19:59:09

EclipseJUnit單元測(cè)試

2009-06-08 19:57:29

EclipseJUnit4單元測(cè)試

2024-02-07 11:44:20

NestJSRxJS異步編程

2011-12-08 10:24:53

JavaNIO

2023-10-13 18:02:57

JUnitMockito關(guān)系

2019-12-12 13:50:27

strace追蹤系統(tǒng)調(diào)用Linux

2023-05-24 16:41:41

React前端

2024-05-06 13:34:28

WireGoogleGo

2021-01-05 08:39:51

容器前端流水線

2021-09-21 15:44:02

LinuxOBSWayland

2021-02-20 09:14:35

PythonPygal可視化

2022-01-03 08:06:15

函數(shù)Go數(shù)據(jù)

2024-08-19 01:10:00

RedisGo代碼

2022-11-03 20:38:01

CMD命令Go

2010-06-23 15:21:45

SharepointExchange

2013-01-07 13:54:17

Android開發(fā)JUnit單元測(cè)試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)