Connect with us

Программирование

Лучше код – проще тестирование

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

Анна Гуляева

Опубликовано

/

     
     

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

Тестирование – неизбежный краеугольный камень любого проекта, стоящий всех трудов. Это не значит, что процесс сам по себе приносит удовольствие, на самом деле многие программисты вздрагивают при одной мысли о том, чтобы потратить драгоценные часы на тестирование кода, который и так работает. Postman должно быть достаточно, да?

Ну нет. И вы никогда не должны ориентироваться на удобство: пока вы не протестировали и не исправили все возможные аспекты вашего кода, он не может считаться законченным. И более того, выработка хороших привычек тестирования со временем изменит ваш подход к написанию кода. Вы скоро заметите, что вы пишете более красивый и чистый код, потому что у вас в подсознании сидит мысль: “Как я протестирую эту функцию?” Давайте перейдем к делу!

Красота и бойлерплейт

Тестирование требует определенного уровня знакомства с процессом создания кода и лучшими практиками, так как создание чистого кода значительно снижает расходы на тесты. Что это значит? Что ж, рассмотрим довольно распространенный бэкенд-процесс: создание процесса регистрации пользователя для некого API. Просто, да?

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

Программисту А могут не нравиться promise, поэтому он отказывается от обеспечения связности и читаемости и просто используют callback  функции для работы со всеми своими асинхронными вызовами. Это очень распространено среди начинающих программистов (виноват, я и сам так делал в самом начале работы). Так как это работает, программист может даже не задумываться об изучении promise – зачем? Оказывается, существует очень хорошая причина (помимо преимуществ обучения и самосовершенствования).

Если вы постоянно используете обратные вызовы, случается “ад обратных вызовов”, что делает тестирование этого кода реальным вызовом! Не говоря уже о том, что ваш код выглядит ужасно уродливо.

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

С другой стороны, программист Б знает promise и любит их. Почему бы их не любить? Когда вы правильно соединяете их, они выглядят хорошо, занимают меньше места на экране, в них проще находить ошибки и их проще тестировать.

Итак, программист Б, более опытный и уверенный в своей способности к решению проблем, работает с promise с самого начала, создает красивый и читаемый код, который делает свою работу, и не нагромождает пирамиды из скобок и диагонального кода.

user.save()
 .then(user => res.status(200).send(user))
 .then(() => console.log('User saved'))
 .catch(error => next(error))

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

Что посеешь – то и пожнешь

В конце концов, оба подхода приводят к завершению работы. Давайте посмотрим, как наши программисты справляются с тестированием кода. Мы изучим два случая: юнит-тестирование для хелперов (utils) и компонентное тестирование для самих контроллеров.

Программист А начинает работать над юнит-тестами… и он понимает, что у него почти нет хелперов для тестирования. Так как он не позаботился о том, чтобы разделить фрагменты кода, которые снова можно использовать, на отдельные файлы, многие из “хелперов” включены в контроллер, что приводит к огромному количеству скопированного и вставленного стандартного кода.

Контроллер может выполнять свою работу, но этот подход ухудшает читаемость и приводит к тому, что программисту А нужно тестировать один и тот же код снова и снова.

У программиста Б, с другой стороны, все хелперы организованы в папке utils и могут быть вызваны по необходимости. Этот подход позволяет программисту Б провести юнит-тест для каждого из них один раз, и он знает, что если тест был пройден, то он будет пройден для каждой функции в контроллере. Чисто, быстро и менее затратно.

Время компонентного тестирования!

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

Давайте посмотрим, как дела у программиста Б. Отлично! Он только что закончил компонентное тестирование для процесса регистрации, который стал гораздо проще, потому что хелперы уже протестированы с самого начала.

Конечно, больше всего времени здесь экономят promise. Вместо того, чтобы постоянно тестировать каждую ошибку для каждой функции обратного вызова, как программист А, программист Б всего лишь должен протестировать каждый promise дважды. Это упрощается процесс, потому что promise показывает ошибки в блоке .catch() в конце каждой цепочки promise, отображая возможный отказ каждого promise над блоком .catch().

Умный код, простые тесты, счастливый разработчик

Можно сказать, что программисту Б гораздо проще тестировать процесс регистрации, а дальнейшая разработка контроллера будет проще с разделенными хелперами и использованием promise для улучшенной читаемости и функциональности кода.

Эти примеры очень субъективны и случайны, и я специально не сказал о некоторых современных функциях вроде async/await из ES8, чтобы объяснить свою позицию максимально просто: размышляя о тестировании, вы неизбежно создадите более качественный код, который будет легко тестировать.

Это как цикл положительной обратной связи: подсознательно вы начнете думать о коде с позиции тестирования во время его создания. Сохраните себе нервы – в будущем вы будете благодарны.

 

Комментарии
Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Advertisement
 
Click to comment

You must be logged in to post a comment Login

Leave a Reply

Популярное

X
X

Спасибо!

Теперь редакторы в курсе.