TGViewer
Валерий | AQA Engineer | Автотестирование на Python | REST, gRPC, GraphQL Валерий | AQA Engineer | Автотестирование на Python | REST, gRPC, GraphQL @aqa_engineer · 1.52K subscribers
Post #430 1.04K
#solid
📌 D – Dependency Inversion Principle (DIP)
Принцип инверсии зависимостей

“Зависимости должны быть от абстракций, а не от конкретных реализаций.”

В DIP помогает строить гибкие, легко тестируемые и переиспользуемые компоненты.
Особенно когда нужно подменить авторизацию, логирование, сделать allure-разметку или сбор coverage

В чём суть?

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

🧪 Пример: плохая реализация (без DIP)

Скажу честно, сам я тоже когда-то грешил завязываясь на конкретную реализацию клиента, в данном случае requests.Session()

class ApiClient:
def __init__(self):
self.session = requests.Session()

def get_user(
self,
user_id
) -> dict:
response = self.session.get(
f"{API_URL}/user/{user_id}"
)
return response.json()


Проблемы:
• Жёсткая зависимость от requests, если мы захотим использовать, например httpx, мы не сможем этого сделать без изменения кода.
• Нельзя замокать поведение в тесте
• Нарушен DIP: клиент зависит от деталей

✅ Как сделать правильно (с применением DIP)
То есть говорим какие методы обязательно должны быть у принимаемого на вход клиента.
В Python нет интерфейсов в классическом понимании, поэтому abc.ABC и @abstractmethod — это абстрактные классы, которые эмулируют интерфейсы.

1. Вводим интерфейсы:
from abc import ABC, abstractmethod

class BaseHttpClient(ABC):
@abstractmethod
def get(
self,
url: str,
**kwargs: Any
) -> dict:
pass


2. Реализация:

Наследуемся и описываем методы соблюдая контракт, "контракт" — это обязательство реализовать методы, объявленные в абстракции (BaseHttpClient).

При соблюдении этих правил, любой клиент, который соблюдает контракт, может быть безболезнено (в идеале) использован.

class HttpClient(BaseHttpClient):
def get(
self,
url: str,
**kwargs: Any
) -> dict:
return requests.get(url, **kwargs).json()


3. Внедряем зависимости:

То есть любой наследник BaseHttpClient не должен поломать код.
class ApiClient:
def __init__(
self,
http_client: BaseHttpClient
):
self.http_client = http_client

def get_user(self, user_id, headers) -> dict:
return self.http_client.get(
f"{API_URL}/user/{user_id}",
headers=headers,
).json()


🧪 Теперь в тесте:

# Мы можем или замокать клиент тем самым написать тест без реального апи
class MockHttpClient(BaseHttpClient):
def get(self, url, headers):
return {"id": 123, "name": "Test User"}

def test_get_user():
client = ApiClient(MockHttpClient())
user = client.get_user(123)
assert user["id"] == 123


# Можем добавить свою логику, например логгирование запроса
class LoggedHttpClient(BaseHttpClient):
def get(
self,
url,
headers
) -> dict:
print(url, headers)
response = self.http_client.get(
url,
headers=headers
)
print(response.text)
return response.json()


# И здесь тест уже будет с логами
def test_get_logged_user():
client = ApiClient(LoggedHttpClient())
user = client.get_user(123)
assert user["id"] == 123


Профит:
• Подменили зависимости без боли
• Не нужен реальный backend для тестов
• Код клиента не меняется — только зависимости

DIP особенно полезен когда:
• Пишешь интеграционные и контрактные тесты
• Нужно мокать внешние сервисы
• В проекте много обвязки (логов, ретраев, токенов) — и ты хочешь это всё отделить
• Требуется расширяемость (добавить кеш, валидацию, другой http-клиент)

Вывод

Применение DIP в API‑тестах:
🔹 Упрощает подмену зависимостей
🔹 Повышает читаемость и тестируемость
🔹 Позволяет изолировать бизнес‑логику от инфраструктуры
🔹 Снижает связанность компонентов

🔥Перешли другу\коллеге пусть тоже знает)

На этом мы закрываем тему SOLID. )


——————————-

📱 TG-сообщество

📱 Обучение

📱 Отзывы
  • 🔥 5
  • ❤ 1
  • 👍 1
More from @aqa_engineer
  1. Sep 2, 2026💙💙💙💙💙 Маленькое напоминание о большой дате: где стоит провести День программиста⬆️ Ар…
  2. Sep 2, 2026Привет, давно меня не было пригар по работе, что совсем не успеваю ничего. За что прошу пр…
  3. Jul 16, 2026👩‍💻 В мае-июне я проходила курс «Автоматизация тестирования Rest API Advanced (Python)»…
  4. Jun 10, 2026Привет! Уже на следующей неделе у меня стартуют. Автоматизация тестирования брокеров сообщ…
  5. Jun 8, 2026Несколько месяцев назад я спросил, какой технический тренинг вам был бы действительно инте…
  6. Jun 6, 2026Материалы для тех, кто в теме. Одна из самых больших проблем при развитии в IT - это возмо…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →