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

В Crave мы используем тестовую настройку с Mocha + jsdom и достаточно строгий конфиг для JSLint. Мы также следим за тем, чтобы все пулл-реквесты редактировались одним человеком, а не первоначальным автором кода. Даже с этой настройкой иногда мы сталкиваемся с проблемами в нашем коде. Когда происходят такие случаи, возникает вопрос, который мы пытаемся поднять: Как мы можем автоматически обнаружить эту проблему, прежде чем она повторится?.

На прошлой неделе мы столкнулись с этой ситуацией во время небольшого/среднего рефакторинга. По сути, проблема была вызвана тем, что мы изменили API компонента, который использовался во многих разных местах, но мы не обновили все места, используя старый компонент. Во время выполнения React регистрировал предупреждения в браузере (используя console.error), но наши тесты не улавливали их.

Первое решение, которое пришло нам в голову, состояло в том, чтобы написать лучшие модульные тесты для этого компонента. Очевидно, что это сработает, но мы будем полагаться на большее количество кода, что подразумевает большее количество обзоров и, возможно, больше проблем.
Поскольку React предоставляет нам валидацию Prop с использованием PropTypes, казалось логичным, что валидация PropTypes будет интересным способом.

После некоторых исследований я нашел текст Bonnie Eisenman о валидации PropTypes. Она предложила писать тесты, используя макеты, чтобы отслеживать ошибки консоли и, если нужно, не проходить тесты. Кристофер Кук также предложил реализовать собственный сопоставитель Jasmine, чтобы писать более разборчивые тесты.

Это оказалось очень полезной идеей, но поскольку мы не используем Jasmine, нам пришлось бы ее адаптировать. Также по идее Бонни потребуется написать тест для каждого компонента.

После еще нескольких экспериментов мы подумали об использовании крючков Mocha beforeEach и afterEach. Используя эти хуки, мы могли бы проверять журнал консоли для каждого теста, а также вызывать сбой теста, если это необходимо.

Это почти сработало, но так как мы уже издевались над console.error с помощью SinonJS, тесты начали давать сбои из-за двойного исправления. Поскольку мы не хотели, чтобы эти тесты зависели от глобального исправления, мы выбрали другую альтернативу: исправление обезьяны.

По сути, мы использовали установочный файл M0cha (setup.js), чтобы заменить наш console.error функцией, которая выполняла бы ту же задачу, но выдавала бы ошибку, если бы она вызывалась с использованием некоторых предупреждающих сообщений React.

Вот так это выглядит в итоге:

При таком подходе, если компонент попытается использовать другой компонент, передающий свойства, которых не существует, тест завершится ошибкой и будет выведено сообщение об ошибке. Этот подход в настоящее время работает для React 0.14.x, но мы еще не тестировали React 15 (есть вероятность, что нам потребуется обновить константу ERROR_MESSAGES).

Если у вас есть какие-либо предложения, пожалуйста, сообщите нам об этом в комментариях!