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

Было ли тестовое покрытие больше 80% на проектах

1.0 Junior🔥 71 комментариев
#Опыт и софт-скиллы#Тестирование

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

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

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

Тестовое покрытие на проектах: подход и практика

На проектах, где я работал, целевой показатель покрытия в 80% и более действительно часто фигурировал в требованиях к качеству кода, особенно в зрелых, долгосрочных продуктах в сферах финтеха, стриминга и крупных корпоративных приложений. Однако важно понимать, что сама по себе цифра в 80% — это не самоцель, а инструмент метрики, и ее достижение было результатом продуманной стратегии, а не формального "накручивания" процентов.

Стратегия достижения высокого покрытия

Простое требование "добиться 80%" без четкой стратегии ведет к написанию бесполезных тестов. На успешных проектах мы действовали системно:

  1. Приоритизация по критичности и сложности. Первыми покрывались тестами:
    *   **Бизнес-логика ядра приложения** (расчеты, преобразования данных, состояния).
    *   **Модули, подверженные частым изменениям** (это страховка от регрессий).
    *   **Сложные алгоритмы и цепочки преобразований данных**.
    *   **Public API модулей и библиотек**, используемых другими командами.

  1. Использование модульных (Unit) и интеграционных (Integration) тестов как основы. Именно они дают основной вклад в процент покрытия и максимальную скорость обратной связи.

    // Пример юнит-теста для ViewModel с использованием Coroutines Test
    class UserProfileViewModelTest {
        @Test
        fun `loadUserProfile should update state to Success on repository success`() = runTest {
            // Arrange
            val mockUser = User(id = 1, name = "Test")
            val mockRepository = FakeUserRepository().apply {
                userToReturn = mockUser
            }
            val viewModel = UserProfileViewModel(mockRepository)
    
            // Act
            viewModel.loadUserProfile(1)
    
            // Assert
            val state = viewModel.uiState.first()
            assertThat(state).isInstanceOf(UserProfileState.Success::class.java)
            assertThat((state as UserProfileState.Success).user).isEqualTo(mockUser)
        }
    }
    
  2. Умное игнорирование нерелевантного кода. С помощью аннотаций в JaCoCo мы исключали из отчетов:

    *   Сгенерированный код (Data Binding, Dagger).
    *   Чисто UI-классы (Activity, Fragment, простые адаптеры), логика которых вынесена в ViewModel/Presenter.
    *   Модели данных (data class), состоящие только из полей и автоматических методов.

```kotlin
// Пример: логика вынесена из Fragment, что позволяет ее протестировать
// Сам Fragment можно исключить из отчетов покрытия
class CatalogViewModel @Inject constructor(
    private val loadProductsUseCase: LoadProductsUseCase
) : ViewModel() {
    // Эта бизнес-логика покрывается юнит-тестами
    fun onCategorySelected(categoryId: String) {
        viewModelScope.launch {
            _state.value = State.Loading
            val result = loadProductsUseCase(categoryId)
            _state.value = when (result) {
                is Result.Success -> State.Content(result.data)
                is Result.Error -> State.Error(result.exception.message)
            }
        }
    }
}
```

Организационные практики, которые помогали

  • CI/CD как gatekeeper. В GitLab CI/CD или Jenkins этап сборки с запуском тестов и проверкой покрытия был обязательным. Падение покрытия ниже порога (например, с 82% до 78%) могло блокировать мерж пул-реквеста в основную ветку. Это дисциплинировало команду.
  • Визуализация и регулярный мониторинг. Интеграция JaCoCo в процесс сборки с генерацией HTML-отчетов, которые можно было изучить. Мы проводили регулярные обзоры, выявляя непокрытые, но важные участки кода.
  • Культура "тесты прежде всего" (TDD в отдельных потоках). Для ключевых фич или рефакторинга критически важных модулей мы практиковали Test-Driven Development. Это сразу давало высокое покрытие и более чистый дизайн кода.

Вывод: баланс метрики и здравого смысла

Таким образом, да, на многих проектах мы поддерживали стабильное покрытие выше 80%. Но эта цифра была следствием, а не причиной. Ключевыми были:

  1. Осмысленное тестирование важной логики, а не гонка за процентами.
  2. Автоматизированная проверка покрытия в контуре CI/CD.
  3. Гибкая настройка инструментов (JaCoCo) для исключения из метрик кода, который не имеет смысла тестировать юнит-тестами.

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

Было ли тестовое покрытие больше 80% на проектах | PrepBro