Как правильно писать на тест
Перейти к содержимому

Как правильно писать на тест

  • автор:

Начинаем писать тесты (правильно)

Начинаем писать тесты (правильно) главное изображение

Как начать писать тесты? Сколько нужно писать? На что их нужно писать, а на что — не нужно? Стоит ли всегда применять TDD? Если вас интересуют ответы на эти вопросы, то вы читаете правильную статью. В своей жизни я написал не одну тысячу тестов всех мастей для разных платформ, использовал во всех полях TDD и ставил процесс тестирования в командах, проектах и даже целых компаниях. И теперь я попробую обобщить этот опыт и поделиться им.

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

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

Подписывайтесь на канал Кирилла Мокевнина в Telegram — чтобы узнать больше о программировании и профессиональном пути разработчика

Начнем, пожалуй, с самого главного вопроса: зачем нам вообще нужно тестировать?

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

Следующий ключевой тезис не является особенностью процесса тестирования. Задачи можно условно поделить на два типа: они либо завершены, либо нет, а завершенность задач второго типа — это шкала, где 0 — это «ничего не сделано», а 1 — это сделано на 100%. При решении таких задач 100%-решение часто оказывается недостижимым из-за сверхвысоких накладных расходов.

Приведу прекрасный пример. Для многих сервисов критично такое понятие как SLA или, проще говоря, доступность сервиса. Например, на хостинговых площадках пишут что-то в духе «мы обеспечиваем доступность 99.9% наших серверов». Давайте прикинем, сколько часов за год хостинг может оказаться недоступен в рамках его SLA: 0.001 * 365 * 24 = 8.7 . В принципе, неплохо.

Предположим, что обеспечение такого уровня доступности обходится компании в 1000$ . А во сколько обойдется компании добавление каждой новой девятки в конце? То есть обеспечение 99.99 , 99.999 и так далее. Насколько мне известно, на таком уровне обеспечения происходит экспоненциальный (взрывной) рост стоимости. Я уже не говорю про то, что 100%-доступность является фантастикой.

Этот пример ярко демонстрирует то, что в задачах с плавающим результатом главным принципом является «максимальный результат за минимальные ресурсы». Другими словами, ищется баланс, при котором мы получаем результат, удовлетворяющий стейкхолдеров (заинтересованных лиц), за приемлемый бюджет/сроки.

Теперь возвращаемся к нашим тестам и обнаруживаем, что тесты относятся именно к этому типу задач. Добавление первых тестов в проект дает невероятный эффект. Покрытие в 50% (половина кода вызывается в тестах) получается почти сразу, и по сравнению с отсутствием тестов — мы на два корпуса впереди. Дальше ситуация начинает меняться, и где-то на уровне 70-90% начинается резкое замедление роста покрытия, тесты становятся все более точечными, дорогими. Возрастает сложность их поддержки, рефакторинга.

Этот процесс бесконечен. Добиться 100% покрытия очень дорого и, скорее всего, неоправданно (см. пример выше). Кроме того, никакие тесты не дают вам полную гарантию работоспособности.

Кроме количества тестов и их качества, на стоимость также влияет то, какой тип тестов мы используем. Существует множество классификаций видов тестов, таких как: «по знанию системы», «по степени автоматизации», «по времени проведения тестирования». На этом этапе нас интересует только одна классификация: «по степени изолированности компонентов»:

  • Модульное тестирование
  • Интеграционное тестирование
  • Системное тестирование (приемочное)

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

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

Так вот, есть только шкала. Чем более простую и мелкую часть системы мы тестируем — тем дешевле тесты, чем более сложную (составную) — тем дороже. И ваша задача как специалиста — исходить не из того, чтобы соответствовать своим представлениям о видах тестирования, а писать тесты так, чтобы они в идеале покрывали большее число кейсов при небольших затратах. Я уверен, что на этой фразе некоторые разработчики напряглись, потому что в их картине мира нужно обязательно писать изолированные юнит-тесты, а приемочные должны писать только тестировщики. Не буду разводить полемику, просто скажу, что бывает по-разному. Есть проекты, в которых процент юнит-тестов (в самом жестком понимании) составляет доли процента от всех остальных тестов (как в Хекслете, хе-хе), а есть те, где пишут только приемочные тесты (отдельные тестировщики).

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

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

