Перейти к содержанию
Тестирование

12 вопросов по теме «QA: Паттерны автоматизации» на собеседовании

В этом материале — 12 вопросов из русской колоды RecallDeck по теме «QA: Паттерны автоматизации». Сначала сформулируйте короткий ответ сами, затем откройте подробный разбор и проверьте примеры, ограничения и отказные случаи.

9 мин чтения12 подробных ответовПроверено 24 августа 2026
Главная мысль

Начните с риска и oracle, затем выберите самый дешёвый уровень теста, который даст полезное доказательство. Название инструмента само по себе не является стратегией.

Вопросы и ответы

12 подробных ответов

01

Что такое Page Object Model и какую проблему он решает?

Короткий ответ: POM — паттерн, где каждая страница или экран приложения описывается отдельным классом, инкапсулирующим локаторы и действия над ними. Тесты вызывают методы этих классов, а не сырые селекторы, поэтому при изменении вёрстки локатор правится в одном месте, а не в сотне тестов.

Подробно:

  1. Инкапсуляция локаторов — селекторы живут внутри page object, тест их не видит.
  2. Читаемость — тест выражен в терминах бизнеса (loginPage.login(user, pass)), а не в CSS/XPath.
  3. PageFactory — в Java-стеке @FindBy + ленивая инициализация элементов через PageFactory.initElements.
  4. Слой Steps поверх POM — бизнес-действия, комбинирующие несколько страниц; тест превращается в сценарий.
┌──────────────┐
│    Тест      │  сценарий: что проверяем
└──────┬───────┘

┌──────────────┐
│    Steps     │  бизнес-действия (login, checkout)
└──────┬───────┘

┌──────────────┐
│ Page Objects │  локаторы + действия страницы
└──────┬───────┘

┌──────────────┐
│  WebDriver   │  браузер
└──────────────┘

⚠️ Частая ошибка: объяснять POM как «так принято/модно» без «зачем». Ценность — единая точка правки при изменении UI и отделение локаторов от тест-логики.

02

Что такое Data-Driven Testing и как его реализовать?

Короткий ответ: DDT — подход, при котором одна и та же логика теста прогоняется на разных наборах входных данных, вынесенных наружу. Тест-данные отделены от тест-логики: добавить кейс — значит добавить строку данных, а не копировать тест.

Подробно:

  1. pytest@pytest.mark.parametrize со списком наборов.
  2. TestNG@DataProvider, возвращающий Object[][].
  3. Внешние источники — CSV/JSON/Excel или БД: данные редактируют без изменения кода.
  4. Зачем — покрытие граничных значений и классов эквивалентности без дублирования тестов.
import pytest

@pytest.mark.parametrize("a, b, expected", [
    (2, 3, 5),
    (0, 0, 0),
    (-1, 1, 0),
])
def test_add(a, b, expected):
    assert add(a, b) == expected

⚠️ Частая ошибка: считать DDT «просто циклом внутри теста». В цикле первое падение прячет остальные кейсы, а отчёт показывает один тест; параметризация даёт отдельный кейс на каждый набор данных.

03

Что такое фикстуры в pytest и какие у них scope?

Короткий ответ: Фикстура — переиспользуемый setup/teardown, который pytest подставляет в тест через dependency injection (по имени аргумента). scope управляет тем, как часто фикстура пересоздаётся: function, class, module, package, session.

Подробно:

  1. DI по имени — тест объявляет def test_x(db):, и pytest сам создаёт db.
  2. Teardown через yield — код после yield выполняется при разрушении фикстуры.
  3. Scope — от самого узкого (function) до самого широкого (session); чем шире, тем дольше живёт объект.
import pytest

@pytest.fixture(scope="session")
def db():
    conn = connect()      # setup: один раз на прогон
    yield conn
    conn.close()          # teardown
scope Пересоздаётся
function на каждый тест (по умолчанию)
class раз на класс
module раз на файл
package раз на пакет
session раз на весь прогон

⚠️ Частая ошибка: session/module-фикстура, отдающая мутабельный объект (список, dict, залогиненный клиент). Один тест меняет состояние — оно протекает в следующий, и тесты начинают зависеть от порядка запуска.

