← Назад к вопросам

Что такое интеграционные тесты?

1.0 Junior🔥 242 комментариев
#Тестирование

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Интеграционные тесты: концепция и практика в Go

Интеграционные тесты — это тип тестирования программного обеспечения, который проверяет взаимодействие между отдельными модулями, компонентами или системами. В отличие от юнит-тестов, которые изолированно тестируют отдельные функции или методы, интеграционные тесты фокусируются на корректности взаимодействия этих частей друг с другом и с внешними зависимостями (базами данных, API, брокерами сообщений и т.д.).

Ключевые цели интеграционного тестирования

  • Проверка взаимодействия компонентов: Убедиться, что отдельные модули правильно обмениваются данными и вызывают друг друга.
  • Валидация интеграции с внешними системами: Проверка работы с реальными или тестовыми базами данных, HTTP-сервисами, файловыми системами.
  • Обнаружение проблем на стыке модулей: Выявление ошибок, которые не проявляются на уровне единичных модулей (например, несоответствие форматов данных, ошибки сетевого взаимодействия).
  • Проверка корректности конфигурации: Убедиться, что компоненты правильно сконфигурированы для совместной работы.

Реализация в Go: примеры и подходы

В Go интеграционные тесты часто помечаются специальным тегов сборки (build tag), например //go:build integration. Это позволяет отделить их от быстрых юнит-тестов и запускать только по требованию.

Пример 1: Тестирование слоя доступа к данным (Repository)

//go:build integration

package repository_test

import (
    "context"
    "database/sql"
    "testing"
    "yourproject/internal/repository"
    "github.com/stretchr/testify/assert"
    _ "github.com/lib/pq" // Драйвер PostgreSQL
)

func TestUserRepository_CreateAndFind(t *testing.T) {
    // Подключение к тестовой БД (например, Docker-контейнер)
    db, err := sql.Open("postgres", "host=localhost port=5432 user=test dbname=testdb sslmode=disable")
    assert.NoError(t, err)
    defer db.Close()
    
    // Миграция схемы (можно использовать goose, golang-migrate и т.д.)
    runMigrations(db)
    
    // Создание репозитория
    repo := repository.NewUserRepository(db)
    ctx := context.Background()
    
    // Тестовый сценарий
    expectedUser := &repository.User{Name: "Alice", Email: "alice@example.com"}
    
    // Действие 1: Создание пользователя
    createdID, err := repo.Create(ctx, expectedUser)
    assert.NoError(t, err)
    assert.NotZero(t, createdID)
    
    // Действие 2: Поиск созданного пользователя
    foundUser, err := repo.FindByID(ctx, createdID)
    assert.NoError(t, err)
    assert.Equal(t, expectedUser.Name, foundUser.Name)
    assert.Equal(t, expectedUser.Email, foundUser.Email)
}

Пример 2: Тестирование HTTP-обработчика (Handler) с поднятым сервером

//go:build integration

package handlers_test

import (
    "bytes"
    "encoding/json"
    "net/http"
    "net/http/httptest"
    "testing"
    "yourproject/internal/app"
)

func TestUserHandler_CreateUser(t *testing.T) {
    // Инициализация приложения со всеми зависимостями (БД, роутинг)
    application := app.NewTestApp() // Метод, поднимающий тестовое окружение
    defer application.Cleanup() // Очистка после теста
    
    // Подготовка запроса
    userReq := map[string]string{"name": "Bob", "email": "bob@example.com"}
    body, _ := json.Marshal(userReq)
    req := httptest.NewRequest("POST", "/api/v1/users", bytes.NewReader(body))
    req.Header.Set("Content-Type", "application/json")
    
    // Запись ответа
    resp := httptest.NewRecorder()
    
    // Вызов обработчика через роутер
    application.Router.ServeHTTP(resp, req)
    
    // Проверки
    if resp.Code != http.StatusCreated {
        t.Errorf("Expected status 201, got %d", resp.Code)
    }
    
    var response map[string]interface{}
    json.Unmarshal(resp.Body.Bytes(), &response)
    if response["email"] != userReq["email"] {
        t.Errorf("Expected email %s, got %s", userReq["email"], response["email"])
    }
}

Практические рекомендации для Go-разработчиков

  • Используйте Docker для изоляции: Запускайте зависимости (PostgreSQL, Redis, Kafka) в контейнерах для предсказуемости тестов.
  • Применяйте фикстуры и сиды: Заранее заполняйте тестовую БД предопределёнными данными для воспроизводимости.
  • Очищайте состояние после тестов: Используйте t.Cleanup() или defer для удаления тестовых данных, чтобы тесты не влияли друг на друга.
  • Мокайте только неустойчивые зависимости: Внешние платежные шлюзы или почтовые сервисы лучше мокать, но свою БД — тестировать с реальным экземпляром.
  • Оптимизируйте время выполнения: Используйте транзакции для отката изменений вместо пересоздания всей БД.

Интеграционные тесты в Go занимают критически важную нишу между юнит-тестами и end-to-end тестированием. Они дают высокую уверенность в корректности взаимодействия компонентов, особенно при использовании реальных внешних систем. Ключевой вызов — поддерживать их стабильность и скорость выполнения, что достигается продуманной организацией тестового окружения и изоляцией тестовых сценариев.

Что такое интеграционные тесты? | PrepBro