Основной наблюдаемый мной анти-паттерн в разработке подобных библиотек — это тесты на внутренние мелкие компоненты. Те самые юнит-тесты. Почему такой подход непродуктивен? Возможно, это и не очевидно, но такое тестирование, хоть и является модульным, но не является дешевым и качественным. Но, как…?

Мы уже говорили о том, что архитектура проекта еще неизвестна, и, как правило, внутреннее разделение на файлы/модули/классы/функции меняется с космической скоростью. В течение часа все может быть переписано несколько раз. Но теперь вместе с кодом нужно постоянно править тесты, что начинает раздражать. Программист начинает сомневаться в том, что они вообще ему нужны, и нередко просто перестает их писать. Другие продолжают мучаться и переписывать их, хотя чаще происходит другое. Написанные тесты начинают вас сковывать и мозг шлет команды «ты потратил время, оставь все как есть». Постепенно рефакторить становится все сложнее и ленивее. Это очень похоже на ситуацию, когда предприниматель инвестировал деньги в новое направление и, даже если бизнес уже тонет, ему тяжело отказаться, ведь было потрачено столько сил и средств (в экономике это называют sunk cost fallacy , — прим. ред.).

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

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

Более низкий уровень — это функция, которая принимает на вход путь до файла и подстроку для поиска, а на выходе (не печатает на экран!) отдает готовый результат, так, чтобы осталось только напечатать его. Такой вид тестов обладает самым лучшим балансом «убедиться в том, что все работает/стоимость». Они косвенно затрагивают все используемые внутренности, не зависят от реализации, очень просты в написании и крайне дешевы в поддержке. По мере стабилизации архитектуры можно добавлять тесты более низкого уровня (если становится понятно, что сложность системы слишком высока).

TDD

Описанная методика особенно хорошо работает в связке с подходом, когда тесты пишутся до кода (вместе с кодом).

Существует миф о том, что тесты нужны только для регресса, то есть для уверенности, что новый код не сломал старый. Это далеко не так. Более того, это следствие написания тестов как таковых. В некоторых ситуациях первостепенная цель написания тестов — это ускорение разработки. Да-да, вы не ослышались, написание тестов до кода/одновременно с кодом, приводит к серьезному ускорению разработки. Чаще всего такие ситуации связаны с тем, что на вход подаются сложные данные, которые как-то трансформируются и прокидываются дальше. Тестировать руками (во время разработки) такой код очень сложно, нужно подготавливать данные, нужно проверять, что результат соответствует ожидаемому.

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

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

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

Дополнительные ссылки

  • Видео версия статьи
  • Бережливое тестирование

Как сделать тест на беременность

В период беременности в женском организме начинает вырабатываться особенный гормон — ХГЧ (хорионический гонадотропин человека). Его концентрация особенно высока на ранних сроках и увеличивается быстрыми темпами, начиная со 2-ой недели от зачатия. Так в период с 1-ой по 2-ую недели содержание ХГЧ доходит до показателей 25-100 мМЕ/мл.

Тесты для определения наличия беременности по содержанию ХГЧ дают положительный ответ уже при 20 мМЕ/мл, то есть эффективны с первого дня задержки менструации. Но не рекомендуется использовать тесты до задержки, так как они могут выдать ложноотрицательный результат (недостаточная концентрация ХГЧ).

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

В какое время необходимо проводить тест

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

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

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

Если вы не помните дату последней менструации, но знаете предполагаемую дату зачатия, проводите тест через 20 дней после нее.

Как сделать тест на беременность

В аптеке вы найдете несколько вариантов тестов: струйные и тест-полоски, с указанием предполагаемого срока и без. Чтобы получить достоверный результат, тест необходимо правильно использовать, а затем интерпретировать увиденное. Как сделать тест на беременность в зависимости от его формы, читайте ниже.

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

