RecallDeck
Направление

Подготовка к собеседованию — QA-инженер (ручное тестирование)

Колода из 146+ карточек с вопросами для собеседования по направлению «QA-инженер (ручное тестирование)» — по темам и уровню сложности, с возвратом ровно перед тем, как вы забудете. Посмотрите несколько карточек ниже, затем войдите, чтобы учить всё направление по расписанию в стиле Anki (SM-2).

146 карточек8 тем

Бесплатно · вход через GitHub · ваш прогресс остаётся с вами.

Что внутри

Все темы направления, сгруппированные так, как вы будете их учить.

Базы данных

42 карточки
Основы SQL

Поведенческое интервью

35 карточек
Поведенческое интервью

Теория тестирования

15 карточек
Теория тестирования

Техники тест-дизайна

11 карточек
Тест-дизайн

Баг-репорты и процессы

11 карточек
Баги и процессы

HTTP, API и клиент-сервер

13 карточек
HTTP и API

Веб, мобильное и безопасность

9 карточек
Веб, мобильное и безопасность

Практические кейсы и задачи

10 карточек
Кейсы и задачи

Примеры вопросов

Несколько карточек из колоды — откройте ответ, затем войдите, чтобы учить весь набор по расписанию.

Что делает SELECT и в каком порядке выполняются части запроса?

Короткий ответ: SELECT извлекает строки из таблиц. Логический порядок выполнения НЕ совпадает с порядком написания: сначала FROM, затем WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT.

Подробно:

Порядок написания (синтаксический):

SELECT   DISTINCT col1, agg(col2)
FROM     t
WHERE    cond
GROUP BY col1
HAVING   agg_cond
ORDER BY col1
LIMIT    10 OFFSET 20;

Логический порядок исполнения:

1. FROM / JOIN      -- какие таблицы, как соединить
2. WHERE            -- фильтр строк ДО группировки
3. GROUP BY         -- группировка
4. HAVING           -- фильтр групп ПОСЛЕ агрегации
5. SELECT           -- вычисление выражений, алиасов
6. DISTINCT         -- удаление дублей
7. ORDER BY         -- сортировка
8. LIMIT / OFFSET   -- срез

⚠️ Ловушка: алиас из SELECT нельзя использовать в WHERE (т.к. WHERE выполняется раньше SELECT), но можно в ORDER BY и часто в GROUP BY (зависит от СУБД). Пример ошибки:

SELECT salary * 12 AS annual FROM emp WHERE annual > 100000; -- ОШИБКА
SELECT salary * 12 AS annual FROM emp ORDER BY annual;        -- ОК

Чем WHERE отличается от ORDER BY, и как работают LIMIT/OFFSET?

Короткий ответ: WHERE фильтрует строки, ORDER BY сортирует результат, LIMIT n OFFSET m возвращает n строк, пропустив первые m.

Подробно:

-- Пагинация: страница 3 по 20 записей (пропустить 40, взять 20)
SELECT id, name
FROM users
WHERE active = TRUE
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;

⚠️ Ловушка: LIMIT без ORDER BY возвращает НЕдетерминированный набор строк — порядок не гарантирован. Также OFFSET на больших значениях медленный (СУБД всё равно читает и отбрасывает пропущенные строки) — для глубокой пагинации используйте keyset-пагинацию:

-- keyset: быстрее, чем большой OFFSET
SELECT * FROM users WHERE id > :last_seen_id ORDER BY id LIMIT 20;

Что делает DISTINCT и в чём подвох?

Короткий ответ: DISTINCT убирает дублирующиеся строки из результата.

Подробно:

SELECT DISTINCT department FROM employees;        -- уникальные отделы
SELECT DISTINCT department, city FROM employees;  -- уникальные ПАРЫ (отдел, город)

⚠️ Ловушка: DISTINCT применяется ко ВСЕМ столбцам в SELECT, а не к одному. SELECT DISTINCT a, b ≠ «уникальные a». Также COUNT(DISTINCT col) считает уникальные значения, игnorируя NULL.

Какие бывают JOIN и чем они различаются?

Короткий ответ: INNER — только совпадения; LEFT — все левые + совпадения справа (иначе NULL); RIGHT — зеркало LEFT; FULL — всё с обеих сторон; CROSS — декартово произведение; SELF — таблица с самой собой.

Подробно:

Пусть есть:

employees           departments
+----+--------+----+   +----+----------+
| id | name   |dept|   | id | title    |
+----+--------+----+   +----+----------+
| 1  | Анна   | 10 |   | 10 | IT       |
| 2  | Борис  | 20 |   | 30 | Finance  |
| 3  | Вера   | NULL|  +----+----------+
+----+--------+----+