04

Чем @pytest.mark.parametrize отличается от параметризации фикстуры через params?

Короткий ответ: @pytest.mark.parametrize размножает один конкретный тест по наборам данных. Фикстура с params=[...] размножает каждый тест, который эту фикстуру использует. Разница — в области действия (area of effect): маркер локален для теста, параметризованная фикстура влияет на всех потребителей.

Подробно:

  1. parametrize — данные привязаны к одной тест-функции, ничего вокруг не трогают.
  2. fixture params — фикстура сама становится многовариантной; любой тест, зависящий от неё, прогонится на каждом варианте.
  3. Когда что — parametrize для входов конкретного теста; параметризованная фикстура для окружения (например, прогнать весь набор на нескольких браузерах).
# parametrize: множит ТОЛЬКО test_add
@pytest.mark.parametrize("n", [1, 2, 3])
def test_add(n):
    ...

# fixture params: множит КАЖДЫЙ тест, берущий browser
@pytest.fixture(params=["chrome", "firefox"])
def browser(request):
    return start(request.param)

⚠️ Частая ошибка: путать области действия — засунуть в параметризованную фикстуру то, что нужно одному тесту, и нечаянно размножить весь модуль в 2-3 раза.

05

В чём разница между assert и verify (soft assert)?

Короткий ответ: Обычный assert останавливает тест на первом же несовпадении. Soft assert (verify) копит несоответствия и репортит их все в конце — полезно, когда надо проверить несколько независимых полей одной формы за один прогон.

Подробно:

  1. Hard assert — падение сразу, остальные проверки не выполняются (fail-fast).
  2. Soft assert — проверки накапливаются, тест падает в конце с полным списком; в TestNG — SoftAssert + обязательный assertAll().
  3. Когда soft — независимые проверки (валидация всех полей формы): один прогон — вся картина сразу.
Hard assert Soft assert
При несовпадении стоп сразу продолжает
Отчёт первая ошибка все ошибки
Когда зависимые шаги независимые проверки

⚠️ Частая ошибка: в TestNG забыть вызвать assertAll()SoftAssert без него не свалит тест, все накопленные падения молча теряются, и зелёный прогон скрывает баги.

06

Чем stub отличается от mock?

Короткий ответ: Stub возвращает заранее заготовленные ответы и ничего не проверяет — это подмена данных. Mock дополнительно верифицирует взаимодействия: какие методы вызвали, сколько раз и с какими аргументами — это подмена + проверка поведения.

Подробно:

  1. Stub — state verification: подсунули ответ, проверяем итоговый результат.
  2. Mock — behavior verification: проверяем сам факт и характер вызова (assert_called_once_with).
  3. Родня — fake (рабочая упрощённая реализация, напр. in-memory БД) и spy (обёртка, записывающая вызовы).
from unittest.mock import Mock

stub = Mock(); stub.get_rate.return_value = 1.1   # stub: только ответ
rate = converter.convert(100, stub)

mock = Mock()                                     # mock: проверяем вызов
notifier.notify(mock, "hi")
mock.send.assert_called_once_with("hi")
Stub Mock
Задача отдать данные проверить вызов
Проверяет результат (state) взаимодействие (behavior)
Провал теста по assert результата по неверному вызову

⚠️ Частая ошибка: употреблять «мок» и «стаб» как синонимы. На собеседовании важно показать, что mock проверяет взаимодействие, а stub — только отдаёт данные.

07

Как автотесты встроены в CI/CD-пайплайн? Что происходит, когда тест падает?

Короткий ответ: Автотесты вешаются на триггер (push/PR) и бегут ступенями от быстрых к медленным: unit → API/smoke → регрессия. Отчёт (Allure) публикуется артефактом. Красный критичный тест — это gate: merge или деплой блокируется.