Как пользоваться струйным тестом

  • Достаньте тест из упаковки.
  • Удалите защитный колпачок, но не выбрасывайте.
  • Направьте часть теста с индикатором вниз под струю мочи на 5-7 секунд.
  • Наденьте колпачок на тест.
  • Поместите тест на сухую поверхность.
  • Проверьте результат через 5 минут (но не дольше, чем через 10).

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

Как сделать тест-полоску:

  • Достаньте тест из упаковки, держась за цветной конец.
  • Опустите тест в емкость с мочой до нужной отметки на 5-7 секунд.
  • Поместите тест на сухую поверхность.
  • Проверьте результат через 5 минут (но не дольше, чем через 10).

Чтобы оценить результат теста правильно, воспользуйтесь инструкцией от производителя.

Обычно результат может быть представлен в трех видах:

  • Полоски. Самые распространенные тесты показывают результат в виде одной (не беременны) или двух полосок (беременны).
  • Плюс и минус. Другая часть сообщает новости в виде «+» (беременны) или «-» (не беременны).
  • Слова и цифры. Некоторые современные тесты показывают результат словами или цифрами (срок беременности).

Как тест на беременность определяет беременность

В тесте содержатся реагенты, которые отвечают на содержание в моче гормона ХГЧ. Если тест используется со дня ожидаемого начала менструации — его точность составляет свыше 99%. Но есть и погрешность, которая чаще всего связана с нарушениями инструкции или определенными состояниями женского организма.

Что может повлиять на тест на беременность

  1. Ложноположительный результат можно получить при приеме препаратов от бесплодия, которые содержат гормон ХГЧ. Как правило, это препараты, которые вводятся в форме инъекций.
  2. Ложноотрицательный результат может быть следствием приема некоторых гормональных препаратов, которые влияют на цикл (например, гормональные контрацептивы). В этом случае из-за сбоя цикла вы рискуете провести тест раньше времени.
  3. Положительный результат теста также можно получить, если вы недавно были беременны, имеете кисту яичников или внематочную беременность. Поэтому в случае неожиданного положительного результата рекомендуется незамедлительно проконсультироваться с врачом.
  4. Ошибочные данные вы также рискуете увидеть на тесте, который пролежал после использования более 10 минут.

Если соблюдать все рекомендации по использованию, тест, скорее всего, покажет достоверный результат. Так что можете смело проводить исследование, не боясь оказаться в заблуждении. Если после проведения теста все же возникают сомнения — точно определить наличие ХГЧ поможет анализ крови.

Надеемся, использование теста на беременность принесет вам только положительные новости. Будьте здоровы!

Как правильно делать тест на беременность

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

Как работает тест на беременность

Механизм работы всех домашних экспресс-тестов на беременность основывается на обнаружении в женском организме высоких показателей ХГЧ (хорионического гонадотропина человека). Этот гормон начинает активно вырабатываться и поступать в кровь примерно через неделю после оплодотворения, удваиваясь каждые 2-3 дня. Через 10-12 дней после зачатия (в среднем, сколько точно – для всех индивидуально) можно делать тест на беременность в домашних условиях – ХГЧ уже определится в моче. То есть, сразу после полового акта делать тест на беременность нет смысла: надо дождаться, когда ХГЧ достигнет нужного уровня.

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

Виды тестов на беременность

В зависимости от устройства и особенностей проведения, выделяют такие виды тестов на беременность:

  • Тест-полоска – наиболее привычный, компактный и недорогой вариант теста на беременность, который легко сделать в домашних условиях. Полоска с нанесенным на нее веществом-реагентом погружается до нужной отметки в контейнер с мочой.
  • Струйный тест – одноразовое устройство, которое используется непосредственно во время мочеиспускания (емкость для сбора мочи не понадобится). Такой быстрый анализ можно сделать в любом месте, где есть туалет.
  • Планшетный (кассетный) – в корпусе таких устройств имеется специальное реагентное окошко, куда нужно нанести несколько капель мочи (пипетка входит в набор).
  • Цифровой – в корпусе теста есть окошко-дисплей, на котором после контакта реагента с мочой отображается результат диагностики – беременна или нет. А в некоторых устройствах даже указывается срок. Согласно инструкции, электронный тест на беременность можно делать уже за 5 дней до задержки (до того дня, когда ожидаются месячные).

