Как мы перестали проверять всё подряд одной задачей и ускорили проверку тестовых на стажировку

    Никто не любит тестовые задания: долго, дорого, не всегда показательно. Но на стажировке от тестовых не отказаться из-за большого потока желающих без портфолио и опыта работы. Несколько лет мы в Контуре проверяли бэкендеров одной большой задачей, которую придумывал и проверял один разработчик. А потом все сломалось и поэтому изменилось. Рассказываем, как не надо делать тестовое, и как теперь выглядит наш отбор на стажировку. 

    Почему на стажировку нельзя без тестового

    Ежегодно мы получаем около 1 000 заявок на стажировку. Поговорить с каждым кандидатом не получается — на это уходит много времени и сил. Посмотреть на портфолио чаще всего тоже нельзя, потому что аудитория стажировки — студенты. Поэтому в отборе на стажировку не обойтись без тестового: с ним мы не тратим зря время кандидатов, HR’ов и собеседующих разработчиков. 

    Раз уж отказаться от тестового нельзя, оно должно быть интересным, занимать не очень много времени на выполнение и отражать требования компании к разработчикам. Теперь у нас шесть задач, которые проверяют базовые знания и нужные нам навыки. Но это сейчас мы такие оптимизированные и разумные, раньше было по-другому. Сначала были грабли, увольнения и затянутый отбор. 

    Одна голова на все процессы

    В 2019 году тестовое на стажировку в Контур — одно большое задание, которое проверяло сразу несколько навыков: базовые знания программирования, чистый код, алгоритмы, структуры данных и что-нибудь еще, что мы проверяли, проходя мимо. Как решить, что именно вот этот кусок задания за чистоту кода, а этот — за структуру данных? Как сделать единообразную шкалу оценок и проверить тестовые?

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

    Задачу он придумывал долго, потому что параллельно работал над текущими тасками в проекте. Автотесты были, но ручная проверка все равно сжирала много времени.

    Задача в тестовом была сложной. Ходила шутка (или не шутка), что тот, кто решит тестовое, может сразу трудоустраиваться джуниором, а не стажером. 

    Долго так работать не получится. И у нас не получилось. 

    Больше голов нет

    Державший весь этот контекст разработчик уволился посреди отбора на стажировку (не из-за нее). Тогда кампанию затянули, но довели до конца.  

    До этого мы годами не трогали тестовое, потому что  ̶р̶а̶б̶о̶т̶а̶е̶т̶ ̶—̶ ̶н̶е̶ ̶т̶р̶о̶г̶а̶й̶. Но увольнение стало поворотным моментом. Накопилось несколько других противоречий: большое тестовое сложно придумать, сложно сделать и сложно начать решать. Проверка затягивается (пока автотесты, пока код-ревью…). Басфактор: некому подхватить, если у создателя тестового завал/болезнь/увольнение. Чтобы прочувствовать боль до конца, посмотрите, как выглядело последнее мегатестовое.

    Все сошлось — нужно было переделывать.

    Подопытные проекты

    Раскатывать изменения сразу на стажировку не стали, начали экспериментировать на проектах поменьше и стартанули со Школы промышленной разработки (Шпора). Там проблемы с тестовым были почти такие же, как у стажировки:

    1. Слишком сложно для студентов 2-3 курсов.

    2. Студенту трудно подступиться к такому большому заданию.

    3. Теряется мотивация: даем часть автотестов, студент отправляет решение и даже не представляет, что оно не проходит скрытые автотесты. Одна опечатка или глупая ошибка — всё, автотесты не проходят, ты не можешь сдать задачу, а найти ошибку не получается. 

    К решению проблемы привлекли бывших студентов курсов — разработчиков Контура. Сформулировали, что хотим проверять, решили делать это через 6 задач (одна задача — один навык), сделали и разместили на Ulearn — это наша площадка с курсами по программированию. В ней есть все нужные для тестового инструменты: автотесты, антиплагиат, инструменты для код-ревью.

    Нам все нравилось, но важнее была реакция целевой аудитории — студентов-будущих стажеров. Позвали порешать новое тестовое прошлогодних шпорунов (как целевую аудиторию, ведь они совсем недавно выпустились или продолжают учиться) и получили хорошую обратную связь. Результаты почувствовали и в бою:

    1. Тестовые сдавали быстрее. Если раньше большую часть тестовых мы получали ближе к дедлайну, то в этот раз много решений получили в первые дни после публикации.

    1. 70 решенных тестовых и 138 тестовых с хотя бы одной задачей вместо 63, решенных в предыдущем году.

    Мы признали эксперимент успешным и перешли к изменению тестового на стажировку. 

    Что и как оцениваем?

    «Мы решили проверять у кандидатов умение писать чистый код, способность разбираться в чужом коде, навык писать код с нуля, понимание алгоритмов, знание, как искать информацию, чтобы разобраться в задаче и решить ее. Эти навыки выбрали, как часто встречающиеся в работе разработчика, плюс такие у нас представления о хорошем стажере и разработчике Контура», — рассказывает Костя Воливач, один из создателей нового тестового на C#. 

    Дальше продумали критерии каждого навыка. Наиболее интересное — проверка чистоты кода. «Мы попытались сформулировать критерии, исходя из принципа “код читается чаще, чем пишется”‎», — рассказывает Леша Пепелев, один из создателей тестового и разработчик критериев оценки. Вот что у нас получилось:

    1. Чистый код не врет. Чтение такого кода не превращается в детектив, где тебя пытаются ввести в заблуждение. Намерения чистого кода выражены в именах классов, методов и переменных и совпадают с фактическим поведением. Если метод называется GetNode, то он должен вернуть узел вызывающему коду, а не сложить его в поле класса. Как проверить себя? Уберите из кода тела всех методов. Можно ли по выжимке догадаться, как работает решение?

    1. Чистый код можно читать с любого места. Если решение состоит из набора классов, то каждый из них представляет что-то цельное. Смысл отдельного класса можно увидеть, не заглядывая в другие классы. Как проверить себя? Удалите из класса все методы, оставьте один. Опишите его, отвечая на вопросы «что он такое»‎, а не «что он делает»‎ без ссылок на удаленный код. На уровне отдельного класса удалите из класса все методы, посмотрите на свойства и поля. Если понять суть можно только по использованию, вызывайте рефакторинг. 

    1. У чистого кода явные зависимости. Читающий должен четко понимать, от чего зависит метод и в чем результат его работы. Как проверить? Спросите себя, можно ли при рефакторинге сломать код, если переставить строки местами или удалить вроде бы ненужную строку? 

    Лучшим решением договорились считать такое, на понимание которого ревьювер тратит меньше всего времени (после прохождения всех остальных критериев). 

    Добавляем контекста и боремся с формулировками

    Новое тестовое придумывают два разработчика, каждый берет по три задачи. Чтобы задачи не висели в вакууме и условия воспринимались легче, мы сочиняем для каждой предысторию. Например, в тестовом-2020 есть задача с интерпретатором:

    Остров Кижи появился здесь, потому что один из любимых языков Кости, автора задачи, — Kotlin. Он назван в честь острова в Спб.

    Другая задача на рефакторинг родилась из плохо работающего пульта от телевизора.  «‎Я решил связать неработающий пульт и телик в одну задачу. Сюжет такой: пульт не работает, потому что код написан плохо, есть ошибки. Разработчик очень торопился, поэтому качество кода низкое, а ревью пропущено. Мы написали примерный код, специально его испортили и запутали»‎,— рассказывает Костя Воливач. 

    Ревью задач проводят 10 разработчиков, они проверяют уровень сложности, формулировки и общую концепцию. Метрика такая: если миддл справляется с задачей за час, все ок, если уходит больше времени, задачу нужно пересматривать. 

    Самое сложное в тестовом для авторов — лирика. «В прошлом году мы поняли, что стажеры не понимают формулировки задач. Тогда мы решали вопрос вручную: пришел вопрос по формулировке — идешь в задачу и правишь текст», — вспоминает Костя. В этом году проверили формулировки заранее на программистах и на редакторах — должно стать лучше. 

    Тестовые проверяют 10 разработчиков. Каждый отвечает за проверку одной задачи во всех тестовых.

    Что по метрикам

    В 2019 году с одной большой задачей мы получили 55 тестовых. В 2020 году все шесть задач решили 63 человека, и ещё 281 кандидат решил хотя бы одну задачу. В 2019 году мы проверяли тестовые больше месяца, в 2020 году на это ушло две недели. 

    После всех нововведений стало легче, прогресс стал нагляднее, а значит мы можем реагировать на ход решения. 

    Если мало человек решили все шесть задач, спрашиваем в чатах, что останавливает остальных, делаем рассылки. Если видим, что решают многие быстро, ищем дополнительных проверяющих. 

    По 2021 году у нас пока нет полных данных, но мы уже видим, что скорость сдачи тестового высокая. Автотесты появились только 15 февраля, а к этому моменту у нас уже 28 человек с шестью решенными задачами. 

    Хотите проверить формулировки (ну и посмотреть задачи, конечно)? Набор на стажировку открыт и тестовое лежит на Ulearn. Чтобы посмотреть тестовое и начать решать, вступите в группу

    Контур
    Делаем веб-сервисы для бизнеса

    Комментарии 31

      0
      Почитал мегатестовое и немного бы его изменил. В свое время решал похожее. Там нужно было наоборот многопоточное решение. Оно добавляло изюминку)… и заодно проверку знаний потоков.
        0
        А как изменили бы?
          0
          Операция сжатия/разжатия требовательна к ресурсам процессора. Поэтому я бы предложил зачитывать файл и паралелльно проводить упаковку/распаковку. Это ускорит производительность программы, хотя и повысит потребление ресурсов. Задание при этом усложнится (причём до уровня junior, а может и middle исполнителя), но при этом станет интереснее.
          Да простят меня стажёры!)
        +3
        Теряется мотивация: даем часть автотестов, студент отправляет решение и даже не представляет, что оно не проходит скрытые автотесты. Одна опечатка или глупая ошибка — всё, автотесты не проходят, ты не можешь сдать задачу, а найти ошибку не получается.

        Позвали порешать новое тестовое прошлогодних шпорунов и получили хорошую обратную связь.

        Мы признали эксперимент успешным и перешли к изменению тестового на стажировку.

        Как человек, который не смог выполнить все задания в прошлом году, скажу, что теряться она не перестала. Решаешь задачу. Загружаешь её на ulearn. Он говорит что неправильно, но тест тебе не покажет, а все открытые тесты проходят и неважно, насколько близок ты был к решению. Если бы проверял человек, то он бы вряд ли оценивал так бинарно «работает-неработает».

        В задачах был большой простор для фантазии и много моментов были обозначены как «вот этого не требуем, но если сделаете, то будет круто». Я на этом и погорел — вместо того, что бы сделать все, я сделал не все, но много чего там сделал из раздела extra, в паре задач точно по тысяче строк кода набралось, тогда как для решения нескольких сотен хватало. А поскольку желающих было много, рассматривали в первую очередь тех, кто просто решил все задачи. Самое печальное в этой истории, что месячной работе ревью не дали.

        Второй момент — раздельная проверка навыков ещё сложнее психологически, чем одно большое задание. Вот например одна задача проверяет разумную архитектуру, чистый код. Что это значит? В одних задачах можно писать как попало, а в этой надо продемонстрировать чистоту? Если так, то нарочно писать «некрасиво но быстро» увеличивает уровень стресса — появляются сомнения, что так и надо, что в реальной работе такой код бы ревью не прошёл. Если не так, то не понятно тогда зачем вообще вот это вот всё с кучей заданий, если чисто писать придётся во всех и это тупо больше времени отнимет, не проще ли одну большую решить.

        Так что совет выполняющим эти задания — сделайте сначала все задания что бы работали, а потом оставшееся время полируйте. Если как я — если не переходить к следующему, пока не отполируешь предыдущее, то может просто не хватить времени на всё
          +1
          Привет!) Спасибо за крутой фидбек. Я согласен, что действительно много в прошлом году было под галочкой, если вы всё сделали, то попробуйте сделать вот это, но при этом мы не писали что за это будет и не акцентировали внимание на том, что это надо делать в последний момент. А хороший тайм-менеджмент, чтобы рассчитать свои силы и решить все задачи, уже больше middle навык. Совет возьмём и повесим на первой странице стажировки, чтобы все могли правильно рассчитать свои силы.
          Более того, в новом 2021 году отсутствуют доп задания под галочкой.
          0
          У нас не 1000 желающих была на стажировки, около 200 человек в среднем и мы в какой-то момент отказались от тестовых заданий — сделав упор на личное собеседование. Выяснилось, что умение решать задачи никак не влияет на то насколько кандидат будет успешен у нас, как он вольется в команду, сможет ли, а главное захочет ли работать и тп.
          К собеседованию привлекали хорошего штатного психолога и специалистов — смотрели со всех сторон, насколько адекватный кандидат, насколько он хочет работать у нас и насколько ему интересно у нас будет, насколько он хочет учится, может и хочет ли работать в команде и все такое прочее.
          Студенты, в массе своей, не очень квалифицированные, мы решили брать самых адекватных и учить их до нужного нам уровня.
          Сейчас у нас успешно работают пятеро разработчиков, которые тестовые задачи в свое время, по разным причинам, не решили бы.
            0
            Вы всех 200 человек сразу на собеседование звали? Или как-то фильтровали сначала?
              0
              HR фильтровал, как не скажу, не знаю, у них там свои методики. А 200 человек — это суммарно в течение года. И даже после HR на некоторых много не тратили времени, было сразу видно что не сработаемся. Может быть это субъективный подход, но нам с этими ребятами было дальше работать в одной команде плечом к плечу.
              0
              а как вы определяли, кого из этих 200 позвать на собеседование? или вы все 200 собеседуете?
                0
                Всех собеседовали, но это в течение года. Времени, кстати не много уходило, в среднем 30-40 минут на человека. по некоторым было сразу видно, что они не подходят, специалисты укладывались минут в 20, HR с ним все равно сидел до конца.
              +1
              А если не секрет, чем вы заманивали людей решать ваше тестовое задание?
              Потому как это явно выраженный вариант задачи типа «Ok, я вам её решу, сколько за это заплатите?»

              Ну то есть задачка сама по себе интересная, но слишком серьёзная для того, чтобы решать её «в стол» (хотя бы потому что решение можно улучшать хоть месяц, идеально не будет), а за решение, пригодное для продакшена, принято платить.
                0
                Заманивали возможностью попасть на стажировку. Получить рабочий опыт в крупной компании, прокачаться в промышленной разработке и, возможно, после этого остаться на работу.
                  0
                  У студентов сейчас всё настолько плохо?
                  Человек, который в состоянии написать свой компрессор так, чтобы за него не было мучительно стыдно – imho легко найдёт работу и так. Почему они идут к вам, а не к конкурентам?
                    +1
                    Конкуренты делают такие же тестовые, потому что)
                    У студентов выбор примерно такой: 1) пойти в мелкую фирму, где все непредсказуемо, но туда проще попасть или 2) попробоваться в крупную компанию, где обучение, наставничество, белая зарплата (и прочие плюшки), но с большой вероятностью не попасть.
                    Правильный студент делает так: в январе-феврале, когда объявляют о наборе крупные компании, идет делать все возможные тестовые. К апрелю знает, куда его точно не возьмут. Если никуда не берут, то в мае-июне идет в мелкие компании, куда берут гораздо проще.
                      +3
                      Задание такое, что у человека, способного его _нормально_ сделать, будет выбор: идти стажёром (даже не джуниором) к вам или миддлом «в мелкую фирму». По моему, выбор очевиден. И по зарплате, и по последующей строчке в резюме.

                      Остаются две категории: те, кто сделает кое-как, и те, кто не возьмётся. Точно выбирать надо из первой категории, не из второй?

                      Ну то есть я делаю вывод, что есть что-то за кадром, чего я не вижу. У меня нет оснований подозревать в глупости ни вас, ни претендентов, значит, вижу не всё картину.
                        +1
                        Дело, наверное, в том, что большая часть талантливых студентов не особенно то мечтает вечно работать мидлом в маленькой конторке, которая рада любому, кто умеет код писать. Они хотят работать там, где возможен профессиональный рост, будет у кого учиться и есть куда расти. (Скажем, наши стажеры, отобранные таким способом, статистически в среднем, через полгода-год дорастают до мидла). Они хотят работать там, где есть масштабные задачи, и будет большой эффект от их профессионализма.

                        Наше тестовое работает пока у нас в компании всё это есть и пока мы справляемся рассказывать об этом студентам.
                          0
                          Всё ещё не понимаю. Те же полгода-год можно поработать мидлом в маленькой конторе и потом идти, к примеру, к вам же – уже не стажёром. Или не к вам.

                          Талантливый студент прочитает задание, если заинтересуется – изучит тему, может, даже пойдёт на соответствующие форумы и пообщается с Булатом Зиганшиным и прочими зубрами ru.compress. Поймёт, что тут ему на несколько лет работы хватит :-). И что останавливаться на том, что можно написать за день (overkill для тестового задания, но, может статься, студент полон энтузиазма) глупо. И что – думаете, он в это ввяжется? Или пойдёт писать тестовое задание для тех, кому его можно написать за несколько часов, а отшлифовать до идеала за неделю?

                          Ну просто противно же сдавать работу «на троечку», когда знаешь, что можно лучше. Т.е. для меня выглядит так, что ваше тестовое не давало вам нанимать тех, кто действительно хорош.
                            0

                            Тебе по фактам из этой конторы на твой вопрос никто не ответит. Это екат(любой другой провинциальный город РФ) и это контур, потому можно на стажировку брать людей через такие задания. И не все покрутят пальцем у виска.

                              0

                              Я тоже вначале подумал об отсутствии конкуренции, но глянул – город-миллионник всё-таки, контор должно быть немало.


                              И странна мне не сама возможность найти людей с таким тестовым (и в Питере можно), а критерии отбора, которые оно задаёт: кмк, это люди, которые, с одной стороны, не ценят своё время, а с другой – не перфекционисты, готовы сдать работу, сделанную кое-как, лишь бы в условия вписалась. Ну, ещё собственно способность его выполнить, но это можно проверить заданием попроще :-)

                                0
                                На самом деле это из серии «работающая бедность», когда-то давно (лет 10 назад) я собеседовался туда. На первичном собеседовании дядька возмущался, мол что я себе позволил, не заполнить некоторую личную информацию в первоначальную анкету, которая включала даже родственников и их места работы.
                                К сожалению, что город миллионник, на это почти никак не влияет. Чтобы найти там достойную работу надо пройти подобные унижения, тестовые задания на БЕСПЛАТНУЮ(!!!!!) стажировку, либо исключительно по знакомству.
                                И по факту даже лучше не ИТ сфере, потому что даже в Москве зарплаты не совсем адекватны по сравнению с мировыми, но хоть как-то, а в Екате в 2 раза меньше. При этом прибыль делается хорошая, можно даже залезть в бухгалтерию и посмотреть чистую прибыль контура (800 млн одна головная организация за последний год).
                                Это же смеху подобно. И ведь там в Екате они все убеждены, что они делают одолжение.
                                Поэтому местные шаражки типо контура, сималенда, многих банков ИТ отделений банков это всё дно донное. Ширма, за которой нет ничего, как и вся страна в общем.
                                  0
                                  Город конечно миллионник, но именно толковых контор, где было бы интересно работать — не много. С МСК и в меньшей степени Питером не сравнить.
                                0
                                Так можно и не год, а десять лет проработать в «маленьких конторах», а потом на собеседовании в серьёзных компаниях тебя по-прежнему оценят джуном. И возьмут не тебя, а студента со стажировки.

                                Уж лучше потратить сразу чуть больше усилий, но попасть на старте карьеры в компанию, в которой ты будешь нормально развиваться. Да, поначалу там могут платить меньше денег, чем в маленькой конторе, где тебя сразу возьмут на позицию миддла, но через несколько лет эти «инвестиции» окупятся.

                                Но, действительно, трудно спорить с тем, что талантливых, но ленивых студентов такие тестовые задания отпугнут. И они предпочтут устроиться работать туда, куда проще попасть.
                                  0

                                  Вы уверены, что в компании, дающей такое тестовое, будешь развиваться быстрее, чем в мелких конторах?


                                  Я не спорю с тем, что порой (а студенту – примерно всегда) имеет смысл пойти на меньшую зарплату, но с большими возможностями развития. Но они должны быть. А уж при таком "тестовом" они должны бросаться в глаза. Но представители компании что-то мнутся и не могут их озвучить. Это раз.
                                  А два – отсеются не ленивые, а те, кто правильно оценит потенциал задачи. То есть самые перспективные.


                                  Самое смешное, что та же задача на конкурсе – имеет все перспективы. То есть выкатываем её публично, критерии оценки, текущий рейтинг, как на ICFPC… И можно собирать сливки: зазывать к себе людей, которые решали её не для того, чтобы стать помощником младшего черпальщика, а чтобы показать свою крутизну.

                              0
                              Миддлами сразу после ВУЗа в нормальные конторы не берут, титул миддл подразумевает все-таки солидный опыт промышленной разработки.
                                0
                                Угу. А студентам не дают задания, которые (при нормальном решении) подразумевают навыки и знания миддла минимум.
                      0
                      Неимоверно интересно было-бы увидеть решения этих задач конкретно от разработчиков компании.
                      Уверен, мы бы увидели много замечательного и узнали бы много нового!

                      Лучшим решением договорились считать такое, на понимание которого ревьювер тратит меньше всего времени (после прохождения всех остальных критериев).

                      Отличное решение, кстати могу дать ещё бесплатный совет как сократить количество заявок — выбросить половину, потому-что «а зачем нам нужны неудачники» (С)

                      Заманивали возможностью попасть на стажировку. Получить рабочий опыт в крупной компании, прокачаться в промышленной разработке и, возможно, после этого остаться на работу.

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

                      Почитал новые тестовые, вот это конечно полный финиш:

                      public interface IDbState
                      {
                          ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, string>>> Collections { get; }
                      }


                      И ещё, представляю какой бы крик поднялся, если бы стажёр подсунул бы вам решение, где возвращает кортежи из публичных методов, как будто так и надо. Почему же вы сами так пишете?
                        0
                        Привет, от души посмеялся «Скажем честно, человек который способен написать вон то мегатестовое задание качественно и в сжатые сроки — он и без вашей стажировки обойдётся.». «И ещё, представляю какой бы крик поднялся, если бы стажёр подсунул бы вам решение, где возвращает кортежи из публичных методов, как будто так и надо. Почему же вы сами так пишете?» а тут знаешь критерии от команды к команде разнятся, ревьюеры из одной команды вполне могут допускать такой код, а из другой нет, поругаю Евгения чтоли. Ревью в принципе субъективная штука.
                        Также вот решение от разработчика компании на тестовое прошлого года.
                          0
                          Рад что вам смешно) Мне например эта статься тоже обеспечила некоторое время здорового смеха. И что конкретно смешного в первой цитате?
                            0
                            Да просто то что отчасти это правда.
                        0
                        Yuliya_42 А речь в статье идет только о тестовом на C#? Или я что-то пропустил? Сейчас ради интереса глянул java. Там 1 задание.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                      Самое читаемое