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

Какой уровень покрытия тестами установлен в твоей команде?

2.0 Middle🔥 121 комментариев
#Основы Go

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

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

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

Уровень покрытия тестами в команде: Практический подход

В нашей команде мы придерживаемся философии "качество важнее формальных метрик", но при этом используем покрытие кода тестами (code coverage) как один из инструментов мониторинга качества, а не как самоцель. Мы стремимся к осмысленному покрытию (meaningful coverage), а не просто к достижению магических цифр.

Текущие метрики и практики

Обычно мы поддерживаем:

  • 80-90% покрытия по строкам кода для критического бизнес-логического слоя (сервисы, обработчики, важные утилиты)
  • 70-80% для инфраструктурного кода (репозитории, клиенты внешних API)
  • Более низкие требования к generated коду, мокам и простым DTO

Важно: мы используем покрытие как "маяк", а не как жесткое требование. PR с 95% покрытием, но с бессмысленными тестами, не будет принят.

Как мы измеряем и обеспечиваем покрытие

Мы используем встроенные инструменты Go и CI/CD пайплайн:

# Запуск тестов с измерением покрытия
go test ./... -coverprofile=coverage.out -covermode=atomic

# Генерация отчета
go tool cover -html=coverage.out -o coverage.html

# Проверка покрытия в CI (пример скрипта)
if go test ./... -coverprofile=coverage.out -covermode=atomic; then
    COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print substr($3, 1, length($3)-1)}')
    echo "Current coverage: ${COVERAGE}%"
    if (( $(echo "$COVERAGE < 80" | bc -l) )); then
        echo "ERROR: Coverage below 80% threshold"
        exit 1
    fi
fi

Наша стратегия тестирования включает:

  1. Многоуровневый подход:

    • Юнит-тесты для изолированной логики (70% всех тестов)
    • Интеграционные тесты для проверки взаимодействия компонентов (20%)
    • E2E-тесты для критических пользовательских сценариев (10%)
  2. Акцент на качестве тестов:

    • Проверяем пограничные случаи (edge cases)
    • Тестируем ошибки и восстановление (error paths)
    • Используем table-driven tests для комплексного покрытия сценариев
// Пример table-driven теста в Go
func TestCalculateDiscount(t *testing.T) {
    tests := []struct {
        name          string
        userType      string
        purchaseSum   float64
        expectedDiscount float64
        expectedError error
    }{
        {"Regular user small purchase", "regular", 100.0, 0.0, nil},
        {"VIP user large purchase", "vip", 1000.0, 100.0, nil},
        {"Invalid user type", "unknown", 500.0, 0.0, ErrInvalidUserType},
        {"Edge case zero purchase", "regular", 0.0, 0.0, nil},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            discount, err := CalculateDiscount(tt.userType, tt.purchaseSum)
            if err != tt.expectedError {
                t.Errorf("unexpected error: got %v, want %v", err, tt.expectedError)
            }
            if discount != tt.expectedDiscount {
                t.Errorf("discount mismatch: got %.2f, want %.2f", discount, tt.expectedDiscount)
            }
        })
    }
}
  1. Исключения из правил:
    • Код, который тривиально прост (геттеры/сеттеры без логики)
    • Main-функции и точки входа
    • Временно исключенные модули (с обязательным комментарием и планом исправления)

Инструменты и процессы

  • go test + cover для базового измерения
  • SonarQube для анализа качества (включая покрытие веток)
  • Git hooks с pre-commit проверками
  • Code review с обязательной проверкой тестов
  • Покрытие веток (branch coverage) для критической логики

Почему мы не гоняемся за 100% покрытием

  1. Закон убывающей отдачи - после 85-90% стоимость каждого нового процента резко возрастает
  2. Ложное чувство безопасности - 100% покрытие не гарантирует отсутствие багов
  3. Сложность поддержки - чрезмерное количество тестов замедляет разработку
  4. Невозможность покрыть всё - некоторые сценарии (сетевые сбои, race conditions) сложно надежно тестировать

Критерии успеха вместо формальных цифр

Мы считаем тестирование успешным, когда:

  • Количество регрессий в production снижается
  • Разработчики уверенно рефакторят код
  • Новые тесты выявляют реальные проблемы до мержа
  • Скорость разработки не падает из-за тестов

Вывод: Наше целевое покрытие 80-90% - это баланс между качеством кода и скоростью разработки. Мы постоянно пересматриваем этот порог, исходя из проекта, его стадии и критичности домена. Главное - чтобы тесты были осмысленными, поддерживаемыми и действительно улучшали качество продукта, а не просто "галочкой" в отчете.

Какой уровень покрытия тестами установлен в твоей команде? | PrepBro