Подробно:

  1. Триггер — push, pull request, по расписанию (nightly) или ручной запуск.
  2. Ступени по цене — сначала быстрые unit, затем API/smoke, в конце тяжёлая UI-регрессия; падение на дешёвой ступени экономит время.
  3. Отчётность — Allure или JUnit XML как артефакт прогона, ссылка прямо в PR.
  4. Реакция на падение — критичный тест красный → pipeline красный → gate на merge; известные флаки уводят в карантин, а не блокируют всё.
push / PR


[ unit ] → [ API / smoke ] → [ UI-регрессия ]
   │             │                  │
   └── fail ─────┴────── fail ──────┘

     красный pipeline → merge заблокирован

         Allure-отчёт (артефакт)

⚠️ Частая ошибка: отвечать расплывчато «мы гоняем тесты в CI» без ступеней и без реакции на падение. Интервьюер ждёт gate на merge и внятную стратегию по флакам.

08

Что такое Allure Report и чем он полезен?

Короткий ответ: Allure — фреймворк отчётности, который превращает результаты прогона в наглядный HTML-отчёт с шагами, вложениями и трендом по истории. Публикуется как артефакт CI, чтобы команда видела не только «упало», но и где именно.

Подробно:

  1. @Step — разбивает тест на человекочитаемые шаги.
  2. @Attachment — прикрепляет скриншоты, логи, тело запроса/ответа к упавшему шагу.
  3. History trend — динамика pass/fail по прогонам, видно флаки и деградацию.
  4. Категории и severity — группировка дефектов и метки важности (critical/minor).
Аннотация / фича Зачем
@Step шаги внутри теста
@Attachment скриншоты / логи / HAR
@Severity важность кейса
@Epic / @Feature / @Story структура по функциональности
history trend pass/fail по прогонам

⚠️ Частая ошибка: генерировать Allure только локально и смотреть в одиночку. Ценность — публикация как CI-артефакта со ссылкой в PR и накопленной историей прогонов.

09

Зачем Docker в инфраструктуре автотестов?

Короткий ответ: Docker даёт воспроизводимые изолированные окружения для тестов: одинаковые версии браузера и драйвера, чистую одноразовую БД, Selenium Grid в контейнерах. Это убирает «у меня на машине работает» и часть флаков, вызванных различиями окружения.

Подробно:

  1. Одинаковые версии — образ фиксирует браузер + драйвер; локально и в CI одно и то же.
  2. Чистое состояние — одноразовый контейнер БД поднимается пустым на каждый прогон, тесты не тянут мусор от прошлых.
  3. Selenium Grid — hub и ноды браузеров в контейнерах, легко масштабировать параллель.
  4. Изоляция — тесты не гадят в хостовую систему; docker compose down — и всё убрано.
services:
  chrome:
    image: selenium/standalone-chrome:148.0
    shm_size: 2gb
    ports: ["4444:4444"]
  tests:
    build: .
    depends_on: [chrome]
    environment:
      REMOTE_URL: http://chrome:4444/wd/hub

⚠️ Частая ошибка: забыть про shm_size для контейнера с Chrome — браузер падает с «session deleted / tab crashed» из-за нехватки /dev/shm.

10

Что такое contract testing (Pact) и что оно заменяет в микросервисах?

Короткий ответ: Contract testing проверяет совместимость сервисов по контракту, а не через живое межсервисное окружение. В consumer-driven подходе (Pact) потребитель описывает ожидаемые запрос и ответ, провайдер обязан этот контракт выполнить; проверки бегут в CI на обеих сторонах и ловят breaking changes без поднятия всех сервисов.

Подробно:

  1. Consumer-driven — потребитель генерирует pact-файл из своих ожиданий к API.
  2. Provider verification — провайдер прогоняет контракт против себя в своём CI.
  3. Pact Broker — хранит контракты и версии; can-i-deploy разрешает или запрещает деплой.
  4. Что заменяет — тяжёлые сквозные E2E между сервисами: быстрее, стабильнее, ловит рассинхрон API на раннем этапе.
┌──────────┐  ожидания   ┌──────────┐  проверка   ┌──────────┐
│ Consumer │ ──────────► │ Contract │ ◄────────── │ Provider │
│ (клиент) │  pact.json  │  (Pact)  │ verify в CI │ (сервис) │
└──────────┘             └────┬─────┘             └──────────┘

                        Pact Broker
                    can-i-deploy? → gate

