Ответ
Smoke Testing — поверхностная проверка стабильности сборки. Sanity Testing — узкая проверка конкретного функционала после изменений. Regression Testing — полная проверка всего приложения на регрессию.
Сравнительная матрица:
| Критерий | Smoke Testing | Sanity Testing | Regression Testing |
|---|---|---|---|
| Другое название | Build Verification Test (BVT) | Surface Testing | — |
| Глубина | Поверхностный (широкий, неглубокий) | Узкий и глубокий | Глубокий и широкий |
| Цель | Проверить, «не сломан» ли билд | Убедиться, что конкретное изменение работает | Найти регрессии во всем приложении |
| Объем | 5-10% критических тест-кейсов | 1-2 модуля/функции | 70-100% регрессионной пачки |
| Когда выполнять | После каждой сборки | После конкретных изменений/фиксов | Перед релизом, после значительных изменений |
| Автоматизация | Высокий приоритет | Средний/низкий | Высокий приоритет |
| Время выполнения | Минуты | Минуты-часы | Часы-дни |
| Кто выполняет | QA/DevOps/CI система | QA/разработчик | QA-команда |
Пример для веб-приложения:
# Smoke Test Suite (проверяем, что приложение «живое»)
def test_smoke_application():
"""Smoke: базовые функции работают после деплоя"""
# 1. Приложение запускается
response = requests.get("https://app.example.com/health")
assert response.status_code == 200
# 2. Главная страница загружается
response = requests.get("https://app.example.com")
assert "Welcome" in response.text
# 3. База данных доступна
db_status = check_database_connection()
assert db_status == "connected"
# 4. Критичный API endpoint отвечает
response = requests.get("https://api.example.com/v1/products")
assert response.status_code == 200
# Sanity Test Suite (после фикса бага в корзине)
def test_sanity_shopping_cart_fix():
"""Sanity: проверяем только исправленную функциональность корзины"""
# Контекст: фиксили баг с добавлением товара при нулевом количестве
# 1. Проверяем исправленный сценарий
cart = ShoppingCart()
result = cart.add_item("product_123", quantity=0)
assert result == False # Теперь должно возвращать False, а не падать
# 2. Проверяем смежный сценарий
result = cart.add_item("product_123", quantity=1)
assert result == True
assert cart.get_item_count() == 1
# НЕ проверяем: оплату, доставку, каталог — только корзину
# Regression Test Suite (полная проверка перед релизом)
class TestRegression:
"""Regression: полная проверка всего приложения"""
def test_regression_user_flows(self):
# 1. Полный flow регистрации
user_id = register_user("test@example.com", "password123")
assert user_id is not None
# 2. Полный flow покупки
cart = create_cart(user_id)
cart.add_item("product_1", 2)
order_id = checkout(cart, "card_123")
assert order_status(order_id) == "confirmed"
# 3. Проверяем историю заказов
orders = get_user_orders(user_id)
assert order_id in [o.id for o in orders]
# 4. Проверяем связанный функционал
invoice = generate_invoice(order_id)
assert invoice.total > 0
# ... и еще 100+ тест-кейсов
Практический workflow в CI/CD:
# .gitlab-ci.yml пример
stages:
- build
- smoke
- sanity
- regression
- deploy
smoke_test:
stage: smoke
script:
- python run_tests.py --suite=smoke # 2 минуты
only:
- main
- merge_requests
sanity_test:
stage: sanity
script:
- python run_tests.py --module=shopping_cart # 5 минут
only:
- merge_requests # Только для изменений в корзине
regression_test:
stage: regression
script:
- python run_tests.py --suite=regression # 2 часа
only:
- main # Только перед релизом
when: manual
Ключевое правило: Smoke → если проходит, то Sanity → если проходит, то Regression. Это фильтры, предотвращающие запуск тяжелых тестов на нестабильных сборках.
Ответ 18+ 🔞
Слушай, а вот объясни мне на пальцах, в чём разница между этими тремя штуками, а то я уже второй час туплю, как пень, и ничего не понимаю. Ну, типа, все говорят «смоук», «сэнити», «регрессия», а я сижу и думаю — да это же одно и то же, ёпта! Но нет, оказывается, не одно и то же, блядь.
Представь себе новенький автомобиль с завода. Только что собрали, красивый такой, блестит.
Smoke Testing (Дымовое тестирование) — это когда ты подходишь к этой тачке, поворачиваешь ключ зажигания и слушаешь: заводится ли она вообще? Фары горят? Стеклоочистители двигаются? Музыка врубается? То есть, ты не едешь на ней в кругосветное путешествие, ты просто проверяешь, не горит ли она уже на стоянке, сука. Не сломан ли билд в принципе. Это быстро, поверхностно, но по критичным точкам. Если машина не заводится — всё, поездка отменяется, дальше даже не смотрим. Вот это и есть смоук.
Sanity Testing (Проверка вменяемости / Здравомыслие) — это уже другая история. Допустим, ты привёз эту машину в сервис, потому что не работал обогрев заднего стекла. Починили тебе его. Sanity-тест — это когда ты после ремонта садишься и проверяешь ТОЛЬКО этот самый обогрев. Включил — греется? Отлично. Ты не начинаешь проверять кондиционер, магнитолу и разгон до сотни. Ты узко и глубоко ковыряешь именно ту фичу, которую только что починили. Цель — убедиться, что конкретное изменение не накосячило в своём уголке.
Regression Testing (Регрессионное тестирование) — а вот это уже пиздец, извини за выражение. Это полная, тотальная проверка всей машины после того, как в ней поковырялись. Починили обогрев стекла? Отлично. А теперь давай прокатимся на 500 километров, проверим ВСЁ: и тормоза, и двигатель на всех передачах, и фары, и сигнал, и чтобы пепельница не выпадала, и чтобы после починки обогрева у тебя вдруг не отвалилась рулевая колонка, блядь. Это долго, нудно, но необходимо, чтобы убедиться, что, исправляя одну хуйню, мы не сломали десять других.
Вот тебе табличка, чтобы в глазах не рябило:
| Критерий | Smoke Testing | Sanity Testing | Regression Testing |
|---|---|---|---|
| Другое название | Проверка сборки (BVT) | Поверхностное тестирование | — |
| Глубина | Широко, но по верхам (как шваброй прошёлся) | Узко, но вглубь (как буравчиком) | И широко, и глубоко (как комбайн) |
| Цель | Узнать, не говно ли билд | Убедиться, что конкретный фикс работает | Найти, что ещё разъебали |
| Объем | 5-10% от всех тестов (самые главные) | 1-2 модуля, на которых работали | 70-100% всех регрессионных тестов |
| Когда делать | После КАЖДОЙ новой сборки | После конкретных правок или фиксов | Перед выпуском версии, после крупных изменений |
| Автоматизация | Овердохуищно важна | Можно и руками, но лучше автоматом | Жизненно важна, иначе с ума сойдёшь |
| Время | Минуты | Минуты-часы | Часы-дни (плачь) |
| Кто делает | QA, DevOps или CI-система сама | QA или разработчик, который фиксил | Вся QA-команда, ордой |
А теперь, чтобы вообще мозг встал на место, смотри на код. Я тебя умоляю, не пугайся, там всё просто.
# Smoke Test Suite (Быстрая проверка "живости")
def test_smoke_application():
"""Смоук: базовые функции работают после деплоя"""
# 1. Приложение вообще запустилось?
response = requests.get("https://app.example.com/health")
assert response.status_code == 200 # Не 500, ура!
# 2. Главная страница грузится?
response = requests.get("https://app.example.com")
assert "Welcome" in response.text # Не белый экран?
# 3. База данных жива?
db_status = check_database_connection()
assert db_status == "connected" # Не легла?
# 4. Критичный API отвечает?
response = requests.get("https://api.example.com/v1/products")
assert response.status_code == 200 # Не "404 Not Found", блядь?
# Sanity Test Suite (Проверка фикса в корзине)
def test_sanity_shopping_cart_fix():
"""Сэнити: проверяем ТОЛЬКО исправленную корзину"""
# Контекст: фиксили баг, когда добавление товара с количеством 0 валило сервер
# 1. Проверяем исправленный сценарий
cart = ShoppingCart()
result = cart.add_item("product_123", quantity=0)
assert result == False # Теперь должно возвращать False, а не "ёбнуться"
# 2. Проверяем смежный сценарий (вдруг сломали и его)
result = cart.add_item("product_123", quantity=1)
assert result == True
assert cart.get_item_count() == 1
# НЕ проверяем тут: оплату, доставку, каталог — только корзину, ебанашка!
# Regression Test Suite (Полный разбор полётов)
class TestRegression:
"""Регрессия: проверяем ВСЁ, потому что доверия — ноль ебать"""
def test_regression_user_flows(self):
# 1. Полный сценарий "от регистрации до получения"
user_id = register_user("test@example.com", "password123")
assert user_id is not None
# 2. Полный сценарий покупки
cart = create_cart(user_id)
cart.add_item("product_1", 2)
order_id = checkout(cart, "card_123")
assert order_status(order_id) == "confirmed"
# 3. Проверяем историю заказов (вдруг после чекаута её почистили)
orders = get_user_orders(user_id)
assert order_id in [o.id for o in orders]
# 4. Проверяем связанный функционал (накладная, блядь)
invoice = generate_invoice(order_id)
assert invoice.total > 0
# ... и так ещё 100+ тест-кейсов, я не буду всю срань тут расписывать.
И как это всё в пайплайне выглядит? Да элементарно, ёпта!
# .gitlab-ci.yml пример
stages:
- build
- smoke
- sanity
- regression
- deploy
smoke_test:
stage: smoke
script:
- python run_tests.py --suite=smoke # 2 минуты, и понятно, билд труп или нет
only:
- main
- merge_requests # После каждого пулл-реквеста
sanity_test:
stage: sanity
script:
- python run_tests.py --module=shopping_cart # 5 минут, только корзину
only:
changes:
- shopping_cart/**/* # Запускаем ТОЛЬКО если меняли файлы корзины
regression_test:
stage: regression
script:
- python run_tests.py --suite=regression # 2 часа, все соснут
only:
- main # Только на основной ветке перед релизом
when: manual # Запускаем вручную, потому что дорого и долго
Главное правило, которое нужно выжечь себе на подкорке: это фильтры, блядь. Сначала Smoke (заводится ли?). Если прошёл — Sanity (а тот самый винтик, который крутили, на месте?). Если и он прошёл — тогда уже можно запускать тяжёлую артиллерию Regression (а не развалилось ли всё остальное?). Запускать регрессию на сломанном билде — это как пытаться приготовить ужин, когда у тебя на кухне потоп, газа нет и холодильник сдох. Бессмысленно и беспощадно.