Как эффективно использовать TDD в React



Книга Как эффективно использовать TDD в React



С методологией TDD (Test-Driven Development) связано немало противоречивых мнений. Но не будем вступать в дискуссии о востребованности TDD. Сейчас я постараюсь показать пользу этого инструмента в повседневной разработке кода, рассматривая его лишь с точки зрения практической ценности.



Skillfactory.ru

1. Постановка задачи


В качестве примера будем использовать приложение Buy Some Milk.


Приложение Buy Some Milk

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


Вот типичный сложный пример  —  подмножество функций (свойств). Их нужно разбить на части. Такой процесс называют постановкой задачи.


Это важнейшая составляющая, требующая тщательного исполнения. Но бояться не стоит. Здесь, как и во всем остальном, нужна лишь некоторая практика.


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


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


Задачи


Каждая из задач должна удовлетворять принципам S.M.A.R.T.



  • Specific  —  соответствие специфике задачи.

  • Measurable  —  успешность решения задачи должна подтверждаться тестами.

  • Achievable  —  достижимость, нельзя сделать что-то сверх наших возможностей.

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

  • Time-boxed  —  необходимо отслеживать длительность исполнения. Чрезмерная длительность может указывать на превышение размеров или на невыполнимость задачи.


Для примера Buy Some Milk нетрудно составить список удовлетворяющих таким принципам задач:



  • рендеринг элемента;

  • рендеринг нескольких элементов;

  • добавление элемента в список;

  • очистка поля ввода после добавления элемента;

  • пометка выполненного элемента.


2. Написание теста для отката в случае сбоя


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


Убедитесь, что механизм тестирования работает


Добавляя тесты к существующему коду, важно убедиться, что они связаны с кодом продукта. Например, система запуска ожидает __tests__/*.test.tsx, и когда вы добавите Todo.spec.tsx, он будет проигнорирован. Если тесты пройдены успешно, вы можете оказаться в заблуждении, продолжая править код до тех пор, пока не станет слишком поздно.


Дополнительно я (как и многие другие программисты) всегда применяю еще одну проверку. Это попытка нарушить работу действующего теста. Например, учитывая, что текущий calculate.test.ts проходит успешно, я изменяю некоторую логику в calculate.ts, чтобы проверить, проходит ли теперь тест.


Функция add

В calculate я изменяю add в:


export const add = (x, y) => x - y;

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


Написание тестов


Помните, тестировать всегда нужно с точки зрения пользователя. Пару лет назад в сообществе React была довольно популярна библиотека Enzyme. Ее самым большим недостатком было то, что она чаще тестировала внутреннее состояние, а не поведение.


Например, с Enzyme может быть такой код:


Использование Enzyme для тестирования

Но тесты react-testing-library фокусируются больше на поведении компонента, чем на внутреннем состоянии.


react-testing-library для тестирования поведения

Обратите внимание на API: getByText проверит, есть ли в DOM этот контент (точно так же, как это сделал бы реальный пользователь в браузере), как и toBeInTheDocument, фокус смещается на пользователя (а не на разработчика).


При создании теста описывайте по возможности поведение. И проверяйте бизнес-возможность, а не внутреннее состояние.


3. Создание теста с минимальными усилиями


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


Магические числа (magic numbers), встроенные функции, вложенные операторы if-else и прочее  —  все это подойдет на данном этапе. Но не останавливайтесь на достигнутом. Как только тесты станут рабочими, ищите возможности их улучшить.


4. Выполнение рефакторинга


Мартин Фаулер в своей книге “Рефакторинг: улучшение дизайна существующего кода” дает такие определения.



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




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



Ключевыми особенностями здесь являются.



  1. Изменения не должны менять наблюдаемое поведение.

  2. Изменения должны быть небольшими и последовательными.


Во время рефакторинга нужно следить за статусом теста. После завершения рефакторинга (переименование, извлечение переменной в константу или извлечение фрагмента в функцию) он всегда должен иметь статус passing (успешное завершение). Кроме того, сохраняйте каждое небольшое изменение. По завершении рефакторинга и тестирования я обычно делаю локальную фиксацию (commit). А если предстоит сделать несколько фиксаций, их всегда можно объединить перед отправкой на удаленный сервер.


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


После удачного завершения рефакторинга, можно применить шаги 2-4 ко всем остальным задачам из списка.


5. Отзывы коллег


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


Я предпочитаю пошаговый анализ (5-10 минут), чтобы обсудить предысторию, проблемы и использованные решения. И при этом часто получаю несколько полезных предложений, позволяющих очистить код, сделать его более понятным.


Есть и другие преимущества такой экспертной оценки внутри команды:



  • обмен специфическими познаниями;

  • обмен мнениями по проблеме;

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


Заключение


В этой статье не рассматривалась целесообразность применения TDD. Она заинтересует в первую очередь тех, кто намеревается использовать эту методику. Выполняя рассмотренные шаги, можно увидеть, как она действует. Эти 5 простых и действенных шагов я регулярно выполняю практически со всеми своими задачами. Считаю, что это приносит большую пользу и мне, и моим коллегам в разных проектах.



Skillfactory.ru


83   0  
    Ничего не найдено.

Добавить ответ:
Отменить.