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
Источники
Дополнительные материалы
Low Coupling и High Cohesion — краткое объяснение с примерами
ООП для ООП: GRASP — паттерны проектирования в контексте связности
Взгляд тестировщика на SOLID — как SOLID влияет на тестируемость
Last updated