Тесты на беременность также отличаются уровнем чувствительности – это числа от 10 до 30, указанные в инструкции или на упаковке. Они обозначают концентрацию ХГЧ в моче, на которую способно отреагировать устройство:

  • 10 мМе/л – наиболее чувствительные тесты, позволяют определить беременность еще до начала задержки месячных.
  • 25-30 мМе/л – тест-системы со стандартной чувствительностью. Точность повышается в зависимости от того, на какой день задержки делать тест. Хотя большинство изготовителей заявляют, что уже в первый день задержки менструации домашний тест с вероятностью 99% покажет достоверный результат, в идеале лучше выждать 5-7 дней, чтобы исключить ложноотрицательный ответ.

Все способы самостоятельной диагностики зачатия просты в применении и занимают минимум времени, не дольше 10 минут. Как правильно сделать любой из тестов на беременность – читайте в инструкции.

Когда лучше делать тест на беременность?

Как уже было сказано выше, большинство тестов, с помощью которых можно проверить беременность в домашних условиях, начинает работать с первого дня задержки месячных. В случае сверхчувствительных тестов – даже до того, как началась задержка. Если говорить о том, на каком сроке тест показывает беременность, когда ее можно определить с максимальной вероятностью, то после зачатия должно пройти 12-14 дней. В редких случаях тест на беременность может обнаружить ХГЧ в урине уже через 10 дней после полового акта, до задержки. Но эти результаты не слишком надежны: ответ может быть ложноположительным или ложноотрицательным.

На какой день задержки делать тест, если цикл не регулярный?

Если у женщины нерегулярный цикл менструации, склонный к задержкам – сложно сказать точно, когда лучше делать тест на беременность. В этом случае сделать тест можно не дожидаясь задержки:

  • По прошествии 20-25 дней после полового акта без средств контрацепции.
  • При наличии непривычных ощущений: набухание, болезненность молочных желез (сильнее, не так как обычно перед месячными), тошнит, кружится голова, изменилось восприятие вкусов, запахов и тому подобное.
  • Если менструация не наступает дольше, чем это типично для женщины, даже учитывая склонность к задержкам.

Когда делать тест на беременность – утром или вечером?

Точность диагностики также зависит от того, когда, в какое время суток делать тест на беременность – утром или вечером. Больше шансов не ошибиться с результатом – сделать анализ утром: в это время показатели ХГЧ в моче максимальны. Это особенно имеет значение, если задержка еще не наступила или месячные задерживаются на 1-2 дня.

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

Как правильно делать тест на беременность?

Хотите сделать тест на беременность правильно и с максимальной точностью – перед тем как пользоваться, внимательно прочитайте инструкцию.

Как делать анализ на беременность с помощью теста полоски:

  • Соберите утреннюю мочу в контейнер.
  • Погрузите в емкость с уриной полоску реагентной стороной до отмеченного уровня.
  • Извлеките тест, положите горизонтально на чистую сухую поверхность, без адсорбентов, выждите 3-5 минут, пока пройдет нужная реакция.
  • Оцените результат: две полоски или одна, “+” или “-”, “yes” или “no” – что означает беременна или нет.

Как правильно делать тест на беременность струйного или цифрового типа:

  • Снимите с корпуса устройства пластиковый колпачок.
  • На 10 секунд поместите стержень с реагентом под струю урины.
  • Положите устройство на 3-5 минут в сухое, чистое место, подождите пока тест сработает.
  • Получите результат.

Что делать, чтобы тест показал максимально точный результат

