Поднятие Docker контейнеров в тестах с Go и Dockertest

Для запуска интеграционных тестов в Golang часто требуются внешние зависимости в виде базы данных, брокера сообщений либо еще каких-то сторонних компонентов.В итоге для поднятия внешних сервисов мы используем Docker и пишем docker-compose.yml файл который выглядит как-то так:

version: '3'
services:
  db:
    image: postgres:10.6-alpine
    ports:
      - '5432'
    environment:
      LC_ALL: C.UTF-8
      POSTGRES_DB: test
      POSTGRES_USER: test
      POSTGRES_PASSWORD: pass

Далее до запуска go test мы делаем docker-compose up -d.

Все вроде здорово и все работает, но что если мы будем запускать нужные нам контейнеры прямо в наших тестах? А после завершения мы будем все очищать. И все это без yaml и утилиты docker-compose.

Это возможно при помощи библиотеки https://github.com/ory/dockertest

package main

import (
	"fmt"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"github.com/ory/dockertest"
	"log"
)

func main() {
	pool, err := dockertest.NewPool("")
	if err != nil {
		log.Fatalf("Could not connect to docker pool: %s", err)
	}

	// pulls an image, creates a container based on it and runs it
	resource, err := pool.Run("postgres", "10.6-alpine", []string{"POSTGRES_DB=test", "POSTGRES_USER=test", "POSTGRES_PASSWORD=pass"})
	if err != nil {
		log.Fatalf("Could not start resource: %s", err)
	}

	if err := pool.Retry(func() error {
		var err error
		dsnString := "postgres://test:[email protected]:" + resource.GetPort("5432/tcp") + "/test?sslmode=disable"
		db, err := sqlx.Connect("postgres", dsnString)
		if err != nil {
			return err
		}
		return db.Ping()
	}); err != nil {
		log.Printf("Could not connect to docker resource: %s", err)
	}

	fmt.Println(" Image port: " + resource.GetPort("5432/tcp"))

	if err := pool.Purge(resource); err != nil {
		log.Fatalf("Could not purge resource: %s", err)
	}
}

Что делает наш код? В начале поднимает dockertest pool и запускает нужный нам контейнер при помощи pool.Run:

resource, err := pool.Run("postgres", "10.6-alpine", []string{"POSTGRES_DB=test", "POSTGRES_USER=test", "POSTGRES_PASSWORD=pass"})

Далее наша программа ждет пока контейнер не будет готов к работе при помощи метода pool.Retry и когда все готово просто показывает на каком порту работает наш Postgres:

resource.GetPort("5432/tcp")

Итого данный кусок кода можно поместить в начало и последнюю часть в конец работы наших тестов.

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *