githubEdit

Coupling и Cohesion

Coupling (связность между модулями) и Cohesion (сплочённость внутри модуля) — принципы из проектирования ПО, которые напрямую влияют на тестируемость кода. Высокое coupling делает unit-тесты дорогими: изолировать модуль сложно, тест тянет за собой дюжину зависимостей. Низкое cohesion усложняет определение границ компонента: непонятно, что именно тестировать. Понимание этих концепций помогает QA-инженеру оценивать архитектурные решения и вносить предложения по улучшению тестируемости.

Определение

Coupling (связность) — мера степени взаимозависимости между модулями. Хорошее ПО стремится к низкому coupling: модули взаимодействуют через чёткие интерфейсы, а не через прямые вызовы внутренностей.

Cohesion (сплочённость) — мера того, насколько элементы модуля функционально связаны друг с другом. Хорошее ПО стремится к высокому cohesion: каждый модуль делает одну вещь хорошо.

Правило: Low coupling + High cohesion = тестируемый, поддерживаемый код.

Виды Coupling (от лучшего к худшему)

Data Coupling

Модули взаимодействуют, передавая только необходимые данные через параметры. Лучший вид связности — легко мокировать в тестах.

Stamp Coupling

Передаётся полная структура данных, хотя нужна только её часть. Приводит к тому, что тест должен конструировать лишний контекст.

Control Coupling

Один модуль управляет поведением другого через флаги/параметры. Тест вынужден проверять различные ветки поведения через один метод.

External Coupling

Зависимость от внешнего протокола, формата файла, устройства. Сложно тестировать без интеграционного окружения.

Common Coupling

Модули разделяют глобальное состояние (глобальные переменные, синглтоны). В тестах — источник flaky-тестов при параллельном запуске.

Content Coupling

Один модуль изменяет внутренние данные другого. Самый плохой вид — делает изолированное тестирование практически невозможным.

Виды Cohesion (от лучшего к худшему)

Functional Cohesion

Все элементы модуля направлены на выполнение одной задачи. Идеально для тестирования: один модуль — один набор тест-кейсов с чёткой областью ответственности.

Sequential Cohesion

Вывод одного элемента — вход для другого. Характерно для pipeline-обработки данных.

Communicational Cohesion

Элементы работают с одними входными данными или создают одни выходные. Пример: обновить запись в БД и отправить её на принтер.

Procedural Cohesion

Элементы обеспечивают порядок выполнения операций, слабо связанных по смыслу.

Temporal Cohesion

Элементы выполняются в один промежуток времени (например, инициализация). Тест вынужден покрывать несвязанную функциональность в одном тесте.

Logical Cohesion

Элементы связаны логически, но не функционально (например, «все операции ввода»).

Coincidental Cohesion

Элементы не имеют никакой концептуальной связи. Худший вариант — тест не имеет чёткого назначения.

Влияние на тестируемость

Проблема в коде
Следствие для тестирования

Высокое coupling (Common/Content)

Unit-тест требует инициализации множества зависимостей; flaky при параллельном запуске

Низкое cohesion (Coincidental)

Непонятно что тестировать; тест-кейсы перекрываются

Зависимость от глобального состояния

Тесты не независимы; порядок запуска влияет на результат

Жёсткие зависимости (new Object() внутри)

Невозможно подставить мок — нужен рефакторинг на DI

Что делать, если код плохо тестируется

Если для написания unit-теста нужно поднять три сервиса и заполнить семь полей — это сигнал архитектурной проблемы. QA может:

  • Зафиксировать как архитектурный долг

  • Писать subcutaneous тесты или integration тесты вместо unit

  • Предложить рефакторинг через Dependency Injection

Источники

Дополнительные материалы

Last updated