Вступление
В 2025 году «приукрашенное» резюме — уже не редкость, а скорее стандарт. Кандидаты добавляют себе проекты, в которых не участвовали, технологии, с которыми едва знакомы, и роли, которые никогда не выполняли. Всё ради того, чтобы выглядеть конкурентно. И вот наступает момент — собеседование. А там начинается совсем не тот «стендап», к которому они готовились.
Если вы решили приписать себе опыт с Playwright, Selenium, Allure, CI/CD, Kafka, Kubernetes, Pytest, GitLab, GitHub Actions и вдобавок написать, что «вели QA-гильдию» — окей. Но тогда, пожалуйста:
Понимайте, что делает автотест автоматическим.
Покажите хотя бы один pull request, где вы действительно что-то настроили.
И да, разберитесь, чем
@pytest.mark.parametrize
отличается от магии.
Никто не против роста и обучения. Но когда в резюме написано «Senior», а в диалоге — уровень «Hello, World», это вызывает вопросы. Причём не риторические.
Важно: в этой статье речь пойдёт не о компаниях и их подходах к найму (об этом — в другой раз). Сейчас — только о кандидатах, которые приходят на собеседование с сильно приукрашенным опытом, не готовые подтвердить написанное делом.
Да, мы будем говорить про вакансии QA Automation Engineer на Python, от Middle до Senior. Да, местами будет жёстко. Но главное — будет честно. Если вы когда-то немного преувеличили свой опыт — приготовьтесь к лёгкому внутреннему дискомфорту.
Цель статьи
Эта статья — не для того, чтобы высмеивать. А чтобы показать: как выглядит «накрученный» опыт со стороны. Как фальшивые строки в резюме распознаются за считаные минуты. И как «10 лет опыта» превращаются в «10 минут фейспалма» — причём не со зла, а просто потому, что всё видно.
Удивительно, но после провала на собеседовании кандидаты часто обижаются: мол, интервьюер «плохой», вопросы «глупые», а компания — «всё равно не та». Давайте разберёмся, почему отказ в таком случае — не месть, не придирка и не заговор. А закономерный итог, к которому вы сами подвели.
Примеры будут настоящие. Где-то неловкие, где-то — болезненные. Но каждый из них — с конкретным выводом. Поехали.
Задачи. Добро пожаловать в реальность
Начнём без прелюдий.
HR-специалистов вы, возможно, и сможете впечатлить. История про то, как вы «8 лет в QA», были «Lead», строили процессы, но вас не ценили и вот теперь вы ищете «команду мечты» — звучит убедительно. Особенно если уверенно подаёте и красиво оформляете резюме.
Но всё меняется, когда вы доходите до технического собеседования.
Тут уже не важно, насколько драматична история вашего увольнения или какие проекты указаны в профиле. Тут важно одно: можете ли вы подтвердить заявленный уровень на практике. Не в лайвкодинге с алгоритмами, не в системном дизайне. А в базовых вопросах. Базовых — в самом прямом смысле.
Операторы
Пример простой, как табуретка. Задача, которая регулярно вызывает панику у кандидатов, претендующих на мидл- и сеньор-позиции по Python:
55 == True is True
Что вернёт выражение? Правильный ответ: False
. Почему? Потому что это цепное сравнение (chain comparison), и Python интерпретирует выражение как:
(55 == True) and (True is True)
А 55 == True
— это False
, потому что в логическом контексте True
приравнивается к 1
, и никакого наследования тут нет. Дальше уже неважно: False and ...
даст False
.
Именно такие задачи — не на знание редких фреймворков, а на понимание основ языка — и становятся критерием, отделяющим реального инженера от человека, который просто «наклеил технологии» в резюме.
Что говорят кандидаты?
Вот примеры реальных ответов:
«Ну,
55 == True
— этоTrue
, потому чтоbool
— этоint
» (почти, но нет:bool
действительно наследуется отint
, ноTrue == 55
— это всё равноFalse
)«
True is True
— этоFalse
, потому чтоis
сравнивает по значению» (наоборот:is
сравнивает по идентичности объектов, иTrue is True
всегдаTrue
)«Ну тут
==
побеждаетis
» (как будто это Mortal Kombat, а не синтаксис языка)
И всё это произносится с абсолютной уверенностью. Настолько спокойной, что кажется: человек действительно верит, что понимает, о чём говорит. И, судя по интонации, рассказывает это уже не на первом собеседовании.
Почему это важно?
Потому что это фундамент. Если вы не можете объяснить разницу между ==
и is
, не понимаете, как Python обрабатывает цепные сравнения или как работает приведение типов — вы не middle и не senior. Как бы ни выглядело ваше резюме.
Это не про придирки. Это про то, что все фреймворки, пайплайны, Kubernetes и GitHub Actions опираются на знание языка. И если в этом знании дыры — никакая “оркестрация” не спасёт.
Если фундамент кривой — небоскрёб падает. И падает быстро.
ООП
Теперь давайте про объектно-ориентированное программирование. Простая задача на наследование. Да-да, та самая классика, знакомая всем, кто хотя бы раз открывал учебник по Python:
class A:
def hello(self):
print("A")
class B(A):
def hello(self):
print("B")
class C(A):
def hello(self):
print("C")
class D(B, C):
pass
D().hello()
Ожидаемый вывод:
B
Почему? Потому что Python использует ромбовидное наследование и алгоритм разрешения порядка поиска методов (MRO), основанный на линеаризации C3. Python сначала смотрит в B
, затем в C
, и вызывает первый подходящий метод. В данном случае — B.hello
.
А что отвечают на собеседовании?
Иногда — действительно страшно:
«Этот код незапустится. Нельзя объявлять одинаковые методы в одном классе.» (А зачем тогда вообще придумали наследование? Чтобы пугать начинающих?)
«Ну… у кого главный метод, у того и вызовется…» (Кто такой «главный метод»? Это какой‑то новый паттерн — магия™?)
Бывают и более обнадёживающие попытки:
«Разрешение идёт слева направо.» Хорошее начало. Но потом продолжение: «до главного родителя». И всё… надежда, как и звук у кандидата, пропадает.
Почему это важно?
Потому что это тоже база. Это даже не про то, как писать продвинутые фреймворки — это про то, как работает язык, которым вы якобы владеете.
Особенно обидно, потому что лет 5–6 назад такие задачи многие решали устно, на слух. Без кода. Я описывал структуру классов — и человек отвечал. Сейчас же, увы, даже те, кто называют себя «QA Lead», не могут объяснить, как Python ищет метод при множественном наследовании.
Даже если вы не писали фреймворки, а занимались автотестами — вам приходилось сталкиваться с классами, наследованием, переопределением. Это часть ежедневной работы. И если за 5–8 лет опыта вы не узнали, как работает super()
и порядок разрешения методов — это не ошибка. Это системный пробел.
Вывод
Если вы называете себя «Senior» или «Lead QA на Python», но не понимаете, почему в примере выше выводится B
, — значит, вы пока не на этом уровне. Может быть, вы просто не уделяли базовым вещам достаточно внимания. Может быть, вас долго «тащила» команда. А может, вы просто слишком быстро начали учить Allure, не добравшись до __init__
.
Как бы там ни было — на собеседовании вы проваливаетесь не на хитроумной задачке. А на вопросе из первой главы.
Словари
Теперь — вообще элементарный вопрос. Звучит он так:
{("a", [1, 2]): "value"}
Может ли такой код выполниться без ошибок? Почти все кандидаты отвечают: «Да, конечно». И сразу начинают объяснять:
«Ну
tuple
же неизменяемый, значит — норм»«Я такого не писал, но вроде бы можно»
«Я такого не видел, значит такого не бывает»
«Так делали в одном проекте, и всё работало»
Серьёзно?
Давайте спокойно разберёмся
Ключи в словарях Python должны быть хешируемыми. Это значит: объект должен иметь постоянный hash()
и быть неизменяемым.
tuple
, действительно, может быть хешируемым. Но только если все его элементы тоже хешируемы. А [1, 2]
— это список. А список — изменяемый тип. Следовательно, ("a", [1, 2])
— это нехешируемый кортеж. А значит, такой ключ в словарь вставить нельзя. Python выбросит TypeError
.
То есть правильный ответ: нет, такой код не выполнится. И это не про подвох, не про тонкости, не про магию. Это просто базовая логика работы типов данных в Python. То, что должен понимать любой человек, который пишет код больше полугода.
Но почему так сложно?
Вот в чём настоящая боль: многие кандидаты не просто ошибаются. Они даже не пытаются рассуждать. Вместо логики — уверенность в духе:
«У меня так не было — значит, не бывает»
«Я работал 4 года — я бы такое точно запомнил»
«Ну это же tuple!»
Создаётся ощущение, что опыт не систематизировался. Не выстроился в понимание, как работает язык. А просто накопился в виде привычек и копипаста.
А ведь задача — из самых простых
Тут не нужно ни писать код, ни разбираться в каком-то редком поведении. Нужно просто знать: ключ в словаре — это всегда хешируемый тип. И всё. Это база. Это то, с чего начинается работа с Python.
Изменяемые и неизменяемые типы данных
Наверняка каждый, кто писал функции на Python, хотя бы раз встречал такую ситуацию:
def append_to_list(item, my_list=[]):
my_list.append(item)
return my_list
print(append_to_list(1))
print(append_to_list(2))
Вопрос: что выведется на экран? Ожидаемый ответ:
[1]
[1, 2]
Почему?
Потому что list
— изменяемый тип данных. Когда вы используете его в качестве значения по умолчанию, Python создаёт один и тот же объект списка при определении функции — и использует его повторно при каждом вызове, если аргумент my_list
не передан явно.
То есть my_list
не создаётся заново при каждом вызове — вы каждый раз работаете с тем самым списком.
Что отвечают кандидаты?
Тут начинается шоу. Вот лишь малая часть реплик с реальных собеседований:
«Такой код не выполнится. Значения по умолчанию в Python нельзя задавать функцией.»
«Не понял, зачем
my_list=[]
написано. Это магия?»«А почему второй вызов не должен вернуть
[2]
?»«Ну тут просто баг в IDE…»
«У меня такого ни разу не было, значит, это не проблема.»
«У меня лапки!»
Знаете, какая из этих фраз самая опасная?
«У меня такого ни разу не было — значит, это не проблема.»
Это и есть самый надёжный индикатор отсутствия критического мышления. Потому что разработка — это не про «у меня работало». Это про понимание, как работает язык.
А ведь задача — элементарная
Не нужно ничего писать руками
Не нужно разбираться в «мета-классах»
Не нужно знать internals интерпретатора
Нужно просто понимать базовый принцип: изменяемые значения по умолчанию — это потенциальная ловушка. И это не «тонкость», а один из первых анти-паттернов, который подчёркивает любая IDE, любой линтер, любой курс по Python с 2015 года. Даже в документации прямо сказано: «Не делайте так. Используйте None
и проверку внутри».
Как правильно?
Вот так:
def append_to_list(item, my_list=None):
if my_list is None:
my_list = []
my_list.append(item)
return my_list
И вывод
Если вы не сталкивались с таким кодом — значит, вы не читали код. Если вы не понимаете, в чём тут проблема — значит, вы не понимаете, как Python работает с аргументами. И уж точно — вы не Senior. Это не «жёсткий вопрос». Это базовая проверка на знание фундаментального поведения языка.
Comprehension
Ещё одна максимально простая и будничная задача. Из тех, с чем любой, кто реально работает с Python, сталкивается чуть ли не каждый день.
print([x for x in range(3)])
print((x for x in range(3)))
print({x for x in range(3)})
Что нужно ответить?
Тут никаких подводных камней. Просто понять, что тут происходит:
print([x for x in range(3)])
Вывод:[0, 1, 2]
— list comprehensionprint((x for x in range(3)))
Вывод:<generator object ...>
— generator expressionprint({x for x in range(3)})
Вывод:{0, 1, 2}
— set comprehension
Что отвечают «сеньоры»?
Первый случай почти всегда отвечают верно. Ура! А вот потом начинается магия.
Второй случай: Говорят, что будет кортеж: (0, 1, 2)
Почему? Ну… ответа обычно нет. Просто «я думал, что круглые скобки = кортеж». А то, что там не фигурные, не квадратные, и при этом есть for
внутри — это, видимо, никого не смущает.
Почему это не кортеж? Потому что кортеж — это: (x, y, z)
. А внутри comprehension с for
и без запятых — это генератор. (x for x in range(3))
— это не кортеж с генератором, это generator expression. Он не выполняется сразу, он ленивый, и это его главное отличие от list/set comprehension.
Третий случай: И тут ответ на миллион: «Это словарь» Словарь. Карл.
Нет, это не словарь. Это set comprehension. Вот так выглядит словарь comprehension:
{x: x * 2 for x in range(3)}
Если в фигурных скобках нет двоеточий, значит это set, а не dict. Set — это просто набор уникальных значений. Тут всё просто. Но почему-то многие уверенно говорят: «словарь».
И вывод
Эта задача даже не про знание синтаксиса. Это про зрение и практику. Если вы пишете на Python, вы просто физически не можете не видеть comprehension. Это визуальный паттерн, который мозг запоминает автоматически, если вы это реально используете.
Если вы смотрите на (x for x in range(3))
и говорите «это кортеж» — вы не пишете на Python. Если вы смотрите на {x for x in range(3)}
и говорите «это словарь» — вы не писали comprehension вообще.
Так что снова: задача не из области «алгоритмов», не из «краевых случаев», не из «хакающего мозга собеса». Это — база. Это синтаксис, который либо живёт у вас в пальцах, либо нет. И если его нет — кто вы после 5 лет на Python?
Знаете, в чём нюанс?
Суть в том, что все задачи выше — это не олимпиады по программированию, не математические загадки, не авторские фокусы с подвохом. Это база. База. Базовая. Самая обычная.
Я, честно признаюсь, бывал на собеседованиях в крупные компании, где автотесты строились из говна и палок, но на собес приносили задачки из олимпиад по информатике, как будто я в финале ACM ICPC. Смешно? Да. Абсурдно? Конечно. Но это хотя бы объяснимо: человек хочет показать «уровень».
Но тут не так. Задачи, о которых я говорил выше — это не уровень, это дыхание. Это то, с чем мы сталкиваемся каждый день, если мы хоть как‑то пишем на Python:
Понимание изменяемых и неизменяемых типов
Как работает аргумент по умолчанию
Что такое генератор, comprehension, set, tuple
Как работает наследование
Что можно, а что нельзя класть в словарь
Это не магия, это не глубокая специфика, это не метапрограммирование. Это — обычное поведение языка, и если ты работаешь с Python, ты это знаешь просто потому, что ты работаешь.
И вот где боль
Когда на собес приходит человек с 8 годами опыта, из которых 5 лет на Python, и он не может объяснить, почему tuple со списком не может быть ключом словаря, или что в my_list=[]
может быть ловушка, — тут уже не про знания. Тут про честность.
Это не просто «не знал». Это «никогда не делал».
Это не «запутался». Это «всё время пользовался Python, но не понимал, как он работает».
А кто он тогда, если не Python-разработчик? Он — человек, который:
накрутил опыт
сидит спокойный, уверенный, улыбается в камеру
думает, что все так делают, и никто ничего не заметит
Но заметят. И на собесе такого человека просто подвесят за мягкое место и начнут пытать.
И вот что страшно
Таких — большинство. Реально толковый кандидат, который понимает язык, на котором пишет, — это сейчас исключение, а не правило. Так что нет, ты не «не прошёл собес из‑за странных задач». Ты провалился на базовой проверке адекватности, потому что не понял то, что должен был понять в первую неделю после «Hello, World».
Откуда берутся такие люди?
Вопрос, скажем прямо, не из лёгких. Но, на мой взгляд, один из главных факторов — жадность. Желание откусить кусок, который не помещается в рот, и утащить мешок, который не поднять своими руками.
Представим ситуацию:
Есть работодатель, готовый платить зарплату 100 рублей.
Есть кандидат, которому по-честному — 65 рублей в самый раз.
Но у кандидата в голове картинка другая.
Он думает:
“Ну я ж посидел полтора года на галере, сделал TODO на Flask-е, запушил это криво на GitHub — мне теперь не 65, а все 255 положено!”
Ну а чтобы в 255 поверили, надо и опыт подкрутить. Было 1,5 года — стало 3. Нет, лучше сразу 5 — солидно же звучит. Пяти лет-то кто спорить будет?
А может, всё-таки виноват работодатель?
Можно ли сказать, что работодатель — тоже хорош, зарплату занижает, ожидания завышает? Можно. Такое встречается. Особенно если на собесе вместо кофе дают кипяток и совет «держитесь».
Но давайте честно: сейчас речь не об этом. Не о том, что в вакансиях иногда просят «Senior QA с опытом в девOps и ML», а ЗП — 50к. А о тех кандидатах, которые тупо врут. Системно. Хладнокровно. Без тени сомнений.
И да, мне говорят: «Ну это же от безысходности. Требования высокие, конкуренция сильная. Человек вынужден приукрасить…»
А я говорю: «Нет. Это инфантильность.». Если ты открываешь вакансию и видишь:
«Ого, требования жёсткие»
«Ого, технологий я не знаю»
«Ого, платить будут не так много»
Пройдите мимо. Не откликайтесь. Найдите вакансию, где вы подходите. Или — сядьте и разберитесь в технологиях, подтяните скиллы. Так, чтобы потом на собесе можно было ответить за каждое слово в своём резюме.
Надежда на болтовню
Отдельный вид кандидатов — «авось проскочу». Ставка делается на то, что:
спросят не то
не будут вдаваться в детали
поговорим про жизнь, и меня возьмут
Серьёзно. Это работает? Иногда — да. У меня были такие собесы. Но знаете, в чём разница?
Я был готов в любой момент пояснить за каждую строчку в резюме.
Хотите код на собесе? — Да легко.
Хотите лайфкодинг? — Пожалуйста.
Хотите автотест прямо сейчас? — Давайте сделаю.
Просто меня об этом не просили. А не потому что я надеялся на «пронесёт».
Вот поэтому такие люди и появляются: жадность, инфантильность, надежда на удачу и вера в то, что все вокруг такие же. Но нет. Не все такие. И если вы честно пашете, растёте и отвечаете за базу — вы уже не в большинстве. Вы — в меньшинстве.
Как распознать накрутку опыта?
Многие кандидаты, к счастью, не слишком искусны в создании правдоподобных легенд. И в большинстве случаев они сами себя выдают на элементарных вещах. Один из самых простых и эффективных способов — задать те же вопросы на разных этапах: на скрининге, на техническом интервью, а потом — на финальном. Часто оказывается, что версии истории вдруг начинают отличаться. Видимо, кандидат выстроил у себя в голове некий сценарий, но, как говорится, стресс — не лучший помощник при запоминании вымышленных деталей. Поэтому расхождения в описании одного и того же места работы — тревожный звоночек. А вы тем временем — почти детектив.
Ещё один надёжный метод — техническое интервью. Если в резюме указано, что человек работает в профессии уже восемь лет, а на собеседовании путается в логических операторах, это, мягко говоря, вызывает вопросы. Конечно, все мы волнуемся, но между волнением и полным отсутствием базовых знаний — большая разница.
Хороший индикатор — глубина ответов. Допустим, кандидат заявляет, что два года участвовал в каком-то процессе. Вы уточняете детали — в ответах скользящие обобщения и максимум общих слов. Это может быть повод покопать чуть глубже. Пара наводящих вопросов — и становится понятно, был ли там реальный опыт или только желание, чтобы он был.
Ну и классика жанра — практическое задание. Особенно если речь про автоматизацию. Открытый файл, просьба накидать несколько автотестов — и всё становится ясно. Специалист с реальным опытом без особых усилий напишет 5–10 тестов в нормальном, рабочем стиле. А если вместо этого — напряжённый взгляд, молчание и внутренний монолог в стиле «где же мой боевой Stack Overflow?» — возможно, опыта не так уж и много. Конечно, если это совсем начинающий кандидат — другое дело. Но если в резюме указано 5+ лет — ожидания чуть иные.
Накрутка опыта — не просто сомнительный приём, это плохая привычка. К счастью, она довольно легко обнаруживается — особенно если подходить к делу с умом и лёгкой иронией.
Советы новичкам
Если вы, уважаемый читатель, только начинаете свой путь в индустрии, искренне рекомендую формировать опыт честно и последовательно, без приписок чужих заслуг. На самом деле, это проще, чем может показаться. Куда разумнее — сделать 5–10 собственных пет-проектов, пройти действительно качественные курсы, прочитать статьи, попробовать технологии на практике, потратить на всё это несколько месяцев, а может, и полгода — но зато погрузиться в тему по-настоящему.
Такой подход даст вам не только знания, но и уверенность. Вы будете чувствовать себя в новой сфере, как рыба в воде. А главное — совесть чиста, репутация крепка, зарплата растёт, и в голове — никакой каши из выдуманных историй. Только здравый смысл, реальный опыт и спокойствие при любом вопросе от рекрутера. Это путь, который даёт не только оффер, но и внутреннее удовлетворение.
Если же вы всё-таки решили «украсть немного опыта», то тут уж, извините, придётся соответствовать. За каждую строку в резюме, за каждое упомянутое слово и технологию — нужно быть готовым объяснить, показать, доказать. Портфолио, рекомендации, осознанные ответы — всё должно быть на месте. Это база, без которой фальшь рано или поздно всплывёт.
Если же путь был выбран по принципу «накрутил и забыл», то, боюсь, велик риск оказаться в ряду тех, кто потом фигурирует в статьях вроде этой — в качестве поучительного примера. Надеюсь, не вашего.
Заключение
Если в резюме «10 лет опыта», а на практике — 10 минут смущения, виноват не вопрос, а ответ.
Мир IT даёт шанс всем. Но требует быть готовым, а не просто выглядеть. И, пожалуйста — прежде чем писать «Senior», проверьте, что внутри действительно есть знания, а не только заголовок.
Ну а если вам всё ещё кажется, что «пронесёт» и никто не заметит накрутку — не забудьте перезарядить берёзовую палку.
Источник: https://habr.com/ru/articles/911920/