Оффтоп Digital Skynet
170

За что я ценю тестирование и почему советую вам делать то же самое

В закладки

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

Внедряя тесты в приложения, я осознал насколько эффективно тестирование и как оно влияет на качество кода.

Краткий обзор стека технологий для тестирования

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

Enzyme - это тестовая утилита для React. Волшебство в том, что он отображает ваши компоненты React в Jest. Это позволяет эффективно протестировать JSX-код без ручной транскомпиляции. Вы создаете компоненты, используя один из трех методов: shallow, mount или render.

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

Вот что я узнал.

Тестирование предотвращает регрессию

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

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

Юнит-тестирование с помощью mocks и stubs

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

Чтобы этого избежать, вы можете заменить эти зависимости mocks или stubs. В итоге результат будет таким, как вы и ожидаете.

Например, вы хотите протестировать этот метод:

Stub:

Mock:

Главное различие между stubs и mocks заключается в том, что в одном случае мы управляем состоянием, а в другом - поведением.

Когда мы используем mocks, мы заменяем весь модуль на mock (ложный, тестовый объект, имитирующий настоящий). А stub - это функция, которая всегда выводит один и тот же результат, вне зависимости от того, что было подано на вход. Mocks используют для того, чтобы проверить, была ли функция вызвана с правильными аргументами, а stubs, чтобы протестировать, как функция работает с полученным ответом. Стабы нужны для проверки состояния метода, а моки используются для регулировки поведения.

Знайте что проверять не нужно

Имейте в виду, что не нужно тестировать весь код.

При помощи Jest, вы можете легко отслеживать свое тестовое покрытие, добавив --coverage в тестовый скрипт в CLI (интерфейс командной строки). Хотя это полезный метод, отнеситесь к нему с долей скептицизма. Способ, которым Jest измеряет охват теста, заключается в отслеживании стека вызовов, поэтому более высокое покрытие теста не означает, что ваши тесты эффективны.

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

Представим компонент Listings с методом renderCarousel, который отображает карусель из внешней библиотеки:

Неэффективный тест:

Эффективный тест:

Разница между ними заключается в том, что именно тесты на самом деле проверяют.

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

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

Хорошие тесты = хороший код

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

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

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

Пишите тесты по мере написания кода

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

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

В системе с абстрагированными API-интерфейсами вы можете протестировать каждый класс, прежде чем двигаться дальше. Это позволит узнать, где допущена ошибка. Например, метод «get» вызывает getData для взаимодействия с базой данных. Сначала я бы написал тесты для getData и удостоверился, что они зеленые. И если какой-либо из моих тестов для контроллера терпит неудачу, возможно, это связано с тем, как я вызываю getData.

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

https://martinfowler.com/articles/mocksArentStubs.html

https://medium.com/@rickhanlonii/understanding-jest-mocks-f0046c68e53c

Адаптированный перевод статьи Why I now appreciate testing, and why you should, too от Digital Skynet :)

Материал опубликован пользователем. Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Digital Skynet", "author_type": "self", "tags": [], "comments": 1, "likes": 0, "favorites": 3, "is_advertisement": false, "subsite_label": "flood", "id": 44925, "is_wide": false, "is_ugc": true, "date": "Tue, 04 Sep 2018 14:20:44 +0300" }
{ "id": 44925, "author_id": 187179, "diff_limit": 1000, "urls": {"diff":"\/comments\/44925\/get","add":"\/comments\/44925\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/44925"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 199791 }

1 комментарий 1 комм.

Популярные

По порядку

0

Было бы классно увидеть рекомендации по сервису, где тестят живые люди, если таковые есть

Ответить
0
{ "page_type": "article" }

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "240х200_mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "flbq" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Плашка на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } }, { "id": 19, "label": "Тизер на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "p1": "cbltd", "p2": "gazs" } } } ]
Хакеры смогли обойти двухфакторную
авторизацию с помощью уговоров
Подписаться на push-уведомления
{ "page_type": "default" }