Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.
- Описание проекта и общее оформление
- Общая работоспособность проекта
- Качество кода, стандарты кодирования, линтеры
- Автоматические тесты
- CI/CD, автоматизация, деплой
- Система контроля версий (VCS), Git
- Архитектура, шаблоны, построение кода
- Работа над заданием, сбор фидбека
- Где взять тестовые задания?
- Как учиться писать более лучший код
- А можно не делать тестовое?
- Итого
- Полезные ссылки
Я довольно часто общаюсь с начинающими разработчиками, помогаю им на различных площадках и в чатах. Отвечаю на вопросы как общего характера, так и связанные с какой-либо технологией или отладкой кода. Также я иногда провожу код-ревью проектов, над которыми работают ребята — это бывают как проекты на Хекслете, открытые (опенсорсные) проекты, так и тестовые задания самого разного размера.
Я помню, как сам делал самое первое тестовое задание. Оно было с одной стороны простым, но с другой — сложным, нужно было сделать на PHP без фреймворков небольшое приложение для добавления статей и загрузки древовидных комментариев. Подобное задание можно сделать не только на PHP, но и на любом языке для веба — Go, Python, Ruby, Java, NodeJS.
Несмотря на то, что стек технологий разнится, ошибки могут быть типовыми:
- Код не запускается или не выполняет поставленную задачу
- Отсутствует описание (README). Соответственно, нет инструкций по запуску
- Код не соответствует принятым стандартам кодирования и best practices
- Задание было прислано в архиве или Google Docs, то есть не использовалась система контроля версий, например, Git.
В тексте я поделюсь советами, которые помогут улучшить ваше тестовое задание, узнать о существовании полезных инструментов и развить навыки разработки и развертывания приложения. Это советы абсолютно универсальны — их можно применить не только к тестовому заданию, но и вообще к любому вашему проекту на Github.
Описание проекта и общее оформление
Добавьте описание того, что делает ваш проект, даже если это ToDo App — приложение для ведения задач. Опишите, какие используются технологии, версии языка и библиотек. Укажите требования к операционной системе и пакетам, которые необходимо установить. Опишите команды, которые могут использоваться для развертывания приложения, чтобы его можно было разрабатывать или демонстрировать.
Если у приложения есть рабочая демонстрация, укажите на нее ссылку. Это может быть ссылка на GitHub Pages, Heroku или ваш домен и сервер, где приложение развернуто и его можно посмотреть.
Проверьте, что в тексте нет ошибок. Не все владеют русским или английским языком идеально. Но даже текстовые редакторы кода (например, VSCode) подсвечивают все опечатки.
Описание проекта стоит делать либо на английском языке, либо на том языке, который используется в компании и на котором вы получили тестовое задание. Если это просто пет-проект для тренировки, который выложен на GitHub, старайтесь использовать английский язык. Возможно, если вы находитесь в поиске работы, с вами даже свяжется зарубежная компания. Для перевода текстов я обычно использую Deepl.com — для перевода он использует машинное обучение, поэтому часто там переводы лучше, чем в Google Translate.
Если вы делаете приложение с веб-интерфейсом (например, сайт, где можно публиковать новости), используйте готовое решение, не занимайтесь версткой и стилизацией самостоятельно. Для таких целей можно использовать фреймворк Bootstrap.
Когда вы работаете над тестовым заданием, не забудьте приложить текст задания в README или отдельно в проект. Ревьюер может его просто не иметь при себе, или забыть какие-то мелочи. Также вы сможете это задание использовать в вашем портфолио, в таком случае текст задания будет служить описанием проекта.
Например, так выглядит репозиторий без описания:
А так выглядит репозиторий проекта с подробным README:
Общая работоспособность проекта
Если вы делаете тестовое задание, обязательно сверяйтесь с условиям. Если их нет, стоит их уточнить. Спросите себя — достигнута ли поставленная цель? Нажимаются ли кнопки? Работает ли регистрация? Сохраняются ли данные? Об этом часто забывают из-за неопытности. Вы можете сфокусироваться на чем-то одном и забыть про остальные части приложения.
Очень обидно, когда твою работу не примут из-за того, что ты где-то не поставил скобку или опечатался. Про тесты я расскажу дальше, но помните — ваше решение должно быть рабочим. Да, бывают моменты, когда просят сделать не рабочее решение, а абстрактное. Например, описать интерфейсы классов, использовать заглушки, но обычно это указано в ТЗ.
Качество кода, стандарты кодирования, линтеры
Есть теория, которая называется «Теория разбитых окон». В ней говорится, что «Если в здании разбито одно стекло и никто его не меняет, то через некоторое время в этом здании не останется ни одного целого окна». Такой подход актуален и для кода. Если мы начинаем забивать на соблюдение стиля кода, то в итоге начинаем писать как попало — и перестаем обращать внимание на весь код вообще, различные подходы и здравый смысл.
Линтеры — это инструменты (скрипты), которые проверяют код на соответствие настроенным стандартам. Они нужны для того, чтобы было единство кода как внутри проекта, так и между множеством разработчиков. То есть линтеры нужны для того, чтобы другой разработчик мог с легкостью писать код и не думать о том, что ему использовать — табы или пробелы.
Сравните. Оба примеры написаны на PHP с использованием условной конструкции, но в одном случае стандарты игнорируются:
if ($a === $b)
{
bar();
}
elseif ($a > $b) {
$foo->bar($arg1);} else
{
BazClass::bar($arg2, $arg3);
}
А в следующем случае разработчик использует линтер для соблюдения стандартов:
if ($a === $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar($arg2, $arg3);
}
Чтобы разработчики не ругались о том, какое форматирование использовать, они договариваются о едином стандарте для кода. В каждом языке есть общепринятые стандарты. Иногда стандартов может быть несколько. Еще реже бывают отдельные стандарты внутри проекта или внутри компании. В PHP общепринятый стандарт — PSR, для JS чаще всего используется стандарт от Airbnb.
Современные редакторы позволяют настроить проверку и исправление ошибок как при редактировании кода, так и по специальной команде, например, по горячей клавише. При необходимости правила линтера могут изменяться — например, можно не проверять определенные файлы. Правила линтера могут даже расширяться — например, сортировать импорты, либо указывать возвращаемый тип у функции. Обычно использование линтера — это санитарное правило, как мытье рук перед едой.
На Хекслете есть проекты — практические задания разной степени сложности, где нужно сделать свое приложение по техническому заданию. Во время код-ревью этих проектов используется вот такой порядок проверки:
Проверка кода идет по пунктам указанным ниже. Если на верхнем уровне есть серьезные проблемы, то проверка останавливается до исправления.
- Конфигурация (линтеры, запуск тестов, CI).
- Внешний вид и общая работоспособность.
- Тесты.
- Авторизация.
- Правильное использование роутинга (имена, именованные маршруты).
- Оформление шаблонов.
- Оформление моделей.
- Оформление обработчиков.
Если игнорируются ошибки линтера на самом верхнем уровне, код не проходит ревью, а возвращается студенту с просьбой исправить замечания. Обычно линтер становится частью CI/CD (про это ниже), поэтому если при написании вы забудете проверить свой код, это сделает скрипт.
Кроме линтера можно использовать и различные онлайн-инструменты для проверки качества кода. В проектах Хекслета используется CodeClimate — этот сервис анализирует код и может подсветить моменты, которые стоит поправить. Например, глубокую вложенность с условиями и циклами.
Читайте также: Как пройти собеседование на тестировщика: все этапы и вопросы
Автоматические тесты
В современной разработке от тестирования никуда не деться. Умение писать тесты и тестируемый код сейчас встречается практически в каждой вакансии. И сама культура написания тестов существует уже довольно давно. Если вы откроете любую хорошую книгу по разработке, наверняка найдете там главу или целый раздел, посвященный написанию тестов.
Грамотные тесты могут ускорять разработку, плохие, неудобные или медленные тесты — наоборот. Их не хочется запускать, они могут часто ломаться от каждого изменения или выполняться несколько часов.
Современные фреймворки и библиотеки помогают писать простые и легкие тесты. Например, во фреймворке Laravel есть множество инструментов для этого: утверждения (assertions) для проверки данных, стабы для внешних запросов, генерация тестовых данных.
Для JS используется jest и обертки-библиотеки, которые помогают писать тесты. Для фронтенда есть библиотека testing-library — ее можно использовать с любым популярным фреймворком React/Angular/Vue. Для PHP повсеместно используется PHPUnit. Обязательно изучите эти инструменты и попробуйте написать парочку тестов.
Старайтесь не писать низкоуровневые тесты. Вы могли видеть пирамиду тестирования, где на нижнем уровне находятся юнит-тесты, а на самом верху — интеграционные. Это довольно условное деление, ведь что-то может быть отдельным компонентом, а что-то — целой системой. Все зависит от того, как посмотреть.
Большие фреймворки (Laravel, Symfony) уже обладают удобными инструментами для тестирования. Вы сможете с легкостью написать один функциональный тест, который будет проверять основную логику приложения. Один высокоуровневый тест может заменить десяток низкоуровневых. Если тесты проходят быстро, это удобно.
Модульные тесты полезны там, где нужно изменить какой-то кусок кода со сложной логикой, если в нем нет побочных эффектов — например, вызова внешнего сервиса или обращения к базе. Но если у вас уже есть верхнеуровневый тест, который покрывает этот кусок кода, смысла в модульном тесте по большому счету нет.
По теме тестов есть полезная статья «Бережливое тестирование, или Почему модульные тесты хуже, чем вы думаете».
CI/CD, автоматизация, деплой
Теперь, когда вы стали использовать линтеры и тесты, вы можете заставить их работать и помогать вам на регулярной основе.
Что такое CI/CD? Если коротко, в процесс выкладки кода (например, обычный git push
на GitHub) встраивается автоматизация и различные проверки. Как это может выглядеть? Вы разрабатываете что-то у себя, пишете код. Проверили — все работает. Делаете коммит, пуш, код уходит на GitHub. Дальше там могут происходить различные действия в зависимости от того, что вы настроили.
Самый простой вариант CI/CD — запускается сборка, ставятся зависимости, запускаются линтеры, тесты. Более сложный вариант — происходит деплой (публикация) вашего приложения, линковка, создание нового сервера.
Читайте также: Как разработчику правильно описать хард-скиллы в своем резюме
Если ваш проект выложен на GitHub, вы можете воспользоваться бесплатным решением платформы — Github Actions. Так как GitHub — это про сообщество и опенсорс, можно переиспользовать скрипты-экшены других разработчиков. Например, в PHP можно использовать экшен, который проверяет зависимости приложения на уязвимости.
Конечно же, можно определять и свои команды. Из этих команд вы собираете цепочку, в которой они выполняются последовательно друг за другом. Например:
- Скачать исходный код
- Установить зависимости
- Подготовить проект (например, создать необходимые переменные или миграции)
- Запустить линтер
- Запустить тесты.
Все действия будут совершаться без участия программиста и помогут отследить ошибку, пока ведется разработка.
Вернемся к тестовому заданию со статьями. Напомню, что нужно сделать приложение, в котором можно создать статью и оставить комментарии. При этом комментарии должны быть в виде дерева, как на Хабре. Вы знаете, что ваше приложение работает 100%, ведь вы даже написали тесты. Будет ли проверяющий запускать код? Допустим. Но что, если нужно проверить аналогичные проекты у 20 человек? Тогда вряд ли он это сделает. Даже если скачать и развернуть ваше приложение займет две минуты, то на всех уйдет минут 40. При этом каждому нужно посмотреть код, оценить его, дать фидбек.
Если вы выложите ваше приложение куда-то, ревьювер сможет подергать методы или прожать кнопки. А также наверняка оценит то, что вы сэкономили ему время.
Для этого можно использовать различные облачные сервисы. Для бэкенда можно использовать Heroku. Он интегрируется с GitHub и позволяет деплоить приложение по команде git push
. Особенность Heroku в том, что он не обладает своей файловой системой, поэтому там нельзя хранить ничего, кроме кода, но можно подключить различные хранилища, например, базу данных. Есть бесплатные тарифы, которые идеально подойдут для выполнения такой задачи.
При этом, если вы используете какие-то проверки — например, линтеры и тесты, то код не будет деплоиться Heroku, если они будут провалены.
Для фронтенда можно использовать Vercel, Netlify, Github Pages. Кроме того, там тоже можно настроить сборку приложения и автоматизировать деплой.
Читайте также: Не бояться, решать задачи и проверить звук в Zoom: Как джуниор-разработчику подготовиться к собеседованию
Система контроля версий (VCS), Git
Думаю, вы уже догадались, что нужно использовать Git. Именно вокруг него строятся различные интеграции и автоматизации. Прошли те времена, когда разработчики хранили на своем жестком диске копии файлов index.php, index_backup.php, index2.php на случай, если что-то пойдет не так.
Git позволяет работать одновременно над разными кусками кода, сравнивать их между собой. Хранит в себе историю изменений — кто, когда и что поменял. Использование этого инструмента — это еще одна санитарная норма в современной разработке.
Историю коммитов можно использовать для анализа того, как развивалось приложение, какие решения принимались, оценить навык использования инструмента. Иногда встречается такое, что в проекте за все время существования есть всего один коммит. Обычно я делаю вывод, что разработчик не любит пользоваться этим инструментом и проверяет у себя локально, отправляя в удаленный репозиторий готовое решение.
Старайтесь использовать понятные, краткие описания к коммитам. Желательно на английском языке или хотя бы на том, который принят в компании, для которой вы выполняете задание.
Если есть сложности в работе с Git — пройдите наш курс. Помните, что это теория, которую стоит закреплять на практике.
Я не упомянул здесь Docker. Если вы умеете им пользоваться, это круто. Оформите конфиг и команды для запуска вашего приложения в Docker. Он позволяет упаковать приложение в изолированное окружение (например, настройки веб-сервера, специфические системные утилиты и пакеты), повысить переносимость, а инфраструктура приложения станет иммутабельной.
Архитектура, шаблоны, построение кода
Хаха, а тут советов нет. Выдумывайте сами.
Нет, на самом деле. Задача тестового задания — проверить ваши знания. Конкретные штуки. Например, как вы применяете паттерны, если они нужны. Как структурируете код, какие абстракции выделяете. Тяжело давать советы, которые актуальны для всех. Просто пишите понятный код. Все будет зависеть от вашего опыта и знаний.
В вакансиях вы часто можете увидеть требование «писать понятный, чистый код». На самом деле это тяжело делать, если нет опыта. Поэтому просто пишите код, пишите код, пишите код.
Читайте книги, смотрите доклады, анализируйте код других разработчиков. Старайтесь понять, почему сделано именно так. Анализируйте популярные решения, почему они так реализованы.
Подходы и решения могут быть вообще разными в разных языках — код одного и того же веб-приложения на PHP и Ruby, Python, JS будет выглядеть по-разному. Некоторые решения будут просто не нужны в рамках других языков. Например, паттерны — их придумывают из-за несовершенства и ограничений языков.
Руководствуйтесь здравым смыслом. Например, если у вас есть шаблон странички и какие-то компоненты, будет некорректно обращаться к базе данных из шаблона. Кроме того, имена переменных должны быть понятными — избегайте ненужных сокращений, лишнего контекста. Если у вас какие-то данные или процедуры дублируются, значит, что это какая-то абстракция — и ее стоит выделить отдельно.
Если начитаться про паттерны, SOLID и другие принципы, можно легко уйти в оверинжиниринг (придумывать функционал на будущее). Старайтесь сделать свое решение простым и понятным (KISS) — ведь скорее всего то, что вы заходите добавить, вам никогда не понадобится (YAGNI). Готовьтесь обосновывать те решения, которые приняли в коде.
Программирование — это творческий процесс, который контролируете только вы. Практикуйтесь.
Читайте также: Как решить задачу, если непонятно, с чего начать: советы от Хекслета
Работа над заданием, сбор фидбека
Когда вам предлагают сделать тестовое задание, обычно сразу же указывают дедлайн. В других случаях компания может спросить у разработчика, сколько времени у него оно займет. Например, справитесь ли вы за неделю, либо вам понадобится всего два дня.
Без опыта невозможно дать грамотную оценку трудозатрат. Проблема с оценкой времени есть даже у опытных разработчиков. Поэтому прикиньте по времени, сколько вы будете работать над задачей, и возьмите немного времени с запасом.
Если возникают ситуации, когда вам непонятна формулировка задания или требования, лучше спросить, а не играть в угадайку. Потому что задания могут быть действительно неверно сформулированы, либо даже сделаны таким образом, чтобы побудить вас задавать вопросы.
Я слышал о ситуациях, когда разработчику было непонятно тестовое задание и он задавал по нему уточняющие вопросы. На это заказчик (работодатель) говорил, мол, вы не слишком самостоятельны, раз задаете много вопросов. Кажется, что это не очень правильно и нужно дважды подумать, прежде чем идти в такую компанию.
Если есть вопросы, спрашивайте. Если вы задерживаетесь с заданием, сообщайте об этом. Возможно, можно будет отправить задание попозже или частично завершенное. Важно иметь обратную связь, а не пропадать из поля зрения, если что-то пошло не так. Вопросы, связанные непосредственно с разработкой, лучше не спрашивать — типа «У меня проблема с такой-то библиотекой, которую вы сказали использовать, поможете?». Ведь то, как вы разберетесь с технологией, тоже является частью тестового задания.
Можно сразу же поделиться ссылкой на репозиторий, чтобы ревьювер мог смотреть за ходом разработки.
Где взять тестовые задания?
У Хекслета есть репозиторий, в котором сообщество делится тестовыми заданиями. Сюда присылают ссылки студенты, сторонние разработчики и даже сами компании. Задания самого разного уровня, на любой стек и уровень.
Как учиться писать более лучший код
Практика, практика и еще раз практика. Как говорилось выше — пишите больше кода, читайте книги, изучайте проекты. У Хекслета есть множество проектов, в которых можно принять участие. За этими проектами следят и, как правило, хорошие практики переносятся из одного проекта в другой. Даже стек особо не важен. Например, в каждом проекте используется Makefile и есть подробное ридми для описания инструкций по работе с проектом. Вы можете подглядеть, как писать тесты, как работать с популярным фреймворком (Laravel, Ruby On Rails) и даже как создать инфраструктуру с помощью Terraform и Ansible (вряд ли это будет в вашем тестовом, ну а вдруг).
А можно не делать тестовое?
На самом деле тестовое задание предлагается далеко не всем. Чаще всего их дают начинающим разработчикам или тем, у кого нет портфолио. В резюме соискатели пишут, что владеют определенными технологиями, и это нужно проверить. Бывает, что у компании специфический стек (типа Clojure), но у кандидатов нет опыта по этой технологии. Тогда могут найти опытного человека (который уже поработал программистом), но без опыта с нужной в компании технологией.
По моему опыту, чем больше у разработчика полезного кода на Github, тем выше вероятность, что ему не придется делать тестовое задание. Например, проекты Хекслета, открытые проекты, пет-проекты или тестовые задания. Например, я делал тестовое один раз, когда у меня не было даже проектов Хекслета. Потом это же тестовое пригодилось в поиске следующей работы, и в трудоустройстве в другую компанию.
Читайте также: Как понять, что перед вами плохой разработчик
Итого
В этой статье мне хотелось рассказать вам про технологии, подходы и практики, которые можно использовать при работе над тестовым заданием.
Кто-то скажет, что не нужно насчет всего этого заморачиваться. Но я постоянно вижу, что кандидаты выполняют тестовое задание, но его толком не проверяют просто потому, что оно оформлено криво.
Часть перечисленных практик уже являются стандартами разработки. Попробуете один-два раза и поймете, насколько круто их использовать. Вы покажете, что знакомы с кучей технологий хотя бы поверхностно, и что это для вас не пустой звук. Тогда с вас останется просто писать грамотный код.
Полезные ссылки
Git
GitHub — git-хостинг и сообщество разработчиков
Git How To: курс обучения Git на русском
Стиль именования коммитов / Хабр
Как следует писать комментарии к коммитам
Автоматизация, CI/CD, деплой
Как и для чего использовать Docker
Вебинар: Stateful vs. Stateless
Никита Соболев — Автоматизируем все с GitHub Actions. Доклад, рассказывающий, что такое Github Actions, с примерами использования
Code Climate — платформа для статистического анализа и поиска проблемных мест. Также позволяет оценивать покрытие кода с помощью скрипта (показывает бейджик с процентом покрытия тестами)
Eslint — линтер для Javascript
airbnb style guide — популярный стайлгайд для Javascript
Jest — фреймворк тестирования для Javascript
Testing-library — библиотека для тестирования фронтенда в Javascript
PHPUnit — фреймворк для тестирования в PHP
PHP_CodeSniffer — популярный линтер для PHP
PSR-12 — современные стандарты кодирования для PHP
Vercel и Netlify — платформы для развертывания приложения (статика, фронтенд)
Heroku — платформа для облачного развертывания приложения, подходит для бэкенд-приложений
Дополнительно
Как быстро стоит делать тестовое
Рефакторинг и Паттерны проектирования
Продуманная оптимизация
The Twelve-Factor App (Русский перевод)
Список тестовых заданий для прокачки
Книги
Совершенный код
Видео
Доклады по ментальному программированию. Про важность нейминга и семантичности кода
- Часть 1
- Часть 2
Доклад «Снесите это немедленно»
Как писать качественный и понятный код? Чистые функции
Начинаем писать тесты (правильно)
Никогда не останавливайтесь: В программировании говорят, что нужно постоянно учиться даже для того, чтобы просто находиться на месте. Развивайтесь с нами — на Хекслете есть сотни курсов по разработке на разных языках и технологиях