Около 6 месяцев назад охват тестированием нашей команды был довольно мрачным, колеблясь где-то около 0% для большинства наших интерфейсных приложений… да, мы знаем. Команда недавно перешла на использование ReactJS, быстро расширялась и боролась с жесткими сроками. Тестирование было первым делом. Я имею в виду, что у нас есть команда QA, верно?

Перенесемся в настоящий момент, и наше тестовое покрытие взлетело до примерно 20% на каждое приложение! Написание тестов, конечно, не бесплатно. Есть много накладных расходов и первоначальной работы, чтобы заставить работать модульные и сквозные тесты. Так зачем это делать? Каковы реальные преимущества?

Как это снова работает?

В большинстве нетривиальных приложений есть несколько мест, где логика усложняется, и люди опасаются вносить изменения. В прошлый раз мы там что-то поменяли, говорят, сломалось все приложение. Где-то есть таблица Excel со списком из 10 сценариев, которые нужно протестировать, когда вы вносите изменения… отлично. Или того хуже, просто спросите Сару, как это работает, она написала это 5 лет назад 🤷‍♀.

Написание тщательных, исчерпывающих тестов для этих частей вашего приложения придаст вам уверенности в проведении рефакторинга. Удалите кусок кода с подозрительным комментарием //not sure what this does but it works...

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

100% тестовое покрытие

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

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

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

Проверяю ли я все сценарии?

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

Если вы используете шутку, вы можете просто запустить jest colllectCoverage, чтобы получить визуальное представление о количестве пройденных строк кода и логических путях, пройденных во время тестирования. Вы можете найти этот файл на coverage/lcov-report

Написание тестируемого кода

Когда наша команда впервые начала писать тесты, мы заметили, насколько сложно тестировать некоторые из наших компонентов. Я считаю, что хорошо структурированный код поддается тестированию. Рефакторинг кода просто для того, чтобы тесты прошли, вероятно, плохая идея, но в основе проблемы часто лежит тесная связь между логикой представления и состояния, встраивание слишком большого количества логики в компоненты стиля швейцарской армии (это кнопка, но также может быть переключатель!) или какой-либо другой нежелательный шаблон (он же hax), который проскользнул в вашу кодовую базу. Как это туда попало? 😅

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

Обертывание сторонних библиотек с использованием шаблона адаптера может иметь такое же преимущество: вместо тестирования или имитации деталей реализации библиотеки, которую вы не контролируете, вы можете заключить ее в объект (или компонент), который раскрывает интересующие вас функции. и его легко можно высмеять.

Извлечение часто используемых функций в отдельный файл делает написание тестов для них почти тривиальным. Их тестирование с помощью прокси-сервера путем запуска действий пользователя часто приводит к тому, что тесты сложнее написать и, вероятно, будут более хрупкими. Вы хотите проверить, что ваша submitOrder функция действительно преобразует данные в orderObject, но вместо этого вы пишете тест, в котором пользователь нажимает кнопку, а затем проверяет полезную нагрузку, отправленную на ваш api, которую вы удаляете.

Напишете тесты

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