Перейти на тестирование

Интеграционный тест Golang с MySQL

Тест интеграции с testify Suite, уверен, он вам понадобится ...

Когда вы создаете приложение go и развертываете его без тестирования, вы часто обнаруживаете ошибку в своем коде. Не рекомендуется развертывать непроверенный код. Обычно в веб-разработке существует 3 типа тестирования:

  • Модульное тестирование - это тестирование самых маленьких модулей по отдельности, или мы можем сказать, что мы тестируем каждую функцию. Обычно тестируется разработчиком или CI (непрерывная интеграция), это самый дешевый и простой из трех тестов. Объем этого теста довольно велик.
  • Интеграционный тест отвечает за объединение некоторых разделов нашего приложения, которые являются частью потока нашей программы, и за обеспечение правильного взаимодействия между разделами. Например, поток регистрации пользователей. Пользователи не могут зарегистрировать 2 повторяющихся письма и т. Д.
  • Функциональный тест - это последний тест перед развертыванием кода в реальной среде, это работа по обеспечению качества и, конечно же, этот тест стоит больше всего денег и времени.

В этой статье мы протестируем Integration Test с нашим кодом базы данных Go-MySQL.

Требование

Достаточно некоторых основ программирования на Go. Для маршрутизатора http вы можете использовать net/http, я предпочитаю gin из-за функции.

Мы будем использовать testify, чтобы помочь нам с тестированием позже, а GORM - это библиотека go-ORM для базы данных SQL, которая поможет нам с запросом к базе данных.

Репозиторий: https://github.com/david-yappeter/go-mysql-suite

Начать

Инициализируйте модуль go.

$ mkdir go-mysql-suite && cd go-mysql-suite && go mod init myapp

Каталог и файлы нашего проекта в итоге будут выглядеть так.

.
├── config
│   └── gorm.go
├── controllers
│   └── user.go
├── entity
│   └── user.go
└── migrations
│   ├── migration.go
├── service
│   └── user.go
└── tests
│   ├── suite_test.go
│   └── user_test.go
├── .env
├── go.mod
├── go.sum
└── server.go

Сначала напишем наш server.go

server.go

func init() будет вызываться первым перед main() start, он загрузит .env config, когда мы запустим программу. Затем мы вызываем config.ConnectGorm(), чтобы инициализировать соединение с базой данных, мы напишем код позже, и мы вызываем defer sqlDB.Close(), чтобы закрыть соединение с базой данных после остановки нашего кода.

Здесь мы предоставим 2 основных конечных точки: /users (GET), /users (POST), первая - для получения массива пользователей, а вторая - для создания пользователя. Контроллер будет инициализирован позже внутри controllers/user.go.

Далее мы перейдем к config/gorm.go

config/gorm.go

В этом файле мы инициализируем глобальную переменную db *gorm.DB, в которой хранится наш пул базы данных, и ConnectGorm() вызывается в server.go и присваивает значение db при выполнении кода. Нашим получателем будет GetDB(), который вернет значение db.

Остальные функции initConfig(), initLog(), initNamingStrategy - это просто конфиг GORM.

Затем мы создадим нашу User сущность в entity/user.go

entity/user.go

Мы создадим простого пользователя, чтобы сделать CRUD короче. Тег binding предназначен для gin связующего позже, а тег gorm поможет нам при миграции модели.

Перейдем к controllers

controller/user.go

В нашем контроллере User есть глобальная переменная UserController, которая будет вызываться в server.go и содержать 2 функции Create и GetAll. Функция будет получать / создавать пользовательские данные из модуля service, который мы создадим позже.

Для service мы создадим 3 функции UserCreate, UserGetAll, UserGetByEmail

service/user.go

Мы будем использовать github.com/google/uuid для хеширования user.ID при вставке данных в базу данных, а UserGetAll вернет всех пользователей из базы данных. И, конечно же, нам нужно будет проверить, использовалось ли электронное письмо раньше или нет, прежде чем вставлять данные.

Наконец, нам нужно сделать migrations перед прыжком в testing.

migrations/migration.go

migration прост, вам просто нужно вызвать db.AutoMigrate вместе со всеми моделями, которые нужно перенести.

.env будет содержать эту конфигурацию, измененную в соответствии с вашими

DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASS=
DB_DATABASE=go_mysql_suite

Этот код уже работает нормально, но мы создадим тест отсюда.

Suite Test

tests/suite_test.go

suite.Suite из testify предоставьте нам 4 interface, которые мы можем использовать: SetupTest, TearDownTest, SetupSuite, TearDownSuite.

  • SetupSuite будет запущен первым для инициализации необходимых данных Suite.
  • TearDownSuite запустится последним, после того, как все тесты пройдены.
  • SetupTest будет запущен перед тестом.
  • TearDownTest запустится после теста.

Функция TestSuite запустит тест, и имя функции должно начинаться с Test (префикс).

Мы инициализируем соединение с базой данных и миграцию в SetupSuite, а затем закрываем соединение и удаляем все таблицы в TearDownSuite. Мы устанавливаем нашу тестовую среду, используя os.SetEnv, а затем os.Unsetenv, чтобы избежать перезаписи конфигурации в нашем сеансе терминала.

Далее следует, как провести тест с созданным нами suite.

tests/user_test.go

Префикс каждой тестовой функции ДОЛЖЕН начинаться с Test, внутри тестов мы можем вызвать нашу службу и создать поток, например, мы создаем пользователя с [email protected], а затем с [email protected]. Конечно, мы ожидаем NoError, поэтому мы будем использовать testify подмодуль с именем assert, который помогает нам с условным assert.NoError, assert.Error и т. Д.

Когда мы пытаемся вставить третьего пользователя с [email protected], мы ожидаем ошибки от этой функции, потому что адрес электронной почты был найден в базе данных.

Попробуем запустить тест.

$ go test ./tests
My Output:
ok      myapp/tests     0.245s
// Verbose
$ go test -v ./tests
My Output (Verbose):
=== RUN   TestSuite
--- PASS: TestSuite (0.16s)
    --- PASS: TestSuite/TestCreateUser (0.02s)
PASS
ok      myapp/tests     0.293s
PS D:\go\src\go-mysql-suite> go test ./tests
ok      myapp/tests     0.245s
PS D:\go\src\go-mysql-suite> go test -v ./tests
=== RUN   TestSuite
=== RUN   TestSuite/TestCreateUser
--- PASS: TestSuite (0.16s)
    --- PASS: TestSuite/TestCreateUser (0.02s)
PASS
ok      myapp/tests     (cached)

Выводы

Неплохо иметь тест в вашем коде, может быть, вам потребовалось достаточно времени, чтобы написать тест. Но поверьте мне, это поможет вам в дальнейшем, сэкономит ваше время и энергию, которые нужно перепроверять каждый раз перед развертыванием. И что самое приятное, вы можете включить go test в CI / CD.

На этом все, желаю удачного дня :).