В чем разница между Smoke, Sanity и Regression Testing?

Ответ

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 (а не развалилось ли всё остальное?). Запускать регрессию на сломанном билде — это как пытаться приготовить ужин, когда у тебя на кухне потоп, газа нет и холодильник сдох. Бессмысленно и беспощадно.