Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.
Я довольно часто общаюсь с начинающими разработчиками, помогаю им на различных площадках и в чатах. Отвечаю на вопросы как общего характера, так и связанные с какой-либо технологией или отладкой кода. Также я иногда провожу код-ревью проектов, над которыми работают ребята — это бывают как проекты на Хекслете, открытые (опенсорсные) проекты, так и тестовые задания самого разного размера.
Я помню, как сам делал самое первое тестовое задание. Оно было с одной стороны простым, но с другой — сложным, нужно было сделать на 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 с использованием условной конструкции, но в одном случае стандарты игнорируются:
А в следующем случае разработчик использует линтер для соблюдения стандартов:
Чтобы разработчики не ругались о том, какое форматирование использовать, они договариваются о едином стандарте для кода. В каждом языке есть общепринятые стандарты. Иногда стандартов может быть несколько. Еще реже бывают отдельные стандарты внутри проекта или внутри компании. В 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. Кроме того, там тоже можно настроить сборку приложения и автоматизировать деплой.
Система контроля версий (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 (Русский перевод)
Список тестовых заданий для прокачки
Книги
Совершенный код
Видео
Доклады по ментальному программированию. Про важность нейминга и семантичности кода
Доклад «Снесите это немедленно»
Как писать качественный и понятный код? Чистые функции
Начинаем писать тесты (правильно)
<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 17:00:26 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="k5FQGSL5Fuagi7P-6i4xBt532w4UMnP2viQhzgNWGhV8QJsu0Ie7hhbIl2bmIcFxHn72pBwFjVQDxLuaUVH9ew";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Как разработчику улучшить свое тестовое задание</title>
<meta name="description" content="Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.">
<link rel="canonical" href="https://ru.hexlet.io/blog/posts/kak-razrabotchiku-uluchshit-svoe-testovoe-zadanie">
<meta property="og:title" content="Как разработчику улучшить свое тестовое задание">
<meta property="og:description" content="Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.">
<meta property="og:image" content="https://ru.hexlet.io/vite/assets/blog_post-7eTyeLLt.webp">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="IH3uFQmQvj9qNaiRYQwEvEkl43LyYndDK2UDkvu2jVrPrCUi--4TX9x2jAltA_TLiSzO2PpVieGWhZnGqbFqNA" />
<script src="/vite/assets/inertia-INZxX8jp.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-6pOtQ3OW.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<link rel="preload" as="image" href="/vite/assets/blog_post-7eTyeLLt.webp"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzY2OSwicHVyIjoiYmxvYl9pZCJ9fQ==--cbbaa606be07bca305bd21d9919235989a1ed289/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Code%20typing-amico.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzk5MiwicHVyIjoiYmxvYl9pZCJ9fQ==--e9d0f30948ea766a7e6bc3e3d56c192344d45fb8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programming-cuate%20(1).png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDA0MywicHVyIjoiYmxvYl9pZCJ9fQ==--e2c6c0775e2308e42fbc5dc592ba2db0470632ca/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programmer-rafiki.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzcyNSwicHVyIjoiYmxvYl9pZCJ9fQ==--2e84f5f94140ee4e22019ac479c290ef48c3fac8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Static%20website-cuate.png"/><link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAzNywicHVyIjoiYmxvYl9pZCJ9fQ==--c9a507d1b30c26185c312c95f68af4f0d8122afa/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programmer-bro.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><div id="app" data-page="{"component":"web/blog/posts/show","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T17:00:26.453Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"QYkrWy7PnbOudMZoLSz65qV7Wu7Sy52NUD932hEF_hKuWOBs3LEw0xg34vAhIwqRZXJ3RNr8Yy_t3-2OQwIZfA","post":{"model_name":"BlogPost","category":{"id":12,"name":"Карьера","slug":"career","state":"published","created_at":"2017-07-21T15:42:21.481Z"},"creator":{"public_name":"Nikolai Gagarinov","id":104929,"is_tutor":true},"tags":[{"id":1119,"slug":"bez-steka","name":"Без стека"}],"id":1915,"title":"Как разработчику улучшить свое тестовое задание","slug":"kak-razrabotchiku-uluchshit-svoe-testovoe-zadanie","state":"published","summary":"Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.","votes_count":34,"created_at":"2022-06-30T09:42:21.279Z","published_at":"2022-06-30T10:57:54.101Z","body":"**Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.**\n\nЯ довольно часто общаюсь с начинающими разработчиками, помогаю им на различных площадках и в чатах. Отвечаю на вопросы как общего характера, так и связанные с какой-либо технологией или отладкой кода. Также я иногда провожу код-ревью проектов, над которыми работают ребята — это бывают как проекты на Хекслете, открытые (опенсорсные) проекты, так и тестовые задания самого разного размера.\n\n::programs\n\nЯ помню, как сам делал самое первое тестовое задание. Оно было с одной стороны простым, но с другой — сложным, нужно было сделать на PHP без фреймворков небольшое приложение для добавления статей и загрузки древовидных комментариев. Подобное задание можно сделать не только на PHP, но и на любом языке для веба — Go, Python, Ruby, Java, NodeJS.\n\nНесмотря на то, что стек технологий разнится, ошибки могут быть типовыми:\n\n1. Код не запускается или не выполняет поставленную задачу\n2. Отсутствует описание (README). Соответственно, нет инструкций по запуску\n3. Код не соответствует принятым стандартам кодирования и best practices\n4. Задание было прислано в архиве или Google Docs, то есть не использовалась система контроля версий, например, Git.\n\nВ тексте я поделюсь советами, которые помогут улучшить ваше тестовое задание, узнать о существовании полезных инструментов и развить навыки разработки и развертывания приложения. Это советы абсолютно универсальны — их можно применить не только к тестовому заданию, но и вообще к любому вашему проекту на Github.\n\n## Содержание\n\n## Описание проекта и общее оформление\n\nДобавьте описание того, что делает ваш проект, даже если это ToDo App — приложение для ведения задач. Опишите, какие используются технологии, версии языка и библиотек. Укажите требования к операционной системе и пакетам, которые необходимо установить. Опишите команды, которые могут использоваться для развертывания приложения, чтобы его можно было разрабатывать или демонстрировать.\n\nЕсли у приложения есть рабочая демонстрация, укажите на нее ссылку. Это может быть ссылка на GitHub Pages, Heroku или ваш домен и сервер, где приложение развернуто и его можно посмотреть.\n\nПроверьте, что в тексте нет ошибок. Не все владеют русским или английским языком идеально. Но даже текстовые редакторы кода (например, VSCode) подсвечивают все опечатки.\n\nОписание проекта стоит делать либо на английском языке, либо на том языке, который используется в компании и на котором вы получили тестовое задание. Если это просто пет-проект для тренировки, который выложен на GitHub, старайтесь использовать английский язык. Возможно, если вы находитесь в поиске работы, с вами даже свяжется зарубежная компания. Для перевода текстов я обычно использую [Deepl.com](http://deepl.com/) — для перевода он использует машинное обучение, поэтому часто там переводы лучше, чем в Google Translate.\n\nЕсли вы делаете приложение с веб-интерфейсом (например, сайт, где можно публиковать новости), используйте готовое решение, не занимайтесь версткой и стилизацией самостоятельно. Для таких целей можно использовать фреймворк [Bootstrap](https://getbootstrap.com/).\n\nКогда вы работаете над тестовым заданием, не забудьте приложить текст задания в README или отдельно в проект. Ревьюер может его просто не иметь при себе, или забыть какие-то мелочи. Также вы сможете это задание использовать в вашем портфолио, в таком случае текст задания будет служить описанием проекта.\n\nНапример, так выглядит репозиторий без описания:\n\n\n\nА так выглядит репозиторий проекта с подробным README:\n\n\n\n## Общая работоспособность проекта\n\nЕсли вы делаете тестовое задание, обязательно сверяйтесь с условиям. Если их нет, стоит их уточнить. Спросите себя — достигнута ли поставленная цель? Нажимаются ли кнопки? Работает ли регистрация? Сохраняются ли данные? Об этом часто забывают из-за неопытности. Вы можете сфокусироваться на чем-то одном и забыть про остальные части приложения.\n\nОчень обидно, когда твою работу не примут из-за того, что ты где-то не поставил скобку или опечатался. Про тесты я расскажу дальше, но помните — ваше решение должно быть рабочим. Да, бывают моменты, когда просят сделать не рабочее решение, а абстрактное. Например, описать интерфейсы классов, использовать заглушки, но обычно это указано в ТЗ.\n\n## Качество кода, стандарты кодирования, линтеры\n\nЕсть теория, которая называется «[Теория разбитых окон](https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BE%D1%80%D0%B8%D1%8F_%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%82%D1%8B%D1%85_%D0%BE%D0%BA%D0%BE%D0%BD)». В ней говорится, что «Если в здании разбито одно стекло и никто его не меняет, то через некоторое время в этом здании не останется ни одного целого окна». Такой подход актуален и для кода. Если мы начинаем забивать на соблюдение стиля кода, то в итоге начинаем писать как попало — и перестаем обращать внимание на весь код вообще, различные подходы и здравый смысл.\n\n[Линтеры](https://ru.hexlet.io/blog/posts/linter) — это инструменты (скрипты), которые проверяют код на соответствие настроенным стандартам. Они нужны для того, чтобы было единство кода как внутри проекта, так и между множеством разработчиков. То есть линтеры нужны для того, чтобы другой разработчик мог с легкостью писать код и не думать о том, что ему использовать — табы или пробелы.\n\nСравните. Оба примеры написаны на PHP с использованием условной конструкции, но в одном случае стандарты игнорируются:\n\n```php\n\nif ($a === $b) \n{\n bar();\n} \nelseif ($a > $b) {\n $foo->bar($arg1);} else \n{\n\tBazClass::bar($arg2, $arg3);\n}\n```\n\nА в следующем случае разработчик использует линтер для соблюдения стандартов:\n\n```php\nif ($a === $b) {\n\tbar();\n} elseif ($a > $b) {\n\t$foo->bar($arg1);\n} else {\n\tBazClass::bar($arg2, $arg3);\n}\n```\n\nЧтобы разработчики [не ругались](https://www.youtube.com/watch?v=SsoOG6ZeyUI) о том, какое форматирование использовать, они договариваются о едином стандарте для кода. В каждом языке есть общепринятые стандарты. Иногда стандартов может быть несколько. Еще реже бывают отдельные стандарты внутри проекта или внутри компании. В PHP общепринятый стандарт — [PSR](https://www.php-fig.org/psr/psr-12/), для JS чаще всего используется стандарт от [Airbnb](https://github.com/airbnb/javascript).\n\nСовременные редакторы позволяют настроить проверку и исправление ошибок как при редактировании кода, так и по специальной команде, например, по горячей клавише. При необходимости правила линтера могут изменяться — например, можно не проверять определенные файлы. Правила линтера могут даже расширяться — например, сортировать импорты, либо указывать возвращаемый тип у функции. Обычно использование линтера — это санитарное правило, как мытье рук перед едой.\n\nНа [Хекслете](https://ru.hexlet.io/) есть проекты — практические задания разной степени сложности, где нужно сделать свое приложение по техническому заданию. Во время код-ревью этих проектов используется вот такой порядок проверки:\n\n*Проверка кода идет по пунктам указанным ниже. Если на верхнем уровне есть серьезные проблемы, то проверка останавливается до исправления.*\n\n1. *Конфигурация (линтеры, запуск тестов, CI).*\n2. *Внешний вид и общая работоспособность.*\n3. *Тесты.*\n4. *Авторизация.*\n5. *Правильное использование роутинга (имена, именованные маршруты).*\n6. *Оформление шаблонов.*\n7. *Оформление моделей.*\n8. *Оформление обработчиков.*\n\nЕсли игнорируются ошибки линтера на самом верхнем уровне, код не проходит ревью, а возвращается студенту с просьбой исправить замечания. Обычно линтер становится частью CI/CD (про это ниже), поэтому если при написании вы забудете проверить свой код, это сделает скрипт.\n\nКроме линтера можно использовать и различные онлайн-инструменты для проверки качества кода. В проектах Хекслета используется [CodeClimate](http://codeclimate.com/) — этот сервис анализирует код и может подсветить моменты, которые стоит поправить. Например, глубокую вложенность с условиями и циклами.\n\n## Автоматические тесты\n\nВ современной разработке от тестирования никуда не деться. Умение писать тесты и тестируемый код сейчас встречается практически в каждой вакансии. И сама культура написания тестов существует уже довольно давно. Если вы откроете любую хорошую книгу по разработке, наверняка найдете там главу или целый раздел, посвященный написанию тестов.\n\nГрамотные тесты могут ускорять разработку, плохие, неудобные или медленные тесты — наоборот. Их не хочется запускать, они могут часто ломаться от каждого изменения или выполняться несколько часов.\n\nСовременные фреймворки и библиотеки помогают писать простые и легкие тесты. Например, во фреймворке [Laravel](https://laravel.com/) есть множество инструментов для этого: утверждения (assertions) для проверки данных, стабы для внешних запросов, генерация тестовых данных.\n\nДля JS используется [jest](https://jestjs.io/) и обертки-библиотеки, которые помогают писать тесты. Для фронтенда есть библиотека [testing-library](https://testing-library.com/) — ее можно использовать с любым популярным фреймворком React/Angular/Vue. Для PHP повсеместно используется [PHPUnit](https://phpunit.de/). Обязательно изучите эти инструменты и попробуйте написать парочку тестов.\n\nСтарайтесь не писать низкоуровневые тесты. Вы могли видеть [пирамиду тестирования](https://habrastorage.org/getpro/habr/post_images/b6d/7a8/3ed/b6d7a83ed09e1a8046529bebfe02836e.png), где на нижнем уровне находятся юнит-тесты, а на самом верху — интеграционные. Это довольно условное деление, ведь что-то может быть отдельным компонентом, а что-то — целой системой. Все зависит от того, как посмотреть.\n\nБольшие фреймворки (Laravel, Symfony) уже обладают удобными инструментами для тестирования. Вы сможете с легкостью написать один функциональный тест, который будет проверять основную логику приложения. Один высокоуровневый тест может заменить десяток низкоуровневых. Если тесты проходят быстро, это удобно.\n\nМодульные тесты полезны там, где нужно изменить какой-то кусок кода со сложной логикой, если в нем нет побочных эффектов — например, вызова внешнего сервиса или обращения к базе. Но если у вас уже есть верхнеуровневый тест, который покрывает этот кусок кода, смысла в модульном тесте по большому счету нет.\n\nПо теме тестов есть полезная статья «[Бережливое тестирование, или Почему модульные тесты хуже, чем вы думаете](https://medium.com/nuances-of-programming/%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D0%BB%D0%B8%D0%B2%D0%BE%D0%B5-%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8%D0%BB%D0%B8-%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D1%82%D0%B5%D1%81%D1%82%D1%8B-%D1%85%D1%83%D0%B6%D0%B5-%D1%87%D0%B5%D0%BC-%D0%B2%D1%8B-%D0%B4%D1%83%D0%BC%D0%B0%D0%B5%D1%82%D0%B5-24670e16ab0)».\n\n## CI/CD, автоматизация, деплой\n\nТеперь, когда вы стали использовать линтеры и тесты, вы можете заставить их работать и помогать вам на регулярной основе.\n\n[Что такое CI/CD](https://aws.amazon.com/ru/devops/continuous-integration/)? Если коротко, в процесс выкладки кода (например, обычный `git push` на GitHub) встраивается автоматизация и различные проверки. Как это может выглядеть? Вы разрабатываете что-то у себя, пишете код. Проверили — все работает. Делаете коммит, пуш, код уходит на GitHub. Дальше там могут происходить различные действия в зависимости от того, что вы настроили.\n\nСамый простой вариант CI/CD — запускается сборка, ставятся зависимости, запускаются линтеры, тесты. Более сложный вариант — происходит деплой (публикация) вашего приложения, линковка, создание нового сервера.\n\nЕсли ваш проект выложен на [GitHub](https://github.com/), вы можете воспользоваться бесплатным решением платформы — [Github Actions](https://github.com/features/actions). Так как GitHub — это про сообщество и опенсорс, можно переиспользовать скрипты-экшены других разработчиков. Например, в PHP можно использовать [экшен](https://github.com/marketplace/actions/the-php-security-checker), который проверяет зависимости приложения на уязвимости.\n\nКонечно же, можно определять и свои команды. Из этих команд вы собираете цепочку, в которой они выполняются последовательно друг за другом. Например:\n\n1. Скачать исходный код\n2. Установить зависимости\n3. Подготовить проект (например, создать необходимые переменные или миграции)\n4. Запустить линтер\n5. Запустить тесты.\n\nВсе действия будут совершаться без участия программиста и помогут отследить ошибку, пока ведется разработка.\n\nВернемся к тестовому заданию со статьями. Напомню, что нужно сделать приложение, в котором можно создать статью и оставить комментарии. При этом комментарии должны быть в виде дерева, как на Хабре. Вы знаете, что ваше приложение работает 100%, ведь вы даже написали тесты. Будет ли проверяющий запускать код? Допустим. Но что, если нужно проверить аналогичные проекты у 20 человек? Тогда вряд ли он это сделает. Даже если скачать и развернуть ваше приложение займет две минуты, то на всех уйдет минут 40. При этом каждому нужно посмотреть код, оценить его, дать фидбек.\n\nЕсли вы выложите ваше приложение куда-то, ревьювер сможет подергать методы или прожать кнопки. А также наверняка оценит то, что вы сэкономили ему время.\n\nДля этого можно использовать различные облачные сервисы. Для бэкенда можно использовать [Heroku](https://www.heroku.com/). Он интегрируется с GitHub и позволяет деплоить приложение по команде `git push`. Особенность Heroku в том, что он не обладает своей файловой системой, поэтому там нельзя хранить ничего, кроме кода, но можно подключить различные хранилища, например, базу данных. Есть бесплатные тарифы, которые идеально подойдут для выполнения такой задачи.\n\nПри этом, если вы используете какие-то проверки — например, линтеры и тесты, то код не будет деплоиться Heroku, если они будут провалены.\n\nДля фронтенда можно использовать [Vercel](https://vercel.com/), [Netlify](https://www.netlify.com/), [Github Pages](https://pages.github.com/). Кроме того, там тоже можно настроить сборку приложения и автоматизировать деплой.\n\n\n## Система контроля версий (VCS), Git\n\nДумаю, вы уже догадались, что нужно использовать [Git](https://git-scm.com/). Именно вокруг него строятся различные интеграции и автоматизации. Прошли те времена, когда разработчики хранили на своем жестком диске копии файлов index.php, index_backup.php, index2.php на случай, если что-то пойдет не так.\n\nGit позволяет работать одновременно над разными кусками кода, сравнивать их между собой. Хранит в себе историю изменений — кто, когда и что поменял. Использование этого инструмента — это еще одна санитарная норма в современной разработке.\n\nИсторию коммитов можно использовать для анализа того, как развивалось приложение, какие решения принимались, оценить навык использования инструмента. Иногда встречается такое, что в проекте за все время существования есть всего один коммит. Обычно я делаю вывод, что разработчик не любит пользоваться этим инструментом и проверяет у себя локально, отправляя в удаленный репозиторий готовое решение.\n\nСтарайтесь использовать понятные, краткие описания к коммитам. Желательно на английском языке или хотя бы на том, который принят в компании, для которой вы выполняете задание.\n\nЕсли есть сложности в работе с Git — пройдите наш [курс](https://ru.hexlet.io/courses/intro_to_git). Помните, что это теория, которую стоит закреплять на практике.\n\nЯ не упомянул здесь [Docker](https://www.docker.com/). Если вы умеете им пользоваться, это круто. Оформите конфиг и команды для запуска вашего приложения в Docker. Он позволяет упаковать приложение в изолированное окружение (например, настройки веб-сервера, специфические системные утилиты и пакеты), повысить переносимость, а инфраструктура приложения станет иммутабельной.\n\n## Архитектура, шаблоны, построение кода\n\nХаха, а тут советов нет. Выдумывайте сами.\n\nНет, на самом деле. Задача тестового задания — проверить ваши знания. Конкретные штуки. Например, как вы применяете паттерны, если они нужны. Как структурируете код, какие абстракции выделяете. Тяжело давать советы, которые актуальны для всех. Просто пишите понятный код. Все будет зависеть от вашего опыта и знаний.\n\nВ вакансиях вы часто можете увидеть требование «писать понятный, чистый код». На самом деле это тяжело делать, если нет опыта. Поэтому просто пишите код, пишите код, пишите код.\n\nЧитайте книги, смотрите доклады, анализируйте код других разработчиков. Старайтесь понять, почему сделано именно так. Анализируйте популярные решения, почему они так реализованы.\n\nПодходы и решения могут быть вообще разными в разных языках — код одного и того же веб-приложения на PHP и Ruby, Python, JS будет выглядеть по-разному. Некоторые решения будут просто не нужны в рамках других языков. Например, паттерны — их придумывают из-за несовершенства и ограничений языков.\n\nРуководствуйтесь здравым смыслом. Например, если у вас есть шаблон странички и какие-то компоненты, будет некорректно обращаться к базе данных из шаблона. Кроме того, имена переменных должны быть понятными — избегайте ненужных сокращений, лишнего контекста. Если у вас какие-то данные или процедуры дублируются, значит, что это какая-то абстракция — и ее стоит выделить отдельно.\n\nЕсли начитаться про паттерны, [SOLID](https://ru.wikipedia.org/wiki/SOLID_(%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) и другие принципы, можно легко уйти в [оверинжиниринг](https://www.youtube.com/watch?v=ok2cYf1Y8ig&feature=emb_logo) (придумывать функционал на будущее). Старайтесь сделать свое решение простым и понятным ([KISS](https://ru.wikipedia.org/wiki/KISS_(%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF))) — ведь скорее всего то, что вы заходите добавить, вам никогда не понадобится ([YAGNI](https://ru.wikipedia.org/wiki/YAGNI)). Готовьтесь обосновывать те решения, которые приняли в коде.\n\nПрограммирование — это творческий процесс, который контролируете только вы. Практикуйтесь.\n\n## Работа над заданием, сбор фидбека\n\nКогда вам предлагают сделать тестовое задание, обычно сразу же указывают дедлайн. В других случаях компания может спросить у разработчика, сколько времени у него оно займет. Например, справитесь ли вы за неделю, либо вам понадобится всего два дня.\n\nБез опыта невозможно дать грамотную оценку трудозатрат. Проблема с оценкой времени есть даже у опытных разработчиков. Поэтому прикиньте по времени, сколько вы будете работать над задачей, и возьмите немного времени с запасом.\n\nЕсли возникают ситуации, когда вам непонятна формулировка задания или требования, лучше спросить, а не играть в угадайку. Потому что задания могут быть действительно неверно сформулированы, либо даже сделаны таким образом, чтобы побудить вас задавать вопросы.\n\nЯ слышал о ситуациях, когда разработчику было непонятно тестовое задание и он задавал по нему уточняющие вопросы. На это заказчик (работодатель) говорил, мол, вы не слишком самостоятельны, раз задаете много вопросов. Кажется, что это не очень правильно и нужно дважды подумать, прежде чем идти в такую компанию.\n\nЕсли есть вопросы, спрашивайте. Если вы задерживаетесь с заданием, сообщайте об этом. Возможно, можно будет отправить задание попозже или частично завершенное. Важно иметь обратную связь, а не пропадать из поля зрения, если что-то пошло не так. Вопросы, связанные непосредственно с разработкой, лучше не спрашивать — типа «У меня проблема с такой-то библиотекой, которую вы сказали использовать, поможете?». Ведь то, как вы разберетесь с технологией, тоже является частью тестового задания.\n\nМожно сразу же поделиться ссылкой на репозиторий, чтобы ревьювер мог смотреть за ходом разработки.\n\n## Где взять тестовые задания?\n\nУ Хекслета есть [репозиторий](https://github.com/Hexlet/ru-test-assignments), в котором сообщество делится тестовыми заданиями. Сюда присылают ссылки студенты, сторонние разработчики и даже сами компании. Задания самого разного уровня, на любой стек и уровень.\n\n## Как учиться писать более лучший код\n\nПрактика, практика и еще раз практика. Как говорилось выше — пишите больше кода, читайте книги, изучайте проекты. У Хекслета есть множество проектов, в которых можно принять участие. За этими проектами следят и, как правило, хорошие практики переносятся из одного проекта в другой. Даже стек особо не важен. Например, в каждом проекте используется Makefile и есть подробное ридми для описания инструкций по работе с проектом. Вы можете подглядеть, как писать тесты, как работать с популярным фреймворком (Laravel, Ruby On Rails) и даже как создать инфраструктуру с помощью Terraform и Ansible (вряд ли это будет в вашем тестовом, ну а вдруг).\n\n## А можно не делать тестовое?\n\nНа самом деле тестовое задание предлагается далеко не всем. Чаще всего их дают начинающим разработчикам или тем, у кого нет портфолио. В резюме соискатели пишут, что владеют определенными технологиями, и это нужно проверить. Бывает, что у компании специфический стек (типа Clojure), но у кандидатов нет опыта по этой технологии. Тогда могут найти опытного человека (который уже поработал программистом), но без опыта с нужной в компании технологией.\n\nПо моему опыту, чем больше у разработчика полезного кода на Github, тем выше вероятность, что ему не придется делать тестовое задание. Например, проекты Хекслета, [открытые проекты](https://guides.hexlet.io/how-to-be-a-helpful-for-the-hexlet-community/), пет-проекты или тестовые задания. Например, я делал тестовое один раз, когда у меня не было даже проектов Хекслета. Потом это же тестовое пригодилось в поиске следующей работы, и в трудоустройстве в другую компанию.\n\n\n## Итого\n\nВ этой статье мне хотелось рассказать вам про технологии, подходы и практики, которые можно использовать при работе над тестовым заданием.\n\nКто-то скажет, что не нужно насчет всего этого заморачиваться. Но я постоянно вижу, что кандидаты выполняют тестовое задание, но его толком не проверяют просто потому, что оно оформлено криво.\n\nЧасть перечисленных практик уже являются стандартами разработки. Попробуете один-два раза и поймете, насколько круто их использовать. Вы покажете, что знакомы с кучей технологий хотя бы поверхностно, и что это для вас не пустой звук. Тогда с вас останется просто писать грамотный код.\n\n## Полезные ссылки\n\n### Git\n\n[GitHub](https://github.com/) — git-хостинг и сообщество разработчиков\n\n[Git How To: курс обучения Git на русском](https://githowto.com/ru)\n\n[Стиль именования коммитов / Хабр](https://habr.com/post/183646/)\n\n[Как следует писать комментарии к коммитам](https://habr.com/ru/post/416887/)\n\n### Автоматизация, CI/CD, деплой\n\n[Как и для чего использовать Docker](https://guides.hexlet.io/docker/#%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B2-%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D0%B5)\n\n[Вебинар: Stateful vs. Stateless](https://www.youtube.com/watch?v=WPCz_U7D8PI)\n\n[Никита Соболев — Автоматизируем все с GitHub Actions](https://www.youtube.com/watch?v=QoCSvwkP_lQ). Доклад, рассказывающий, что такое Github Actions, с примерами использования\n\n[Code Climate](https://codeclimate.com/) — платформа для статистического анализа и поиска проблемных мест. Также позволяет оценивать покрытие кода с помощью скрипта (показывает бейджик с процентом покрытия тестами)\n\n[Eslint](https://eslint.org/) — линтер для Javascript\n\n[airbnb style guide](https://github.com/airbnb/javascript) — популярный стайлгайд для Javascript\n\n[Jest](https://jestjs.io/) — фреймворк тестирования для Javascript\n\n[Testing-library](https://testing-library.com/) — библиотека для тестирования фронтенда в Javascript\n\n[PHPUnit](https://phpunit.de/) — фреймворк для тестирования в PHP\n\n[PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) — популярный линтер для PHP\n\n[PSR-12](https://www.php-fig.org/psr/psr-12/) — современные стандарты кодирования для PHP\n\n[Vercel](https://vercel.com/) и [](http://netlify/)[Netlify](https://www.netlify.com/) — платформы для развертывания приложения (статика, фронтенд)\n\n[Heroku](https://heroku.com/) — платформа для облачного развертывания приложения, подходит для бэкенд-приложений\n\n::posts\n\n### Дополнительно\n\n[Как быстро стоит делать тестовое](https://catwomenko.ru/2017/03/20/fastest-test-ever/)\n\n[Рефакторинг и Паттерны проектирования](https://refactoring.guru/ru)\n\n[Продуманная оптимизация](http://optimization.guide/)\n\n[The Twelve-Factor App (Русский перевод)](https://12factor.net/ru/)\n\n[Список тестовых заданий для прокачки](https://github.com/Hexlet/ru-test-assignments)\n\n### Книги\n\n[Совершенный код](https://www.ozon.ru/context/detail/id/138437220/)\n\n### Видео\n\nДоклады по ментальному программированию. Про важность нейминга и семантичности кода\n\n- [Часть 1](https://www.youtube.com/watch?v=EEq1wdM2M2w)\n- [Часть 2](https://www.youtube.com/watch?v=vkUTX1hruF8)\n\n[Доклад «Снесите это немедленно»](https://www.youtube.com/watch?v=R-FfI4i0-uY) \n\n[Как писать качественный и понятный код? Чистые функции](https://www.youtube.com/watch?v=_tPRetDsLj4&list=PLo6puixMwuSOnsZFbZRg0i2SmoJediaCA&index=2)\n\n[Начинаем писать тесты (правильно)](https://www.youtube.com/watch?v=zsz8kdi62mE&list=PLo6puixMwuSPfJVVXKhLkHCymzEQAKxjr&index=48)\n","reading_time":11,"url":"https://ru.hexlet.io/blog/posts/kak-razrabotchiku-uluchshit-svoe-testovoe-zadanie","cover_thumb_variant":null,"cover_list_variant":"/vite/assets/blog_post-7eTyeLLt.webp","cover_main_variant":"/vite/assets/blog_post-7eTyeLLt.webp","related_stacks_count":5},"relatedPosts":[{"model_name":"BlogPost","id":660,"title":"Кто такой тестировщик и как им стать","slug":"gid-po-professii-testirovschik-chem-zanimaetsya-skolko-zarabatyvaet-chto-nado-znat-i-gde-uchitsya","summary":"Рассказываем, кто такой тестировщик и чем он занимается, сколько зарабатывает такой специалист, а также какие нужны знания и компетенции, чтобы им стать.","created_at":"2020-01-29T16:58:16.214Z","published_at":"2023-12-29T10:36:34.186Z","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MTYzNiwicHVyIjoiYmxvYl9pZCJ9fQ==--72f5a3fb78c634c408f39349dbd2e203809b4069/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX2FuZF9wYWQiOls3MDgsMzU0XSwic2F2ZXIiOnsicXVhbGl0eSI6ODV9fSwicHVyIjoidmFyaWF0aW9uIn19--324dc52aa55ebe818c2a887ebcb832b9ad1c0381/%D1%82%D0%B5%D1%81%D1%82%D0%B5%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA2023-01.png"},{"model_name":"BlogPost","id":1636,"title":"Как просить повышения зарплаты программисту и не бояться этого","slug":"bolshe-zarabatyvat","summary":"Вместе с карьерным коучем Оксаной Паниной рассказываем, как правильно просить прибавку к зарплате и не потерять доверие работодателя.\r\n","created_at":"2021-12-01T12:30:31.883Z","published_at":"2022-11-24T09:08:03.643Z","cover_list_variant":"/vite/assets/blog_post-7eTyeLLt.webp"},{"model_name":"BlogPost","id":1690,"title":"Чему мидлы и сеньоры могут научиться на Хекслете: 10 направлений ","slug":"midly-i-senory","summary":"На Хекслете кроме профессий есть сотни курсов — не только с базовыми концепциями программирования, но и треки с объяснениями сложных алгоритмов, парадигм разработки и тестирования на разных языках. Рассказываем о курсах, которые помогут разработчикам среднего уровня и выше углубить свои знания, разобрать в новых технологиях и языках программирования или сменить направление деятельности.\r\n","created_at":"2022-01-19T15:27:25.659Z","published_at":"2022-10-20T08:47:27.572Z","cover_list_variant":"/vite/assets/blog_post-7eTyeLLt.webp"}],"category":{"id":12,"name":"Карьера","slug":"career","state":"published","created_at":"2017-07-21T15:42:21.481Z"},"mainStackCategory":{"id":13,"name":"Курсы по PHP","slug":"php","short_name":"PHP","order":95,"state":"published","category_slug":"courses_php"},"categories":[{"id":6,"name":"Мотивация","slug":"motivation","state":"published","created_at":"2016-10-06T18:31:38.903Z"},{"id":3,"name":"Истории успеха","slug":"success","state":"published","created_at":"2016-07-30T12:57:18.308Z"},{"id":14,"name":"Дневник студента","slug":"student-diary","state":"published","created_at":"2019-02-25T13:27:09.471Z"},{"id":4,"name":"Код","slug":"code","state":"published","created_at":"2016-08-23T13:33:44.258Z"},{"id":12,"name":"Карьера","slug":"career","state":"published","created_at":"2017-07-21T15:42:21.481Z"}],"relatedLandings":[{"stack":{"id":179,"slug":"fullstack-php","title":"Fullstack-разработчик на PHP","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":null,"duration_in_months":16},"id":279,"slug":"fullstack-php","title":"Fullstack-разработчик на PHP","subtitle":"","subtitle_for_lists":null,"locale":"ru","current":true,"duration_in_months_text":"16 месяцев","stack_slug":"fullstack-php","price_text":"от 7 934 ₽","duration_text":"16 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzY2OSwicHVyIjoiYmxvYl9pZCJ9fQ==--cbbaa606be07bca305bd21d9919235989a1ed289/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Code%20typing-amico.png"},{"stack":{"id":2,"slug":"php","title":"PHP-разработчик","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":60,"duration_in_months":10},"id":1,"slug":"php","title":"РНР-разработчик","subtitle":"Изучите PHP и Laravel для разработки и проектирования REST API","subtitle_for_lists":"Изучите PHP и Laravel для разработки и проектирования REST API","locale":"ru","current":true,"duration_in_months_text":"10 месяцев","stack_slug":"php","price_text":"от 5 650 ₽","duration_text":"10 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzk5MiwicHVyIjoiYmxvYl9pZCJ9fQ==--e9d0f30948ea766a7e6bc3e3d56c192344d45fb8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programming-cuate%20(1).png"},{"stack":{"id":43,"slug":"fullstack-javascript","title":"Fullstack-разработчик на Node.js","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":140,"duration_in_months":12},"id":74,"slug":"fullstack-javascript","title":"Fullstack-разработчик на Node.js","subtitle":"Освоите JavaScript, Node.js, Fastify и React для фронтенда и бэкенда.","subtitle_for_lists":"Освоите JavaScript, Node.js, Fastify и React для фронтенда и бэкенда.","locale":"ru","current":true,"duration_in_months_text":"12 месяцев","stack_slug":"fullstack-javascript","price_text":"от 7 934 ₽","duration_text":"12 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDA0MywicHVyIjoiYmxvYl9pZCJ9fQ==--e2c6c0775e2308e42fbc5dc592ba2db0470632ca/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programmer-rafiki.png"},{"stack":{"id":13,"slug":"backend","title":"Node.js-разработчик","audience":"for_beginners","start_type":"weekly","pricing_model":"purchase","priority":"high","kind":"profession","state":"published","stack_state":"finished","order":130,"duration_in_months":10},"id":19,"slug":"backend","title":"Node.js-разработчик","subtitle":"Изучите JavaScript, Node.js, Fastify и REST API","subtitle_for_lists":"Изучите JavaScript, Node.js, Fastify и REST API","locale":"ru","current":true,"duration_in_months_text":"10 месяцев","stack_slug":"backend","price_text":"от 4 755 ₽","duration_text":"10 месяцев","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzcyNSwicHVyIjoiYmxvYl9pZCJ9fQ==--2e84f5f94140ee4e22019ac479c290ef48c3fac8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Static%20website-cuate.png"},{"stack":{"id":63,"slug":"go-web-development","title":"Веб-разработка на Go","audience":"for_programmers","start_type":"anytime","pricing_model":"subscription","priority":"medium","kind":"track","state":"published","stack_state":"finished","order":1250,"duration_in_months":1},"id":113,"slug":"go-web-development","title":"Веб-разработка на Go","subtitle":"Навык создания веб-приложений на Go, необходимый для получения оффера на позицию Go-разработчика","subtitle_for_lists":"Изучите Go и разработку веб-приложений","locale":"ru","current":true,"duration_in_months_text":"1 месяц","stack_slug":"go-web-development","price_text":"от 3 900 ₽","duration_text":"1 месяц","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAzNywicHVyIjoiYmxvYl9pZCJ9fQ==--c9a507d1b30c26185c312c95f68af4f0d8122afa/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programmer-bro.png"}]},"url":"/blog/posts/kak-razrabotchiku-uluchshit-svoe-testovoe-zadanie","version":"0b0c6d4ebbd40fd58630a0dd89cc25544ccdf24e","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","author":"Nikolai Gagarinov","name":"Как разработчику улучшить свое тестовое задание","datePublished":"2022-06-30T10:57:54.101Z","headline":"Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.","image":"/vite/assets/blog_post-7eTyeLLt.webp","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":34}]}</script><div style="--container-size:var(--container-size-lg);margin-top:var(--mantine-spacing-xl);height:100%" class="m_7485cace mantine-Container-root" data-size="lg" data-strategy="block"><script type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"position":1,"@type":"ListItem","item":{"@id":"/blog","name":"Блог Хекслета"}},{"position":2,"@type":"ListItem","item":{"@id":"/blog/categories/career","name":"Карьера"}},{"position":3,"@type":"ListItem","item":{"@id":"/blog/posts/kak-razrabotchiku-uluchshit-svoe-testovoe-zadanie","name":"Как разработчику улучшить свое тестовое задание"}}]}</script><div style="margin-bottom:var(--mantine-spacing-xs)" class="m_8b3717df mantine-Breadcrumbs-root"><a style="--text-fz:var(--mantine-font-size-sm);--text-lh:var(--mantine-line-height-sm);white-space:normal;color:inherit" class="mantine-focus-auto m_849cf0da m_f678d540 mantine-Breadcrumbs-breadcrumb m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-size="sm" data-underline="hover" href="/"><div style="color:inherit" class="m_4451eb3a mantine-Center-root"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-home-link "><path d="M20.085 11.085l-8.085 -8.085l-9 9h2v7a2 2 0 0 0 2 2h4.5"></path><path d="M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 1.807 1.143"></path><path d="M20 21a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M20 16a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M15 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path><path d="M21 16l-5 3l5 2"></path></svg></div></a><div class="m_3b8f2208 mantine-Breadcrumbs-separator">/</div><a style="--text-fz:var(--mantine-font-size-sm);--text-lh:var(--mantine-line-height-sm);white-space:normal;color:inherit" class="mantine-focus-auto m_849cf0da m_f678d540 mantine-Breadcrumbs-breadcrumb m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-size="sm" data-underline="hover" href="/blog">Блог Хекслета</a><div class="m_3b8f2208 mantine-Breadcrumbs-separator">/</div><a style="--text-fz:var(--mantine-font-size-sm);--text-lh:var(--mantine-line-height-sm);white-space:normal;color:inherit" class="mantine-focus-auto m_849cf0da m_f678d540 mantine-Breadcrumbs-breadcrumb m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-size="sm" data-underline="hover" href="/blog/categories/career">Карьера</a><div class="m_3b8f2208 mantine-Breadcrumbs-separator">/</div><p style="--text-fz:var(--mantine-font-size-sm);--text-lh:var(--mantine-line-height-sm);white-space:normal;color:var(--mantine-color-dimmed)" class="mantine-focus-auto m_f678d540 mantine-Breadcrumbs-breadcrumb m_b6d8b162 mantine-Text-root" data-size="sm">Как разработчику улучшить свое тестовое задание</p></div><style data-mantine-styles="inline">.__m__-_R_eub_{margin-bottom:var(--mantine-spacing-xs);}@media(min-width: 36em){.__m__-_R_eub_{margin-bottom:var(--mantine-spacing-xs);}}</style><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root __m__-_R_eub_"><style data-mantine-styles="inline">.__m__-_R_deub_{width:100%;}@media(min-width: 36em){.__m__-_R_deub_{width:70%;}}@media(min-width: 75em){.__m__-_R_deub_{width:75%;}}</style><div class="__m__-_R_deub_"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size)" class="m_8a5d1357 mantine-Title-root" data-order="1">Как разработчику улучшить свое тестовое задание</h1></div></div></div><div style="position:absolute;top:calc(18.75rem * var(--mantine-scale))" class=""></div><style data-mantine-styles="inline">.__m__-_R_2iub_{--grid-gutter:var(--mantine-spacing-xl);}</style><div class="m_410352e9 mantine-Grid-root __m__-_R_2iub_"><div class="m_dee7bd2f mantine-Grid-inner"><style data-mantine-styles="inline">.__m__-_R_dmiub_{--col-flex-grow:auto;--col-flex-basis:100%;--col-max-width:100%;}@media(min-width: 48em){.__m__-_R_dmiub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}@media(min-width: 62em){.__m__-_R_dmiub_{--col-flex-grow:auto;--col-flex-basis:66.66666666666667%;--col-max-width:66.66666666666667%;}}</style><div class="m_96bdd299 mantine-Grid-col __m__-_R_dmiub_"><div style="--stack-gap:var(--mantine-spacing-md);--stack-align:stretch;--stack-justify:flex-start;margin-bottom:var(--mantine-spacing-xl)" class="m_6d731127 mantine-Stack-root"><div class=""><div style="--group-gap:var(--mantine-spacing-xs);--group-align:center;--group-justify:flex-start;--group-wrap:wrap;margin-bottom:var(--mantine-spacing-xl)" class="m_4081bf90 mantine-Group-root"><button style="--badge-height:var(--badge-height-sm);--badge-padding-x:var(--badge-padding-x-sm);--badge-fz:var(--badge-fz-sm);--badge-bg:var(--mantine-color-default);--badge-color:var(--mantine-color-default-color);--badge-bd:calc(0.0625rem * var(--mantine-scale)) solid var(--mantine-color-default-border);cursor:pointer;color:inherit" class="m_347db0ec mantine-Badge-root" data-variant="default" data-size="sm" type="button" aria-label="Без стека"><span class="m_5add502a mantine-Badge-label">Без стека</span></button></div><div style="--group-gap:calc(0.625rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:wrap;margin-bottom:var(--mantine-spacing-sm);color:var(--mantine-color-gray-text)" class="m_4081bf90 mantine-Group-root"><div style="--group-gap:calc(0.1875rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:wrap;margin-inline-end:var(--mantine-spacing-lg)" class="m_4081bf90 mantine-Group-root">30 июня 2022 г.</div><div style="--group-gap:calc(0.1875rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-clock "><path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"></path><path d="M12 7v5l3 3"></path></svg></div>11 минут</div><div style="--group-gap:calc(0.1875rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-thumb-up "><path d="M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3"></path></svg></div>34</div></div><div style="--ar-ratio:2" class="m_71ac47fc mantine-AspectRatio-root"><img style="--image-radius:var(--mantine-radius-md);--image-object-fit:cover;width:100%;height:100%" class="m_9e117634 mantine-Image-root" src="/vite/assets/blog_post-7eTyeLLt.webp" alt="Как разработчику улучшить свое тестовое задание"/></div></div><div role="link" tabindex="0" style="cursor:pointer"><button style="display:block;width:100%" class="mantine-focus-auto m_87cf2631 mantine-UnstyledButton-root" type="button" aria-label="Присоединяйтесь к нашему Telegram-сообществу"><div style="background-color:light-dark(var(--mantine-color-gray-1), var(--mantine-color-dark-6))" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:flex-start;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><div style="--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:auto;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-brand-telegram "><path d="M15 10l-4 4l6 6l4 -16l-18 7l4 2l2 6l3 -4"></path></svg></div>Присоединяйтесь к нашему Telegram-сообществу</div></div></button></div><div style="margin-bottom:var(--mantine-spacing-xl)" class="m_d08caa0 mantine-Typography-root"><p><strong>Тестовое задание — один из способов для начинающих разработчиков узнавать новые технологии и прокачивать свой опыт написания кода. Разработчик Николай Гагаринов рассказывает, как программисту улучшить свое тестовое задание и зачем это нужно.</strong></p>
<p>Я довольно часто общаюсь с начинающими разработчиками, помогаю им на различных площадках и в чатах. Отвечаю на вопросы как общего характера, так и связанные с какой-либо технологией или отладкой кода. Также я иногда провожу код-ревью проектов, над которыми работают ребята — это бывают как проекты на Хекслете, открытые (опенсорсные) проекты, так и тестовые задания самого разного размера.</p>
<style data-mantine-styles="inline">.__m__-_R_5derddmiub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_5derddmiub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_5derddmiub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/fullstack-php?promo_name=programs_list&promo_position=blog_post&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">16 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Fullstack-разработчик на PHP</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root"></p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzY2OSwicHVyIjoiYmxvYl9pZCJ9fQ==--cbbaa606be07bca305bd21d9919235989a1ed289/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Code%20typing-amico.png" alt="Fullstack-разработчик на PHP" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 7 934 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/php?promo_name=programs_list&promo_position=blog_post&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">10 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">РНР-разработчик</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите PHP и Laravel для разработки и проектирования REST API</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzk5MiwicHVyIjoiYmxvYl9pZCJ9fQ==--e9d0f30948ea766a7e6bc3e3d56c192344d45fb8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programming-cuate%20(1).png" alt="РНР-разработчик" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 5 650 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/fullstack-javascript?promo_name=programs_list&promo_position=blog_post&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">12 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Fullstack-разработчик на Node.js</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Освоите JavaScript, Node.js, Fastify и React для фронтенда и бэкенда.</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDA0MywicHVyIjoiYmxvYl9pZCJ9fQ==--e2c6c0775e2308e42fbc5dc592ba2db0470632ca/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programmer-rafiki.png" alt="Fullstack-разработчик на Node.js" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 7 934 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/backend?promo_name=programs_list&promo_position=blog_post&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">10 месяцев</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">С нуля</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Node.js-разработчик</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите JavaScript, Node.js, Fastify и REST API</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzcyNSwicHVyIjoiYmxvYl9pZCJ9fQ==--2e84f5f94140ee4e22019ac479c290ef48c3fac8/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Static%20website-cuate.png" alt="Node.js-разработчик" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 4 755 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/go-web-development?promo_name=programs_list&promo_position=blog_post&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">1 месяц</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Веб-разработка на Go</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Изучите Go и разработку веб-приложений</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6NDAzNywicHVyIjoiYmxvYl9pZCJ9fQ==--c9a507d1b30c26185c312c95f68af4f0d8122afa/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Programmer-bro.png" alt="Веб-разработка на Go" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 900 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=blog_post&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div>
<p>Я помню, как сам делал самое первое тестовое задание. Оно было с одной стороны простым, но с другой — сложным, нужно было сделать на PHP без фреймворков небольшое приложение для добавления статей и загрузки древовидных комментариев. Подобное задание можно сделать не только на PHP, но и на любом языке для веба — Go, Python, Ruby, Java, NodeJS.</p>
<p>Несмотря на то, что стек технологий разнится, ошибки могут быть типовыми:</p>
<ol>
<li>Код не запускается или не выполняет поставленную задачу</li>
<li>Отсутствует описание (README). Соответственно, нет инструкций по запуску</li>
<li>Код не соответствует принятым стандартам кодирования и best practices</li>
<li>Задание было прислано в архиве или Google Docs, то есть не использовалась система контроля версий, например, Git.</li>
</ol>
<p>В тексте я поделюсь советами, которые помогут улучшить ваше тестовое задание, узнать о существовании полезных инструментов и развить навыки разработки и развертывания приложения. Это советы абсолютно универсальны — их можно применить не только к тестовому заданию, но и вообще к любому вашему проекту на Github.</p>
<h2 id="heading-2-1">Содержание</h2>
<ul>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-2">Описание проекта и общее оформление</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-3">Общая работоспособность проекта</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-4">Качество кода, стандарты кодирования, линтеры</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-5">Автоматические тесты</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-6">CI/CD, автоматизация, деплой</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-7">Система контроля версий (VCS), Git</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-8">Архитектура, шаблоны, построение кода</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-9">Работа над заданием, сбор фидбека</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-10">Где взять тестовые задания?</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-11">Как учиться писать более лучший код</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-12">А можно не делать тестовое?</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-13">Итого</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="#heading-2-14">Полезные ссылки</a></li>
</ul>
<h2 id="heading-2-2">Описание проекта и общее оформление</h2>
<p>Добавьте описание того, что делает ваш проект, даже если это ToDo App — приложение для ведения задач. Опишите, какие используются технологии, версии языка и библиотек. Укажите требования к операционной системе и пакетам, которые необходимо установить. Опишите команды, которые могут использоваться для развертывания приложения, чтобы его можно было разрабатывать или демонстрировать.</p>
<p>Если у приложения есть рабочая демонстрация, укажите на нее ссылку. Это может быть ссылка на GitHub Pages, Heroku или ваш домен и сервер, где приложение развернуто и его можно посмотреть.</p>
<p>Проверьте, что в тексте нет ошибок. Не все владеют русским или английским языком идеально. Но даже текстовые редакторы кода (например, VSCode) подсвечивают все опечатки.</p>
<p>Описание проекта стоит делать либо на английском языке, либо на том языке, который используется в компании и на котором вы получили тестовое задание. Если это просто пет-проект для тренировки, который выложен на GitHub, старайтесь использовать английский язык. Возможно, если вы находитесь в поиске работы, с вами даже свяжется зарубежная компания. Для перевода текстов я обычно использую <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="http://deepl.com/" rel="noopener noreferrer" target="_blank">Deepl.com</a> — для перевода он использует машинное обучение, поэтому часто там переводы лучше, чем в Google Translate.</p>
<p>Если вы делаете приложение с веб-интерфейсом (например, сайт, где можно публиковать новости), используйте готовое решение, не занимайтесь версткой и стилизацией самостоятельно. Для таких целей можно использовать фреймворк <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://getbootstrap.com/" rel="noopener noreferrer" target="_blank">Bootstrap</a>.</p>
<p>Когда вы работаете над тестовым заданием, не забудьте приложить текст задания в README или отдельно в проект. Ревьюер может его просто не иметь при себе, или забыть какие-то мелочи. Также вы сможете это задание использовать в вашем портфолио, в таком случае текст задания будет служить описанием проекта.</p>
<p>Например, так выглядит репозиторий без описания:</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="https://imgur.com/4FAaRCU.png" alt="" loading="lazy"/></p>
<p>А так выглядит репозиторий проекта с подробным README:</p>
<p><img style="--image-object-fit:contain;width:auto" class="m_9e117634 mantine-Image-root" src="https://imgur.com/XZu99Ro.png" alt="" loading="lazy"/></p>
<h2 id="heading-2-3">Общая работоспособность проекта</h2>
<p>Если вы делаете тестовое задание, обязательно сверяйтесь с условиям. Если их нет, стоит их уточнить. Спросите себя — достигнута ли поставленная цель? Нажимаются ли кнопки? Работает ли регистрация? Сохраняются ли данные? Об этом часто забывают из-за неопытности. Вы можете сфокусироваться на чем-то одном и забыть про остальные части приложения.</p>
<p>Очень обидно, когда твою работу не примут из-за того, что ты где-то не поставил скобку или опечатался. Про тесты я расскажу дальше, но помните — ваше решение должно быть рабочим. Да, бывают моменты, когда просят сделать не рабочее решение, а абстрактное. Например, описать интерфейсы классов, использовать заглушки, но обычно это указано в ТЗ.</p>
<h2 id="heading-2-4">Качество кода, стандарты кодирования, линтеры</h2>
<p>Есть теория, которая называется «<a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BE%D1%80%D0%B8%D1%8F_%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%82%D1%8B%D1%85_%D0%BE%D0%BA%D0%BE%D0%BD" rel="noopener noreferrer" target="_blank">Теория разбитых окон</a>». В ней говорится, что «Если в здании разбито одно стекло и никто его не меняет, то через некоторое время в этом здании не останется ни одного целого окна». Такой подход актуален и для кода. Если мы начинаем забивать на соблюдение стиля кода, то в итоге начинаем писать как попало — и перестаем обращать внимание на весь код вообще, различные подходы и здравый смысл.</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.hexlet.io/blog/posts/linter" rel="noopener noreferrer" target="_blank">Линтеры</a> — это инструменты (скрипты), которые проверяют код на соответствие настроенным стандартам. Они нужны для того, чтобы было единство кода как внутри проекта, так и между множеством разработчиков. То есть линтеры нужны для того, чтобы другой разработчик мог с легкостью писать код и не думать о том, что ему использовать — табы или пробелы.</p>
<p>Сравните. Оба примеры написаны на PHP с использованием условной конструкции, но в одном случае стандарты игнорируются:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">if ($a === $b)
{
bar();
}
elseif ($a > $b) {
$foo->bar($arg1);} else
{
BazClass::bar($arg2, $arg3);
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>А в следующем случае разработчик использует линтер для соблюдения стандартов:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">if ($a === $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar($arg2, $arg3);
}</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Чтобы разработчики <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=SsoOG6ZeyUI" rel="noopener noreferrer" target="_blank">не ругались</a> о том, какое форматирование использовать, они договариваются о едином стандарте для кода. В каждом языке есть общепринятые стандарты. Иногда стандартов может быть несколько. Еще реже бывают отдельные стандарты внутри проекта или внутри компании. В PHP общепринятый стандарт — <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.php-fig.org/psr/psr-12/" rel="noopener noreferrer" target="_blank">PSR</a>, для JS чаще всего используется стандарт от <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/airbnb/javascript" rel="noopener noreferrer" target="_blank">Airbnb</a>.</p>
<p>Современные редакторы позволяют настроить проверку и исправление ошибок как при редактировании кода, так и по специальной команде, например, по горячей клавише. При необходимости правила линтера могут изменяться — например, можно не проверять определенные файлы. Правила линтера могут даже расширяться — например, сортировать импорты, либо указывать возвращаемый тип у функции. Обычно использование линтера — это санитарное правило, как мытье рук перед едой.</p>
<p>На <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.hexlet.io/" rel="noopener noreferrer" target="_blank">Хекслете</a> есть проекты — практические задания разной степени сложности, где нужно сделать свое приложение по техническому заданию. Во время код-ревью этих проектов используется вот такой порядок проверки:</p>
<p><em>Проверка кода идет по пунктам указанным ниже. Если на верхнем уровне есть серьезные проблемы, то проверка останавливается до исправления.</em></p>
<ol>
<li><em>Конфигурация (линтеры, запуск тестов, CI).</em></li>
<li><em>Внешний вид и общая работоспособность.</em></li>
<li><em>Тесты.</em></li>
<li><em>Авторизация.</em></li>
<li><em>Правильное использование роутинга (имена, именованные маршруты).</em></li>
<li><em>Оформление шаблонов.</em></li>
<li><em>Оформление моделей.</em></li>
<li><em>Оформление обработчиков.</em></li>
</ol>
<p>Если игнорируются ошибки линтера на самом верхнем уровне, код не проходит ревью, а возвращается студенту с просьбой исправить замечания. Обычно линтер становится частью CI/CD (про это ниже), поэтому если при написании вы забудете проверить свой код, это сделает скрипт.</p>
<p>Кроме линтера можно использовать и различные онлайн-инструменты для проверки качества кода. В проектах Хекслета используется <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="http://codeclimate.com/" rel="noopener noreferrer" target="_blank">CodeClimate</a> — этот сервис анализирует код и может подсветить моменты, которые стоит поправить. Например, глубокую вложенность с условиями и циклами.</p>
<h2 id="heading-2-5">Автоматические тесты</h2>
<p>В современной разработке от тестирования никуда не деться. Умение писать тесты и тестируемый код сейчас встречается практически в каждой вакансии. И сама культура написания тестов существует уже довольно давно. Если вы откроете любую хорошую книгу по разработке, наверняка найдете там главу или целый раздел, посвященный написанию тестов.</p>
<p>Грамотные тесты могут ускорять разработку, плохие, неудобные или медленные тесты — наоборот. Их не хочется запускать, они могут часто ломаться от каждого изменения или выполняться несколько часов.</p>
<p>Современные фреймворки и библиотеки помогают писать простые и легкие тесты. Например, во фреймворке <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://laravel.com/" rel="noopener noreferrer" target="_blank">Laravel</a> есть множество инструментов для этого: утверждения (assertions) для проверки данных, стабы для внешних запросов, генерация тестовых данных.</p>
<p>Для JS используется <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://jestjs.io/" rel="noopener noreferrer" target="_blank">jest</a> и обертки-библиотеки, которые помогают писать тесты. Для фронтенда есть библиотека <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://testing-library.com/" rel="noopener noreferrer" target="_blank">testing-library</a> — ее можно использовать с любым популярным фреймворком React/Angular/Vue. Для PHP повсеместно используется <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://phpunit.de/" rel="noopener noreferrer" target="_blank">PHPUnit</a>. Обязательно изучите эти инструменты и попробуйте написать парочку тестов.</p>
<p>Старайтесь не писать низкоуровневые тесты. Вы могли видеть <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://habrastorage.org/getpro/habr/post_images/b6d/7a8/3ed/b6d7a83ed09e1a8046529bebfe02836e.png" rel="noopener noreferrer" target="_blank">пирамиду тестирования</a>, где на нижнем уровне находятся юнит-тесты, а на самом верху — интеграционные. Это довольно условное деление, ведь что-то может быть отдельным компонентом, а что-то — целой системой. Все зависит от того, как посмотреть.</p>
<p>Большие фреймворки (Laravel, Symfony) уже обладают удобными инструментами для тестирования. Вы сможете с легкостью написать один функциональный тест, который будет проверять основную логику приложения. Один высокоуровневый тест может заменить десяток низкоуровневых. Если тесты проходят быстро, это удобно.</p>
<p>Модульные тесты полезны там, где нужно изменить какой-то кусок кода со сложной логикой, если в нем нет побочных эффектов — например, вызова внешнего сервиса или обращения к базе. Но если у вас уже есть верхнеуровневый тест, который покрывает этот кусок кода, смысла в модульном тесте по большому счету нет.</p>
<p>По теме тестов есть полезная статья «<a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://medium.com/nuances-of-programming/%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D0%BB%D0%B8%D0%B2%D0%BE%D0%B5-%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8%D0%BB%D0%B8-%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D1%82%D0%B5%D1%81%D1%82%D1%8B-%D1%85%D1%83%D0%B6%D0%B5-%D1%87%D0%B5%D0%BC-%D0%B2%D1%8B-%D0%B4%D1%83%D0%BC%D0%B0%D0%B5%D1%82%D0%B5-24670e16ab0" rel="noopener noreferrer" target="_blank">Бережливое тестирование, или Почему модульные тесты хуже, чем вы думаете</a>».</p>
<h2 id="heading-2-6">CI/CD, автоматизация, деплой</h2>
<p>Теперь, когда вы стали использовать линтеры и тесты, вы можете заставить их работать и помогать вам на регулярной основе.</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://aws.amazon.com/ru/devops/continuous-integration/" rel="noopener noreferrer" target="_blank">Что такое CI/CD</a>? Если коротко, в процесс выкладки кода (например, обычный <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">git push</code> на GitHub) встраивается автоматизация и различные проверки. Как это может выглядеть? Вы разрабатываете что-то у себя, пишете код. Проверили — все работает. Делаете коммит, пуш, код уходит на GitHub. Дальше там могут происходить различные действия в зависимости от того, что вы настроили.</p>
<p>Самый простой вариант CI/CD — запускается сборка, ставятся зависимости, запускаются линтеры, тесты. Более сложный вариант — происходит деплой (публикация) вашего приложения, линковка, создание нового сервера.</p>
<p>Если ваш проект выложен на <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/" rel="noopener noreferrer" target="_blank">GitHub</a>, вы можете воспользоваться бесплатным решением платформы — <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/features/actions" rel="noopener noreferrer" target="_blank">Github Actions</a>. Так как GitHub — это про сообщество и опенсорс, можно переиспользовать скрипты-экшены других разработчиков. Например, в PHP можно использовать <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/marketplace/actions/the-php-security-checker" rel="noopener noreferrer" target="_blank">экшен</a>, который проверяет зависимости приложения на уязвимости.</p>
<p>Конечно же, можно определять и свои команды. Из этих команд вы собираете цепочку, в которой они выполняются последовательно друг за другом. Например:</p>
<ol>
<li>Скачать исходный код</li>
<li>Установить зависимости</li>
<li>Подготовить проект (например, создать необходимые переменные или миграции)</li>
<li>Запустить линтер</li>
<li>Запустить тесты.</li>
</ol>
<p>Все действия будут совершаться без участия программиста и помогут отследить ошибку, пока ведется разработка.</p>
<p>Вернемся к тестовому заданию со статьями. Напомню, что нужно сделать приложение, в котором можно создать статью и оставить комментарии. При этом комментарии должны быть в виде дерева, как на Хабре. Вы знаете, что ваше приложение работает 100%, ведь вы даже написали тесты. Будет ли проверяющий запускать код? Допустим. Но что, если нужно проверить аналогичные проекты у 20 человек? Тогда вряд ли он это сделает. Даже если скачать и развернуть ваше приложение займет две минуты, то на всех уйдет минут 40. При этом каждому нужно посмотреть код, оценить его, дать фидбек.</p>
<p>Если вы выложите ваше приложение куда-то, ревьювер сможет подергать методы или прожать кнопки. А также наверняка оценит то, что вы сэкономили ему время.</p>
<p>Для этого можно использовать различные облачные сервисы. Для бэкенда можно использовать <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.heroku.com/" rel="noopener noreferrer" target="_blank">Heroku</a>. Он интегрируется с GitHub и позволяет деплоить приложение по команде <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">git push</code>. Особенность Heroku в том, что он не обладает своей файловой системой, поэтому там нельзя хранить ничего, кроме кода, но можно подключить различные хранилища, например, базу данных. Есть бесплатные тарифы, которые идеально подойдут для выполнения такой задачи.</p>
<p>При этом, если вы используете какие-то проверки — например, линтеры и тесты, то код не будет деплоиться Heroku, если они будут провалены.</p>
<p>Для фронтенда можно использовать <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://vercel.com/" rel="noopener noreferrer" target="_blank">Vercel</a>, <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.netlify.com/" rel="noopener noreferrer" target="_blank">Netlify</a>, <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://pages.github.com/" rel="noopener noreferrer" target="_blank">Github Pages</a>. Кроме того, там тоже можно настроить сборку приложения и автоматизировать деплой.</p>
<h2 id="heading-2-7">Система контроля версий (VCS), Git</h2>
<p>Думаю, вы уже догадались, что нужно использовать <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://git-scm.com/" rel="noopener noreferrer" target="_blank">Git</a>. Именно вокруг него строятся различные интеграции и автоматизации. Прошли те времена, когда разработчики хранили на своем жестком диске копии файлов index.php, index_backup.php, index2.php на случай, если что-то пойдет не так.</p>
<p>Git позволяет работать одновременно над разными кусками кода, сравнивать их между собой. Хранит в себе историю изменений — кто, когда и что поменял. Использование этого инструмента — это еще одна санитарная норма в современной разработке.</p>
<p>Историю коммитов можно использовать для анализа того, как развивалось приложение, какие решения принимались, оценить навык использования инструмента. Иногда встречается такое, что в проекте за все время существования есть всего один коммит. Обычно я делаю вывод, что разработчик не любит пользоваться этим инструментом и проверяет у себя локально, отправляя в удаленный репозиторий готовое решение.</p>
<p>Старайтесь использовать понятные, краткие описания к коммитам. Желательно на английском языке или хотя бы на том, который принят в компании, для которой вы выполняете задание.</p>
<p>Если есть сложности в работе с Git — пройдите наш <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.hexlet.io/courses/intro_to_git" rel="noopener noreferrer" target="_blank">курс</a>. Помните, что это теория, которую стоит закреплять на практике.</p>
<p>Я не упомянул здесь <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.docker.com/" rel="noopener noreferrer" target="_blank">Docker</a>. Если вы умеете им пользоваться, это круто. Оформите конфиг и команды для запуска вашего приложения в Docker. Он позволяет упаковать приложение в изолированное окружение (например, настройки веб-сервера, специфические системные утилиты и пакеты), повысить переносимость, а инфраструктура приложения станет иммутабельной.</p>
<h2 id="heading-2-8">Архитектура, шаблоны, построение кода</h2>
<p>Хаха, а тут советов нет. Выдумывайте сами.</p>
<p>Нет, на самом деле. Задача тестового задания — проверить ваши знания. Конкретные штуки. Например, как вы применяете паттерны, если они нужны. Как структурируете код, какие абстракции выделяете. Тяжело давать советы, которые актуальны для всех. Просто пишите понятный код. Все будет зависеть от вашего опыта и знаний.</p>
<p>В вакансиях вы часто можете увидеть требование «писать понятный, чистый код». На самом деле это тяжело делать, если нет опыта. Поэтому просто пишите код, пишите код, пишите код.</p>
<p>Читайте книги, смотрите доклады, анализируйте код других разработчиков. Старайтесь понять, почему сделано именно так. Анализируйте популярные решения, почему они так реализованы.</p>
<p>Подходы и решения могут быть вообще разными в разных языках — код одного и того же веб-приложения на PHP и Ruby, Python, JS будет выглядеть по-разному. Некоторые решения будут просто не нужны в рамках других языков. Например, паттерны — их придумывают из-за несовершенства и ограничений языков.</p>
<p>Руководствуйтесь здравым смыслом. Например, если у вас есть шаблон странички и какие-то компоненты, будет некорректно обращаться к базе данных из шаблона. Кроме того, имена переменных должны быть понятными — избегайте ненужных сокращений, лишнего контекста. Если у вас какие-то данные или процедуры дублируются, значит, что это какая-то абстракция — и ее стоит выделить отдельно.</p>
<p>Если начитаться про паттерны, <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.wikipedia.org/wiki/SOLID_(%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)" rel="noopener noreferrer" target="_blank">SOLID</a> и другие принципы, можно легко уйти в <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=ok2cYf1Y8ig&feature=emb_logo" rel="noopener noreferrer" target="_blank">оверинжиниринг</a> (придумывать функционал на будущее). Старайтесь сделать свое решение простым и понятным (<a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.wikipedia.org/wiki/KISS_(%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF)" rel="noopener noreferrer" target="_blank">KISS</a>) — ведь скорее всего то, что вы заходите добавить, вам никогда не понадобится (<a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.wikipedia.org/wiki/YAGNI" rel="noopener noreferrer" target="_blank">YAGNI</a>). Готовьтесь обосновывать те решения, которые приняли в коде.</p>
<p>Программирование — это творческий процесс, который контролируете только вы. Практикуйтесь.</p>
<h2 id="heading-2-9">Работа над заданием, сбор фидбека</h2>
<p>Когда вам предлагают сделать тестовое задание, обычно сразу же указывают дедлайн. В других случаях компания может спросить у разработчика, сколько времени у него оно займет. Например, справитесь ли вы за неделю, либо вам понадобится всего два дня.</p>
<p>Без опыта невозможно дать грамотную оценку трудозатрат. Проблема с оценкой времени есть даже у опытных разработчиков. Поэтому прикиньте по времени, сколько вы будете работать над задачей, и возьмите немного времени с запасом.</p>
<p>Если возникают ситуации, когда вам непонятна формулировка задания или требования, лучше спросить, а не играть в угадайку. Потому что задания могут быть действительно неверно сформулированы, либо даже сделаны таким образом, чтобы побудить вас задавать вопросы.</p>
<p>Я слышал о ситуациях, когда разработчику было непонятно тестовое задание и он задавал по нему уточняющие вопросы. На это заказчик (работодатель) говорил, мол, вы не слишком самостоятельны, раз задаете много вопросов. Кажется, что это не очень правильно и нужно дважды подумать, прежде чем идти в такую компанию.</p>
<p>Если есть вопросы, спрашивайте. Если вы задерживаетесь с заданием, сообщайте об этом. Возможно, можно будет отправить задание попозже или частично завершенное. Важно иметь обратную связь, а не пропадать из поля зрения, если что-то пошло не так. Вопросы, связанные непосредственно с разработкой, лучше не спрашивать — типа «У меня проблема с такой-то библиотекой, которую вы сказали использовать, поможете?». Ведь то, как вы разберетесь с технологией, тоже является частью тестового задания.</p>
<p>Можно сразу же поделиться ссылкой на репозиторий, чтобы ревьювер мог смотреть за ходом разработки.</p>
<h2 id="heading-2-10">Где взять тестовые задания?</h2>
<p>У Хекслета есть <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/Hexlet/ru-test-assignments" rel="noopener noreferrer" target="_blank">репозиторий</a>, в котором сообщество делится тестовыми заданиями. Сюда присылают ссылки студенты, сторонние разработчики и даже сами компании. Задания самого разного уровня, на любой стек и уровень.</p>
<h2 id="heading-2-11">Как учиться писать более лучший код</h2>
<p>Практика, практика и еще раз практика. Как говорилось выше — пишите больше кода, читайте книги, изучайте проекты. У Хекслета есть множество проектов, в которых можно принять участие. За этими проектами следят и, как правило, хорошие практики переносятся из одного проекта в другой. Даже стек особо не важен. Например, в каждом проекте используется Makefile и есть подробное ридми для описания инструкций по работе с проектом. Вы можете подглядеть, как писать тесты, как работать с популярным фреймворком (Laravel, Ruby On Rails) и даже как создать инфраструктуру с помощью Terraform и Ansible (вряд ли это будет в вашем тестовом, ну а вдруг).</p>
<h2 id="heading-2-12">А можно не делать тестовое?</h2>
<p>На самом деле тестовое задание предлагается далеко не всем. Чаще всего их дают начинающим разработчикам или тем, у кого нет портфолио. В резюме соискатели пишут, что владеют определенными технологиями, и это нужно проверить. Бывает, что у компании специфический стек (типа Clojure), но у кандидатов нет опыта по этой технологии. Тогда могут найти опытного человека (который уже поработал программистом), но без опыта с нужной в компании технологией.</p>
<p>По моему опыту, чем больше у разработчика полезного кода на Github, тем выше вероятность, что ему не придется делать тестовое задание. Например, проекты Хекслета, <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://guides.hexlet.io/how-to-be-a-helpful-for-the-hexlet-community/" rel="noopener noreferrer" target="_blank">открытые проекты</a>, пет-проекты или тестовые задания. Например, я делал тестовое один раз, когда у меня не было даже проектов Хекслета. Потом это же тестовое пригодилось в поиске следующей работы, и в трудоустройстве в другую компанию.</p>
<h2 id="heading-2-13">Итого</h2>
<p>В этой статье мне хотелось рассказать вам про технологии, подходы и практики, которые можно использовать при работе над тестовым заданием.</p>
<p>Кто-то скажет, что не нужно насчет всего этого заморачиваться. Но я постоянно вижу, что кандидаты выполняют тестовое задание, но его толком не проверяют просто потому, что оно оформлено криво.</p>
<p>Часть перечисленных практик уже являются стандартами разработки. Попробуете один-два раза и поймете, насколько круто их использовать. Вы покажете, что знакомы с кучей технологий хотя бы поверхностно, и что это для вас не пустой звук. Тогда с вас останется просто писать грамотный код.</p>
<h2 id="heading-2-14">Полезные ссылки</h2>
<h3 id="heading-3-15">Git</h3>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/" rel="noopener noreferrer" target="_blank">GitHub</a> — git-хостинг и сообщество разработчиков</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://githowto.com/ru" rel="noopener noreferrer" target="_blank">Git How To: курс обучения Git на русском</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://habr.com/post/183646/" rel="noopener noreferrer" target="_blank">Стиль именования коммитов / Хабр</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://habr.com/ru/post/416887/" rel="noopener noreferrer" target="_blank">Как следует писать комментарии к коммитам</a></p>
<h3 id="heading-3-16">Автоматизация, CI/CD, деплой</h3>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://guides.hexlet.io/docker/#%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B2-%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%B9%D0%BD%D0%B5%D1%80%D0%B5" rel="noopener noreferrer" target="_blank">Как и для чего использовать Docker</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=WPCz_U7D8PI" rel="noopener noreferrer" target="_blank">Вебинар: Stateful vs. Stateless</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=QoCSvwkP_lQ" rel="noopener noreferrer" target="_blank">Никита Соболев — Автоматизируем все с GitHub Actions</a>. Доклад, рассказывающий, что такое Github Actions, с примерами использования</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://codeclimate.com/" rel="noopener noreferrer" target="_blank">Code Climate</a> — платформа для статистического анализа и поиска проблемных мест. Также позволяет оценивать покрытие кода с помощью скрипта (показывает бейджик с процентом покрытия тестами)</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://eslint.org/" rel="noopener noreferrer" target="_blank">Eslint</a> — линтер для Javascript</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/airbnb/javascript" rel="noopener noreferrer" target="_blank">airbnb style guide</a> — популярный стайлгайд для Javascript</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://jestjs.io/" rel="noopener noreferrer" target="_blank">Jest</a> — фреймворк тестирования для Javascript</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://testing-library.com/" rel="noopener noreferrer" target="_blank">Testing-library</a> — библиотека для тестирования фронтенда в Javascript</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://phpunit.de/" rel="noopener noreferrer" target="_blank">PHPUnit</a> — фреймворк для тестирования в PHP</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/squizlabs/PHP_CodeSniffer" rel="noopener noreferrer" target="_blank">PHP_CodeSniffer</a> — популярный линтер для PHP</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.php-fig.org/psr/psr-12/" rel="noopener noreferrer" target="_blank">PSR-12</a> — современные стандарты кодирования для PHP</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://vercel.com/" rel="noopener noreferrer" target="_blank">Vercel</a> и <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="http://netlify/" rel="noopener noreferrer" target="_blank"></a><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.netlify.com/" rel="noopener noreferrer" target="_blank">Netlify</a> — платформы для развертывания приложения (статика, фронтенд)</p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://heroku.com/" rel="noopener noreferrer" target="_blank">Heroku</a> — платформа для облачного развертывания приложения, подходит для бэкенд-приложений</p>
<style data-mantine-styles="inline">.__m__-_R_73derddmiub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:80%;}@media(min-width: 36em){.__m__-_R_73derddmiub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_73derddmiub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/gid-po-professii-testirovschik-chem-zanimaetsya-skolko-zarabatyvaet-chto-nado-znat-i-gde-uchitsya"><div style="padding-top:0rem;height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="margin-bottom:var(--mantine-spacing-sm)" class="m_599a2148 mantine-Card-section" data-first-section="true"><div style="--ar-ratio:2" class="m_71ac47fc mantine-AspectRatio-root"><img class="m_9e117634 mantine-Image-root" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MTYzNiwicHVyIjoiYmxvYl9pZCJ9fQ==--72f5a3fb78c634c408f39349dbd2e203809b4069/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX2FuZF9wYWQiOls3MDgsMzU0XSwic2F2ZXIiOnsicXVhbGl0eSI6ODV9fSwicHVyIjoidmFyaWF0aW9uIn19--324dc52aa55ebe818c2a887ebcb832b9ad1c0381/%D1%82%D0%B5%D1%81%D1%82%D0%B5%D1%80%D0%BE%D0%B2%D1%89%D0%B8%D0%BA2023-01.png" loading="lazy" alt="Кто такой тестировщик и как им стать"/></div></div><p style="margin-bottom:var(--mantine-spacing-xs);font-size:var(--mantine-font-size-lg);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Кто такой тестировщик и как им стать</p><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Рассказываем, кто такой тестировщик и чем он занимается, сколько зарабатывает такой специалист, а...</p><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-sm)" class="m_4081bf90 mantine-Group-root">29 декабря 2023 г.<p style="font-size:inherit" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/bolshe-zarabatyvat"><div style="padding-top:0rem;height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="margin-bottom:var(--mantine-spacing-sm)" class="m_599a2148 mantine-Card-section" data-first-section="true"><div style="--ar-ratio:2" class="m_71ac47fc mantine-AspectRatio-root"><img class="m_9e117634 mantine-Image-root" src="/vite/assets/blog_post-7eTyeLLt.webp" loading="lazy" alt="Как просить повышения зарплаты программисту и не бояться этого"/></div></div><p style="margin-bottom:var(--mantine-spacing-xs);font-size:var(--mantine-font-size-lg);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Как просить повышения зарплаты программисту и не бояться этого</p><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Вместе с карьерным коучем Оксаной Паниной рассказываем, как правильно просить прибавку к зарплате...</p><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-sm)" class="m_4081bf90 mantine-Group-root">24 ноября 2022 г.<p style="font-size:inherit" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/midly-i-senory"><div style="padding-top:0rem;height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="margin-bottom:var(--mantine-spacing-sm)" class="m_599a2148 mantine-Card-section" data-first-section="true"><div style="--ar-ratio:2" class="m_71ac47fc mantine-AspectRatio-root"><img class="m_9e117634 mantine-Image-root" src="/vite/assets/blog_post-7eTyeLLt.webp" loading="lazy" alt="Чему мидлы и сеньоры могут научиться на Хекслете: 10 направлений "/></div></div><p style="margin-bottom:var(--mantine-spacing-xs);font-size:var(--mantine-font-size-lg);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Чему мидлы и сеньоры могут научиться на Хекслете: 10 направлений </p><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">На Хекслете кроме профессий есть сотни курсов — не только с базовыми концепциями программирования...</p><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-sm)" class="m_4081bf90 mantine-Group-root">20 октября 2022 г.<p style="font-size:inherit" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></a></div></div></div></div></div>
<h3 id="heading-3-17">Дополнительно</h3>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://catwomenko.ru/2017/03/20/fastest-test-ever/" rel="noopener noreferrer" target="_blank">Как быстро стоит делать тестовое</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://refactoring.guru/ru" rel="noopener noreferrer" target="_blank">Рефакторинг и Паттерны проектирования</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="http://optimization.guide/" rel="noopener noreferrer" target="_blank">Продуманная оптимизация</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://12factor.net/ru/" rel="noopener noreferrer" target="_blank">The Twelve-Factor App (Русский перевод)</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://github.com/Hexlet/ru-test-assignments" rel="noopener noreferrer" target="_blank">Список тестовых заданий для прокачки</a></p>
<h3 id="heading-3-18">Книги</h3>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.ozon.ru/context/detail/id/138437220/" rel="noopener noreferrer" target="_blank">Совершенный код</a></p>
<h3 id="heading-3-19">Видео</h3>
<p>Доклады по ментальному программированию. Про важность нейминга и семантичности кода</p>
<ul>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=EEq1wdM2M2w" rel="noopener noreferrer" target="_blank">Часть 1</a></li>
<li><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=vkUTX1hruF8" rel="noopener noreferrer" target="_blank">Часть 2</a></li>
</ul>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=R-FfI4i0-uY" rel="noopener noreferrer" target="_blank">Доклад «Снесите это немедленно»</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=_tPRetDsLj4&list=PLo6puixMwuSOnsZFbZRg0i2SmoJediaCA&index=2" rel="noopener noreferrer" target="_blank">Как писать качественный и понятный код? Чистые функции</a></p>
<p><a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://www.youtube.com/watch?v=zsz8kdi62mE&list=PLo6puixMwuSPfJVVXKhLkHCymzEQAKxjr&index=48" rel="noopener noreferrer" target="_blank">Начинаем писать тесты (правильно)</a></p></div><div class=""><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap;margin-bottom:var(--mantine-spacing-lg)" class="m_4081bf90 mantine-Group-root"><div class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:var(--mantine-spacing-xs);color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-user "><path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0"></path><path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2"></path></svg></div><p style="margin-inline-end:var(--mantine-spacing-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Nikolai Gagarinov</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">4 года назад</p></div><div style="align-items:center" class="m_8bffd616 mantine-Flex-root __m__-_R_5dirddmiub_"><a style="display:inline-flex" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/kak-razrabotchiku-uluchshit-svoe-testovoe-zadanie/votes"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:var(--mantine-spacing-xs);color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-thumb-up "><path d="M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3"></path></svg></div></a><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">34</p></div></div></div><div style="background-color:var(--mantine-color-indigo-light);border:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding:var(--mantine-spacing-xl)" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root"><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h4)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Читайте также:</p><ul style="margin-inline-start:var(--mantine-spacing-lg)" class="m_abbac491 mantine-List-root"><li style="margin-bottom:var(--mantine-spacing-sm)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><a style="color:inherit" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/gid-po-professii-testirovschik-chem-zanimaetsya-skolko-zarabatyvaet-chto-nado-znat-i-gde-uchitsya">Кто такой тестировщик и как им стать</a></span></div></li><li style="margin-bottom:var(--mantine-spacing-sm)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><a style="color:inherit" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/bolshe-zarabatyvat">Как просить повышения зарплаты программисту и не бояться этого</a></span></div></li><li style="margin-bottom:var(--mantine-spacing-sm)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><a style="color:inherit" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/blog/posts/midly-i-senory">Чему мидлы и сеньоры могут научиться на Хекслете: 10 направлений </a></span></div></li></ul></div><div style="margin-block:var(--mantine-spacing-xl)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div></div><div></div></div><style data-mantine-styles="inline">.__m__-_R_lmiub_{--col-flex-grow:auto;--col-flex-basis:100%;--col-max-width:100%;}@media(min-width: 48em){.__m__-_R_lmiub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}@media(min-width: 62em){.__m__-_R_lmiub_{--col-flex-grow:auto;--col-flex-basis:33.333333333333336%;--col-max-width:33.333333333333336%;}}</style><div class="m_96bdd299 mantine-Grid-col __m__-_R_lmiub_ mantine-visible-from-md"><div style="background-color:var(--mantine-color-indigo-light);border:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-bottom:var(--mantine-spacing-xl);padding:var(--mantine-spacing-xl);width:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root"><div style="margin-bottom:var(--mantine-spacing-md)" class="m_4451eb3a mantine-Center-root" data-inline="true"><p style="font-size:var(--mantine-font-size-h4)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Категории</p></div><ul class="m_abbac491 mantine-List-root"><li style="margin-bottom:var(--mantine-spacing-xs)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><button style="color:inherit;text-decoration:underline" class="mantine-focus-auto m_87cf2631 mantine-UnstyledButton-root" type="button" aria-label="Мотивация">Мотивация</button></span></div></li><li style="margin-bottom:var(--mantine-spacing-xs)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><button style="color:inherit;text-decoration:underline" class="mantine-focus-auto m_87cf2631 mantine-UnstyledButton-root" type="button" aria-label="Истории успеха">Истории успеха</button></span></div></li><li style="margin-bottom:var(--mantine-spacing-xs)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><button style="color:inherit;text-decoration:underline" class="mantine-focus-auto m_87cf2631 mantine-UnstyledButton-root" type="button" aria-label="Дневник студента">Дневник студента</button></span></div></li><li style="margin-bottom:var(--mantine-spacing-xs)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><button style="color:inherit;text-decoration:underline" class="mantine-focus-auto m_87cf2631 mantine-UnstyledButton-root" type="button" aria-label="Код">Код</button></span></div></li><li style="margin-bottom:var(--mantine-spacing-xs)" class="m_abb6bec2 mantine-List-item" data-with-icon="true"><div class="m_75cd9f71 mantine-List-itemWrapper"><span class="m_60f83e5b mantine-List-itemIcon"><div class="m_4451eb3a mantine-Center-root"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-chevron-compact-right "><path d="M11 4l3 8l-3 8"></path></svg></div></div></span><span class="mantine-List-itemLabel"><button style="color:inherit;text-decoration:underline" class="mantine-focus-auto m_87cf2631 mantine-UnstyledButton-root" type="button" aria-label="Карьера">Карьера</button></span></div></li></ul></div><div style="justify-content:end;margin-top:0rem;position:sticky;top:calc(5rem * var(--mantine-scale))" class="m_8bffd616 mantine-Flex-root __m__-_R_5dlmiub_"><div tabindex="0" style="cursor:pointer"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses_php?promo_name=program_category&promo_position=blog_post&promo_creative=card&promo_type=card"><div style="background-color:var(--mantine-color-default);border:calc(0.0625rem * var(--mantine-scale)) solid var(--mantine-color-default-border);padding-inline:var(--mantine-spacing-xl);padding-top:var(--mantine-spacing-xl);padding-bottom:var(--mantine-spacing-xs);width:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root"><div class="m_4451eb3a mantine-Center-root" data-inline="true"><p style="font-size:var(--mantine-font-size-h4)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Курсы по PHP</p></div><img class="m_9e117634 mantine-Image-root" src="/vite/assets/development-BVihs_d5.png"/><p style="margin-bottom:var(--mantine-spacing-xs);text-align:right" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></a></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-CdBlNCiQ.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>