⚠️ Частая ошибка: считать contract testing заменой всем тестам. Он проверяет форму и совместимость API, но не бизнес-логику внутри сервиса — юнит- и функциональные тесты никуда не деваются.

11

Как запустить тесты параллельно и зачем нужен ThreadLocal<WebDriver>?

Короткий ответ: Параллель включается на уровне раннера: в TestNG — атрибуты parallel и thread-count в suite XML, в pytest — плагин pytest-xdist (-n auto). ThreadLocal<WebDriver> нужен, чтобы у каждого потока был свой инстанс драйвера: общий static-драйвер потоки затирают друг у друга, и тесты валятся вперемешку.

Подробно:

  1. TestNG<suite parallel="methods" thread-count="4">.
  2. pytestpytest -n auto (xdist) распределяет тесты по воркерам.
  3. Зачем ThreadLocal — изолирует драйвер по потоку; поток A не открывает URL в браузере потока B.
  4. Teardowndriver.quit() и remove() из ThreadLocal, иначе течёт память и висят браузеры.
public class DriverFactory {
  private static final ThreadLocal<WebDriver> TL = new ThreadLocal<>();

  public static WebDriver get() {
    if (TL.get() == null) TL.set(new ChromeDriver());
    return TL.get();                 // свой драйвер на поток
  }
  public static void quit() {
    TL.get().quit();
    TL.remove();                     // иначе утечёт при пуле потоков
  }
}

⚠️ Частая ошибка: держать один static WebDriver на все потоки. При параллели потоки дерутся за один браузер — рандомные падения, которые невозможно воспроизвести локально в один поток.

12

Спроектируйте фреймворк автоматизации с нуля: какие слои выделите?

Короткий ответ: Фреймворк раскладывается на слои с одной ответственностью каждый: конфиг и фабрика драйвера → page objects → steps/бизнес-действия → тесты, с тест-данными и отчётностью отдельными слоями и интеграцией в CI. Ключевое — SOLID: страница не знает про тест (SRP), драйвер пробрасывается через конструктор (DI), а не берётся из глобала.

Подробно:

  1. Config + фабрика драйвера — окружения, URL, ThreadLocal-драйвер.
  2. Page Objects — локаторы и действия страниц.
  3. Steps / бизнес-действия — сценарные шаги поверх страниц.
  4. Тесты — только «что проверяем» и ассерты.
  5. Тест-данные — отдельный слой (фабрики/билдеры, внешние файлы).
  6. Отчётность + CI — Allure и запуск в пайплайне.
┌──────────────────────────┐
│ CI / раннер (pipeline)   │
├──────────────────────────┤
│ Отчётность (Allure)      │
├──────────────────────────┤
│ Тесты (assert, «что»)    │
├──────────────────────────┤
│ Steps / бизнес-действия  │
├──────────────────────────┤
│ Page Objects (локаторы)  │
├──────────────────────────┤
│ Config + DriverFactory   │
└──────────────────────────┘
   Тест-данные — сквозной слой

⚠️ Частая ошибка: монолитный тест-класс, где локаторы, драйвер и ассерты в одной куче. Меняется вёрстка — правишь десятки тестов; это нарушение SRP и смерть поддерживаемости.

Источники

Источники и редакционная политика

Материалы RecallDeck сопоставлены с официальной документацией и открытыми публикациями компаний, когда первичный источник доступен. Мы не связаны с упомянутыми работодателями, не публикуем конфиденциальные задания и не продаём места в подборках. Формат найма может меняться — уточняйте его у рекрутера.

От чтения к воспроизведению

Отрепетируйте полный цикл интервью.

RecallDeck возвращает сложные темы по расписанию и помогает удерживать в памяти язык, SQL, архитектуру и поведенческие истории.

Начать подготовку

Продолжить подготовку

Библиотека собеседований RecallDeck

Подробные русские ответы, разборы этапов найма и планы подготовки для российского IT-рынка.

RSS