Какой бы вы тест ни выбрали, воспользуйтесь такими советами:

  • Покупайте экспресс-тест только в аптечной сети – так можно рассчитывать, что были соблюдены правила его хранения.
  • Убедитесь, что у теста не истек срок годности. Чувствительные вещества по прошествии определенного времени теряют свои свойства.
  • Обращайте внимание на чувствительность экспресс-теста, в идеале выбирайте 10.
  • Диагностику лучше проводить утром.
  • Минимум за 1 час до того как делать тест на беременность, не употребляйте жидкость.
  • Соблюдайте время, в течение которого тест показывает адекватную информацию. Обычно это 3-5 минут, но не дольше 15 минут.
  • Не полагайтесь на домашний тест, если принимаете такие медикаменты: препараты против тревожности, для улучшения сна, антиконвульсанты, стимуляторы овуляции.
  • Также не стоит рассчитывать на точность результата теста, если вы не здоровы: болит низ живота, поясница, повышенная температура тела, кровь (заболевания мочеполовой сферы), белок в моче (показатель воспалительного процесса). При таких симптомах проконсультируйтесь у терапевта, уролога, гинеколога, чтобы исключить развитие серьезных патологий.
  • Купите 2 разных теста: если они показывают противоречивый результат – сдайте анализ на беременность в лаборатории.

Учитывайте также, что две полоски – повод как можно скорее посетить гинекологию. Высокие показатели ХГЧ могут свидетельствовать об эктопической (внематочной) беременности или о замирании плода, а также о серьезных заболеваниях яичников – эти и другие патологии необходимо исключить. Кроме осмотра у гинеколога понадобится дополнительная диагностика – УЗИ органов малого таза, анализ крови на ХГЧ. После подтверждения нормальной беременности для дальнейшего ее ведения необходимо встать на акушерский учет, оптимально – до 6-8 недель. Это важно, так как до 12-й недели происходит закладка и формирование основных органов и систем малыша. На развитие плода существенно влияют ошибки в диете, вредные привычки, хронические заболевания и инфекции, что может стать причиной врожденных аномалий, “замершей” беременности и выкидышу. Квалифицированный врач поможет вовремя принять меры и минимизировать риски для будущей мамы и ребенка.

Была ли полезной
для вас эта информация?

Как и зачем писать тесты

Как тесты помогают писать чистый новый код и увереннее редактировать старый.

Время чтения: 13 мин

