Ответ
Юнит-тест (Unit Test) проверяет наименьшую изолированную часть кода (модуль, функцию, класс). Интеграционный тест (Integration Test) проверяет взаимодействие нескольких компонентов системы между собой.
| Критерий | Юнит-тесты | Интеграционные тесты |
|---|---|---|
| Цель | Проверить корректность логики одного модуля | Убедиться, что компоненты правильно работают вместе |
| Изоляция | Внешние зависимости (БД, API) заменяются моками | Используют реальные или тестовые зависимости (тестовая БД) |
| Скорость | Очень быстрые | Значительно медленнее |
| Область | Узкая, сфокусированная | Широкая, охватывает несколько слоев |
В пирамиде тестирования юнит-тесты составляют основу (их должно быть больше всего), а интеграционные тесты находятся на следующем уровне.
Пример юнит-теста (проверка одной функции):
# a_module.py
def is_strong_password(password: str) -> bool:
return len(password) >= 8 and any(c.isdigit() for c in password)
# test_a_module.py
def test_is_strong_password():
assert is_strong_password("password123") == True
assert is_strong_password("short") == False
assert is_strong_password("no_digits") == False
Пример интеграционного теста (проверка связки "сервис + БД"):
# user_service.py
class UserService:
def __init__(self, db_session):
self.db = db_session
def create_user(self, name):
user = User(name=name)
self.db.add(user)
self.db.commit()
return user
# test_user_service.py
def test_user_creation_in_db(test_db_session): # test_db_session - реальное подключение к тестовой БД
service = UserService(test_db_session)
user = service.create_user("John Doe")
# Проверяем, что пользователь действительно появился в базе данных
retrieved_user = test_db_session.query(User).filter_by(name="John Doe").one()
assert user.id == retrieved_user.id Ответ 18+ 🔞
Давай разберём эту хуйню, чтобы не путать, как пьяный в подворотне. Есть два главных типа тестов, и если их перепутать — будет пиздец, а не проект.
Юнит-тест — это когда ты берёшь одну мелкую, ёбнутую функцию или класс и проверяешь её в полной изоляции, как будто она сидит в камере-одиночке. Все её дружки-зависимости (база данных, внешние сервисы, файловая система) — это всё хуйня, их заменяешь на подставных уродов, то есть моки. Цель — понять, не сбоит ли логика в самой этой мелкой детали.
Интеграционный тест — это уже проверка, как несколько этих деталей, блядь, срастаются в одно целое. Тут уже мокать нельзя, нужно поднимать реальную (или максимально близкую к реальной) инфраструктуру: тестовую базу, заглушки API и прочую хуету. Он медленный, как черепаха в сиропе, но показывает, не развалится ли всё нахуй при сборке.
| Критерий | Юнит-тесты | Интеграционные тесты |
|---|---|---|
| Цель | Убедиться, что одна функция не гонит пургу | Убедиться, что несколько функций не устроят между собой пиздец при работе |
| Изоляция | Все вокруг — муляжи и подделки (моки) | Используется почти настоящая обстановка (тестовая БД и т.д.) |
| Скорость | Быстрее, чем ты успеешь сказать «ёпта» | Медленнее, чем ожидание ответа от поддержки |
| Область | Одна маленькая пиздюлина | Целый сценарий из нескольких пиздюлин |
Вот представь себе пирамиду тестирования. Внизу, как фундамент, — куча юнит-тестов, их должно быть овердохуища. А выше — интеграционные, их меньше, но они важные, блядь.
Вот тебе пример юнит-теста, где мы проверяем одну функцию, отъединённую от всего мира:
# a_module.py
def is_strong_password(password: str) -> bool:
return len(password) >= 8 and any(c.isdigit() for c in password)
# test_a_module.py
def test_is_strong_password():
assert is_strong_password("password123") == True
assert is_strong_password("short") == False
assert is_strong_password("no_digits") == False
Видишь? Никаких баз данных, никаких сетей. Чистая логика. Либо работает, либо нет.
А теперь пример интеграционного теста, где мы проверяем, как сервис общается с базой данных:
# user_service.py
class UserService:
def __init__(self, db_session):
self.db = db_session
def create_user(self, name):
user = User(name=name)
self.db.add(user)
self.db.commit()
return user
# test_user_service.py
def test_user_creation_in_db(test_db_session): # test_db_session - реальное подключение к тестовой БД
service = UserService(test_db_session)
user = service.create_user("John Doe")
# Проверяем, что пользователь действительно появился в базе данных
retrieved_user = test_db_session.query(User).filter_by(name="John Doe").one()
assert user.id == retrieved_user.id
Вот тут уже пошла интеграция: сервис + сессия базы данных. Если что-то не так сгенерировался SQL, или транзакция не закоммитилась — тест словит этот пиздец. Но и бегать он будет, как сонная муха.
Короче, запомни: юнит-тесты — для проверки мозгов отдельной функции, интеграционные — для проверки, что эти мозги не вытекают при сборке всей системы. И да, не пытайся всё покрыть интеграционными тестами — это путь в никуда, они медленные и хрупкие, как яйца.