INNER JOIN — пересечение (∩). Только строки, где есть совпадение в ОБЕИХ таблицах:

SELECT e.name, d.title
FROM employees e
INNER JOIN departments d ON e.dept = d.id;
-- Анна | IT      (Борис отпал: dept 20 нет в departments;
--                 Вера отпала: dept = NULL)
employees    departments
   [ ##### ]              ← только пересечение

LEFT JOIN — все строки левой таблицы + совпадения справа (нет совпадения → NULL):

SELECT e.name, d.title
FROM employees e
LEFT JOIN departments d ON e.dept = d.id;
-- Анна  | IT
-- Борис | NULL   ← сохранён, departments нет
-- Вера  | NULL   ← сохранён, dept = NULL
[ left ##### ]   ← вся левая + пересечение

RIGHT JOIN — зеркало LEFT (все строки правой):

SELECT e.name, d.title
FROM employees e
RIGHT JOIN departments d ON e.dept = d.id;
-- Анна | IT
-- NULL | Finance  ← департамент 30 без сотрудников

FULL OUTER JOIN — все строки обеих таблиц:

SELECT e.name, d.title
FROM employees e
FULL OUTER JOIN departments d ON e.dept = d.id;
-- Анна  | IT
-- Борис | NULL
-- Вера  | NULL
-- NULL  | Finance

CROSS JOIN — декартово произведение (каждая с каждой), без условия:

SELECT e.name, d.title FROM employees e CROSS JOIN departments d;
-- 3 строки × 2 строки = 6 строк

SELF JOIN — таблица к самой себе (например, сотрудник → менеджер):

SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;

💡 Чем LEFT отличается от INNER на примере: если справа нет совпадения, INNER ВЫБРАСЫВАЕТ строку, а LEFT ОСТАВЛЯЕТ её, подставляя NULL в правые столбцы. Поэтому LEFT JOIN часто используют для поиска «осиротевших» записей:

-- Сотрудники без отдела
SELECT e.name
FROM employees e
LEFT JOIN departments d ON e.dept = d.id
WHERE d.id IS NULL;

⚠️ Ловушка: условие на правую таблицу в LEFT JOIN нужно класть в ON, а не в WHERE, иначе LEFT превращается в INNER:

-- НЕПРАВИЛЬНО: фильтр в WHERE отсекает строки с NULL справа → ведёт себя как INNER
SELECT e.name, d.title FROM employees e
LEFT JOIN departments d ON e.dept = d.id
WHERE d.title = 'IT';

-- ПРАВИЛЬНО: если нужно сохранить все строки слева
SELECT e.name, d.title FROM employees e
LEFT JOIN departments d ON e.dept = d.id AND d.title = 'IT';

Что такое GROUP BY и агрегатные функции?

Короткий ответ: GROUP BY группирует строки по значениям столбцов; агрегаты (COUNT, SUM, AVG, MIN, MAX) считают одно значение на группу.

Подробно:

SELECT department,
       COUNT(*)        AS headcount,
       SUM(salary)     AS payroll,
       AVG(salary)     AS avg_salary,
       MIN(salary)     AS min_salary,
       MAX(salary)     AS max_salary
FROM employees
GROUP BY department;

⚠️ Ловушка: в стандартном SQL в SELECT можно использовать только столбцы из GROUP BY или агрегаты. SELECT name, dept, COUNT(*) ... GROUP BY dept — ошибка (name не сгруппирован и не агрегирован). PostgreSQL это запрещает, MySQL (в нестрогом режиме) молча вернёт произвольное name.

COUNT(*) vs COUNT(col) vs COUNT(DISTINCT col) — в чём разница?

Короткий ответ: COUNT(*) — все строки; COUNT(col) — строки, где col НЕ NULL; COUNT(DISTINCT col) — уникальные не-NULL значения.

Подробно:

-- Таблица: 5 строк, в phone 2 NULL, 1 дубликат
SELECT
  COUNT(*)               AS total,        -- 5
  COUNT(phone)           AS with_phone,   -- 3 (NULL не считаются)
  COUNT(DISTINCT phone)  AS unique_phones -- 2
FROM users;

⚠️ Ловушка: COUNT(col) тихо игнорирует NULL — частая причина расхождения в отчётах. Если нужно посчитать все строки — всегда COUNT(*).

Готовы закрепить навсегда?

Первая сессия — меньше минуты. Ваше будущее «я» на собеседовании скажет спасибо.

Другие направления

RecallDeckПодготовка к собеседованию на интервальных повторениях