Открыть/закрыть навигацию по статье

  1. Кратко
  2. Что такое тест
    1. Примитивное тестирование
    2. Инструменты для тестирования во фронтенде
    1. Подготовка (Arrange)
    2. Выполнение (Act)
    3. Проверка (Assert)
    4. Идеальный тест
    1. Заставляют думать над крайними случаями
    2. Уменьшают количество регрессий
    3. Дают больше уверенности при рефакторинге
    4. Решают проблемы при обновлении зависимостей
    5. Автоматическая документация
    1. Нужно больше времени на начальных этапах
    2. Нужно продумать структуру для тестов и тестовых данных
    3. Нужно настроить CI
    1. Unit тесты
    2. Интеграционные тесты
    3. E2E тесты
    4. Приёмочные тесты

    Обновлено 26 апреля 2024

    Кратко

    Скопировать ссылку «Кратко» Скопировано

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

    Тесты делают код более прочным и живучим. Одновременно с этим тесты — это отличная документация, которая не врёт и не устаревает. Также тесты можно использовать как инструмент разработки программы.

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

    Что такое тест

    Скопировать ссылку «Что такое тест» Скопировано

    Тест — это код, который проверяет предположения о работе другого кода.

    Представим, что у нас есть функция add ( ) , которая складывает одно число с другим:

     function add(a, b)  return a + b> function add(a, b)  return a + b >      

    Мы предполагаем, что функция прибавляет аргумент b к аргументу a и возвращает нам результат. Мы можем проверить это, вызвав её:

     const result = add(10, 5)// result === 15 const result = add(10, 5) // result === 15      

    Но что будет, если мы передадим не два числа, а одно? А если передадим не числа? Или функция за время жизни проекта изменится? Чтобы проверить такие предположения, мы пишем тесты.

    Примитивное тестирование

    Скопировать ссылку «Примитивное тестирование» Скопировано

    Самый простой тест, который мы можем написать — ручной. Сравним руками результат работы функции и ожидаемое значение:

     function testAdd()  const result = add(10, 5) const expected = 15 console.assert( result === expected, `The result $ doesn't match the expected value $.` )> function testAdd()  const result = add(10, 5) const expected = 15 console.assert( result === expected, `The result $result> doesn't match the expected value $expected>.` ) >      

    При запуске функции test Add ( ) она проверит, что вернёт функция add ( ) . Если результат не будет соответствовать ожиданию, консоль покажет ошибку.

    Конечно, такой тест никуда не годится ��

    • Ему сильно не хватает описания – как понять, что именно мы проверяем?
    • Не хватает выразительности и лаконичности — сравнивать значения и выбрасывать ошибки руками не круто.
    • Не хватает интерактивности — чтобы перезапустить тест, нужно запустить функцию заново.

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

    Инструменты для тестирования во фронтенде

    Скопировать ссылку «Инструменты для тестирования во фронтенде» Скопировано

    Инструментов для тестирования много. Чтобы подобрать подходящий, нам надо определиться, какие тесты мы хотим писать. Подробнее о видах тестирования мы поговорим в конце статьи, а пока что посмотрим на самый часто используемый инструмент — Jest.

    Чтобы использовать Jest, его нужно установить в свой проект через npm . Подробнее об установке можно узнать на сайте с документацией Jest.

    Попробуем, используя его, переписать тест нашей функции add ( ) :

     describe('When given 2 numbers', () =>  it('returns the sum of those 2 numbers', () =>  const result = add(10, 5) const expected = 15 expect(result).toEqual(expected) >)>) describe('When given 2 numbers', () =>  it('returns the sum of those 2 numbers', () =>  const result = add(10, 5) const expected = 15 expect(result).toEqual(expected) >) >)      

    Разберём по строкам:

    1. На первой строке мы указываем описание теста — в каких условиях мы собираемся тестировать функцию.
    2. На второй строке указываем само предположение о результате — что функция должна нам вернуть.
    3. На строчках 3–6 выполняем сам тест.

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

    Обвязка из describe ( ) и it ( ) помогает нам описать тест в виде самого настоящего текстового предположения, которое код теста проверит.

    Теперь разберём, собственно, код теста.

    Анатомия теста

    Скопировать ссылку «Анатомия теста» Скопировано

    Наш тест состоит из 3 строк:

     const result = add(10, 5)const expected = 15expect(result).toEqual(expected) const result = add(10, 5) const expected = 15 expect(result).toEqual(expected)      

    Его можно разделить на 3 стадии, которые можно запомнить по мнемоникам:

    • ПВП: Подготовка, Выполнение, Проверка;
    • или по-английски AAA: Arrange, Act и Assert.

    Подготовка (Arrange)

    Скопировать ссылку «Подготовка (Arrange)» Скопировано

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

    В нашем случае подготовкой можно назвать выбор аргументов 10 и 5 , а также обозначение ожидаемого значения const expected = 15 .

    Выполнение (Act)

    Скопировать ссылку «Выполнение (Act)» Скопировано

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

    В нашем случае это строчка с вызовом функции: const result = add ( 10 , 5 ) .

    Проверка (Assert)

    Скопировать ссылку «Проверка (Assert)» Скопировано

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

    В нашем случае проверка — это сравнение результатов на последней строке:

     expect(result).toEqual(expected); expect(result).toEqual(expected);      

    Идеальный тест

    Скопировать ссылку «Идеальный тест» Скопировано

    Идеальный тест состоит из всех трёх стадий ПВП. Часто — такой тест даже состоит из 3 строчек.

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

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

    Плюсы тестов

    Скопировать ссылку «Плюсы тестов» Скопировано

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

    Рассмотрим основные плюсы тестирования.

    Заставляют думать над крайними случаями

    Скопировать ссылку «Заставляют думать над крайними случаями» Скопировано

    Когда мы пишем программу, мы чаще думаем об основном сценарии работы (happy path), часто забывая о крайних случаях.

    Тесты смещают фокус с основного сценария на «что может пойти не так». Когда мы пишем тесты, мы больше склонны искать ошибки и неадекватную работу функции. Чем больше крайних случаев мы обработаем, тем надёжнее будет код.

    Уменьшают количество регрессий

    Скопировать ссылку «Уменьшают количество регрессий» Скопировано

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

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

    Тесты закрывают такие ошибки, потому что падают при возникновении неучтённой ситуации и не дают ей отправиться в продакшен.

    Дают больше уверенности при рефакторинге

    Скопировать ссылку «Дают больше уверенности при рефакторинге» Скопировано

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

    Даже если мы уверены, что полностью знаем кусок, который рефакторим, мы не застрахованы от более простых ошибок:

     // 1.let a = 15;if (a == 20) <> // 2.let a = 15;if (a = 20) <> // 1. let a = 15; if (a == 20) > // 2. let a = 15; if (a = 20) >      

    Второй случай в примере выше всегда будет истинным, потому что в условии вместо сравнения — присваивание. Тесты уберегут от подобных ошибок.

    Решают проблемы при обновлении зависимостей

    Скопировать ссылку «Решают проблемы при обновлении зависимостей» Скопировано

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

    Автоматическая документация

    Скопировать ссылку «Автоматическая документация» Скопировано

    Тесты не врут ��
    Они действительно показывают, как работает система.

    Дополнительная документация может устареть, особенно часто это случается с комментариями. Если документация устарела, у нас появляется два источника правды: документация и код. Это плохо, потому что непонятно, чему верить, и как программа должна работать. Тесты же точно говорят, как программа работать должна и работает ли.

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

    Издержки тестирования

    Скопировать ссылку «Издержки тестирования» Скопировано

    Тестирование не бесплатное, за надёжность кода приходится платить.

    Нужно больше времени на начальных этапах

    Скопировать ссылку «Нужно больше времени на начальных этапах» Скопировано

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

    Это, конечно, не так. Чем проект старше, тем больше мы получаем выгоды от написанных тестов.

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

    Нужно продумать структуру для тестов и тестовых данных

    Скопировать ссылку «Нужно продумать структуру для тестов и тестовых данных» Скопировано

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

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

    Чтобы не запутаться во всех фиктивных объектах и данных, для них нужно организовать структуру. Чем удобнее структура, тем проще писать тесты.

    Грамотно организовать систему с фиктивными объектами сложно. Это требует навыков проектирования, знаний о хорошей архитектуре и опыта.

    Нужно настроить CI

    Скопировать ссылку «Нужно настроить CI» Скопировано

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

    Настройка таких задач — это тоже дополнительная работа.

    Виды тестов

    Скопировать ссылку «Виды тестов» Скопировано

    Хорошо, вот мы взвесили все преимущества и недостатки тестирования. Если мы хотим внедрить тестирование в своём проекте, то какие тесты нам писать?

    Тесты бывают разных видов и проверяют они тоже разные вещи. Рассмотрим основные типы тестов в виде пирамиды и поговорим о каждом.

    Пирамида тестирования: в основании Unit-тесты, чуть выше интеграционные, на вершине — End-to-End

    Пирамида тестирования: в основании Unit-тесты, чуть выше интеграционные, на вершине — End-to-End.

    Unit тесты

    Скопировать ссылку «Unit тесты» Скопировано

    В основании пирамиды лежат юнит-тесты. Их ещё называют модульными тестами или блочными тестами.

    Такие тесты проверяют работу конкретного модуля, функции или части программы. Когда мы писали тест для функции add выше, мы писали именно юнит-тест.

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

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

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

    Интеграционные тесты

    Скопировать ссылку «Интеграционные тесты» Скопировано

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

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

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

    Интеграционными тестами проверяют связующие модули (так называемое middleware):

    • юнит-тесты проверяют прямое назначение middleware в целом;
    • интеграционные — как middleware взаимодействует с конкретными модулями.

    E2E тесты

    Скопировать ссылку «E2E тесты» Скопировано

    Они же End-to-End тесты, они же системные тесты — это проверка работы программы в целом.

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

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

    Одними из самых популярных и удобных фреймворков для E2E тестирования можно назвать Webdriver.IO и Cypress. В качестве примера тестирования с Cypress можем привести тестирование приложения для учёта расходов.

    Приёмочные тесты

    Скопировать ссылку «Приёмочные тесты» Скопировано

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

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

    Писать или не писать

    Скопировать ссылку «Писать или не писать» Скопировано

    Даже при наличии издержек тестирование экономит силы, время и деньги в долгосрочной перспективе. Отказаться от тестирования можно, если:

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

    В остальных случаях тесты лучше писать с самого начала.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *