Антипаттерны Для Тестирования Программного Обеспечения

Введение Есть несколько статей об антипаттернах разработки программного обеспечения.

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

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

Я надеюсь, что вы изучите некоторые из них независимо от вашего языка программирования.

Терминология К сожалению, тестирование еще не выработало единой терминологии.

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

В этой статье мы ограничимся следующей пирамидой тестов:

Антипаттерны для тестирования программного обеспечения

Если вы не видели пирамиду тестов, очень рекомендую посмотреть.

Вот несколько хороших статей для начала:

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

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

Обратите внимание, что в этой статье Нет Упоминаются UI-тесты (верхушка пирамиды) — в основном для краткости и потому, что у них есть свои специфические антипаттерны.

Поэтому мы выделяем две основные категории тестов: модульный (юнит-тесты) и интеграция .

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

Эти тесты сопровождают исходный код и имеют к нему прямой доступ.

Обычно они выполняются с помощью платформа xUnit или подобная библиотека.

Модульные тесты работают непосредственно с исходным кодом и дают полную картину всего.

Тестируется один класс/метод/функция (или наименьшая рабочая единица для этой конкретной функциональности), а все остальное издевается/заменяется.

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

Это может быть набор классов/методов/функций, модуль, подсистема или даже само приложение.

Они тестируют компонент, передавая ему входные данные и проверяя выходные данные.

Обычно требуется какое-то предварительное развертывание или настройка.

Внешние системы можно полностью имитировать или заменять (например, использовать in-memory СУБД вместо реальной), при необходимости использовать реальные внешние зависимости.

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

Вторая категория страдает расплывчатым определением.

Именно здесь возникает больше всего споров по поводу названий.

«Объем» интеграционных тестов также достаточно спорен, особенно относительно характера доступа к приложению (тестирование в черный или белый коробка; допустимый макеты объектов или нет).

Основное практическое правило таково: если тест.

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

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

Их порядок примерно соответствует их распространенности.

Наиболее распространенные проблемы перечислены в начале.

Список антипаттернов тестирования программного обеспечения

  1. Модульные тесты без интеграционных тестов
  2. Интеграционные тесты без модульных тестов
  3. Неправильный тип теста
  4. Тестирование неправильной функциональности
  5. Тестирование внутренней реализации
  6. Чрезмерный акцент на тестовом покрытии
  7. Ненадежные или медленные тесты
  8. Запуск тестов вручную
  9. Недостаточное внимание к тестовому коду
  10. Отказ от написания тестов на новые ошибки с производства
  11. Отношение к TDD как к религии
  12. Написание тестов без предварительного чтения документации
  13. Плохое отношение к тестированию из-за незнания
Антипаттерн 1. Юнит-тесты без интеграционных тестов Это классическая проблема для малых и средних компаний.

Для приложения создаются только юнит-тесты (основа пирамиды) — и ничего больше.

Обычно отсутствие интеграционных тестов вызвано одной из следующих проблем:

  1. В компании нет старших разработчиков.

    Есть только юниоры, которые только что закончили колледж.

    Они сталкивались только с модульными тестами.

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

    Юнит-тесты гораздо проще поддерживать, поэтому мы оставили только их.

  3. Среда приложения слишком сложна для настройки.

    Функции «проверяются» в производстве.

По первому пункту ничего сказать не могу.

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

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

5 , 7 И 8 .

Это подводит нас к последнему вопросу — сложной настройке тестовой среды.

Не поймите меня неправильно, некоторые приложения Действительно сложно протестировать.

Однажды мне пришлось работать с набором REST-приложений, для которых требовалось специальное оборудование на хосте.

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

Но это крайний случай.

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

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

По сути, если вы пытаетесь протестировать приложение, которое сложно настроить, вам нужно сначала исправить процесс установки, прежде чем приступать к самим тестам.

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

Канонический пример — все, что связано с операциями СУБД.

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

Любые тесты производительности по определению являются интеграционными тестами.

Вот краткий обзор того, зачем нам нужны интеграционные тесты:

Тип проблемы Определяется модульными тестами Определяется интеграционными тестами
Основная бизнес-логика Да Да
Проблемы интеграции компонентов Нет Да
Транзакции Нет Да
Триггеры/процедуры базы данных Нет Да
Неправильные контракты с другими модулями/API Нет Да
Неправильные контракты с другими системами Нет Да
Производительность/таймауты Нет Да
Взаимные/самосъемные замки Может быть Да
Проблемы перекрестной безопасности Нет Да
Обычно любая проблема, связанная с кросс-приложениями, требует интеграционных тестов.

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

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

Это можно решить только интеграционными тестами.

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

Антипаттерн 2. Интеграционные тесты без модульных тестов Это противоположность предыдущему антипаттерну.

Это чаще встречается в крупных компаниях и крупных корпоративных проектах.

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

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

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

ниже).

антипаттерн 6 ) и заставил их писать тривиальные модульные тесты.

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

Но на практике такое тестирование будет очень дорогим (как по времени разработки, так и по времени сборки).

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

Но жизнеспособна ли такая стратегия в долгосрочной перспективе?

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

Давайте посмотрим на пример.

Предположим, что у нас есть сервис с четырьмя такими методами/классами/функциями.



Антипаттерны для тестирования программного обеспечения

Об этом свидетельствует номер на каждом модуле.

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

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

Сколько тестов нужно написать, чтобы полностью охватить все возможные сценарии? Очевидно, что вы можете написать 2+5+3+2 = 12 изолированных модульных тестов, которые полностью покроют бизнес-логика эти модули.

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

Разработчик Джо «The Grumpy» не верит в ценность модульных тестов.

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

Сколько? Он начинает просматривать все возможные маршруты через все части сервиса.



Антипаттерны для тестирования программного обеспечения

Опять же, должно быть очевидно, что возможны 2*5*3*2 = 60 кодовых маршрутов.

Означает ли это, что Джо действительно напишет 60 интеграционных тестов? Конечно, нет! Он будет хитрить.

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

Это «репрезентативное» подмножество обеспечит достаточный охват с минимальными усилиями.

В теории все просто, но на практике быстро возникают проблемы.

На самом деле эти 60 сценариев созданы по-разному.

Некоторые из них являются пограничными случаями.

Например, через модуль C проходят три пути кода.

Один из них — особый случай.

Его можно воссоздать только в том случае, если C получает определенные входные данные от компонента B, что само по себе является крайним случаем и может быть получено только с помощью определенных входных данных от компонента A. Это означает, что этот конкретный сценарий может потребовать очень сложной настройки для выбора входных данных, которые вызовут особые условия для компонента C. С другой стороны, Мэри просто воссоздаст крайний случай с помощью простого модульного теста без каких-либо дополнительных сложностей.



Антипаттерны для тестирования программного обеспечения

Итак, Мэри напишет только модульные тесты? В конце концов это приведет ее к антипаттерн 1 .

Чтобы этого избежать, она будет писать как модульные, так и интеграционные тесты.

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

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

Интеграционные тесты должны быть сосредоточены на остальных компонентах.

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

Интеграционные тесты Мэри будут сосредоточены на сериализации/десериализации, взаимодействии с очередями и системной базе данных.



Антипаттерны для тестирования программного обеспечения

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



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

Вторая большая проблема интеграционных тестов — их скорость.

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

Они почти всегда ограничены загрузкой процессора.

С другой стороны, интеграционные тесты могут выполнять операции ввода-вывода на внешних системах, поэтому их гораздо сложнее оптимизировать.

Чтобы получить представление о разнице во времени, примите следующие цифры.

  • Каждый модульный тест занимает в среднем 60 мс.

  • Каждый интеграционный тест занимает в среднем 800 мс.

  • Как показано в предыдущем разделе, в приложении 40 сервисов.

  • Мэри пишет 10 модульных тестов и 2 интеграционных теста для каждого сервиса.

  • Джо пишет по 12 интеграционных тестов для каждого сервиса.

Теперь давайте посчитаем.

Обратите внимание, что Джо предположительно нашел идеальное подмножество интеграционных тестов, которые обеспечивают такое же покрытие кода, как Мэри (на самом деле это не так).

Время выполнения Иметь только интеграционные тесты (Джо) Наличие модульных и интеграционных тестов (Мэри)
Только модульные тесты Н/Д 24 секунды
Только интеграционные тесты 6,4 минуты 64 секунды
Все тесты 6,4 минуты 1,4 минуты
Разница в общем времени работы огромна.

Ожидание одной минуты после каждого изменения кода существенно отличается от ожидания полных шести минут. А предположение о 800 мс для каждого интеграционного теста чрезвычайно консервативно.

Я видел наборы интеграционных тестов, в которых выполнение одного теста занимает несколько минут. Подводя итог, пытаюсь использовать только Интеграционные тесты для проверки бизнес-логики — это огромная трата времени.

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



Интеграционные тесты сложнее отлаживать, чем модульные тесты.

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

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

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

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

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

Опять же, в качестве примера, предположим, что для вашего приложения проводятся только интеграционные тесты.

Допустим, это типичный интернет-магазин.

Ваш коллега (или вы) отправляет новый коммит, который запускает интеграционные тесты со следующим результатом:

Антипаттерны для тестирования программного обеспечения

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

В контексте приложения интернет-магазина это не очень хорошо.

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

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

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

среда.

Теперь представьте, что вы с Мэри работаете над этим приложением, поэтому у вас есть как интеграционные, так и модульные тесты.

Ваши коллеги отправляют коммиты, вы запускаете все тесты и получаете следующее:

Антипаттерны для тестирования программного обеспечения

Теперь два теста провалились:

  • «Клиент покупает продукт» не проходит как раньше (интеграционный тест).

  • «Специальный тест скидок» также не проходит (юнит-тест).

Теперь очень легко понять, где искать проблему.

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

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



Краткое изложение того, зачем нужны модульные тесты

Это был самый длинный раздел статьи, но я думаю, что он очень важен.

Подводя итог: хотя в теории Вы можете использовать только интеграционные тесты, на практике

  1. Юнит-тесты легче поддерживать.

  2. Модульные тесты легко воспроизводят крайние случаи и редкие ситуации.

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

  4. Плохие модульные тесты исправить легче, чем интеграционные тесты.

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

Нам нужны как модульные, так и интеграционные тесты одновременно.

Они не являются взаимоисключающими.

В Интернете есть несколько статей, в которых предлагается использовать только один тип теста.

Все эти статьи распространяют дезинформацию.

Это грустно, но это правда.

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

Нам нужно решить Сколько тесты необходимы в каждой категории.

Здесь нет жестких правил.

Все зависит от вашего приложения.

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

Ваш его Приложения.

Пирамида тестов — это всего лишь предположение о количестве тестов.

Предполагается, что вы пишете коммерческое веб-приложение, но это не всегда так.

Давайте посмотрим на несколько примеров:

Пример: Утилита командной строки Linux

Ваше приложение представляет собой утилиту командной строки.

Он принимает файлы в одном формате (например, CSV), выполняет некоторые преобразования и экспортирует в другой формат (например, JSON).

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

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

Что нужно для этого примера:

  • Множество модульных тестов для математических расчетов.

  • Некоторые интеграционные тесты для чтения CSV и записи JSON.
  • Никаких тестов графического интерфейса, потому что графического интерфейса нет.
Вот как выглядит «пирамида» тестов такого проекта:

Антипаттерны для тестирования программного обеспечения

Здесь доминируют модульные тесты, и полученный вид Нет представляет собой пирамиду.



Пример: Управление платежами

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

Приложение представляет собой платежный шлюз, обрабатывающий платежную информацию для внешней системы.

Это новое приложение должно регистрировать все транзакции во внешней базе данных, оно должно взаимодействовать с внешними поставщиками платежей (Paypal, Stripe, WorldPay и т. д.), а также отправлять данные о платежах в еще одну систему, которая выставляет счета.

Что нужно для этого примера:

  • Модульных тестов почти нет, потому что нет бизнес-логики.

  • Множество интеграционных тестов для внешних коммуникаций, хранения баз данных и систем выставления счетов.

  • Никаких тестов графического интерфейса, потому что графического интерфейса нет.
Вот как выглядит «пирамида» тестов такого проекта:

Антипаттерны для тестирования программного обеспечения

Здесь доминируют интеграционные тесты, и результирующий вид снова Нет представляет собой пирамиду.



Пример: конструктор сайтов

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

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

На рынке можно приобрести новые шаблоны.

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

  • Модульных тестов почти нет, потому что нет бизнес-логики.

  • Несколько интеграционных тестов для взаимодействия с рынком.

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

Вот как выглядит «пирамида» тестов такого проекта:

Антипаттерны для тестирования программного обеспечения

Здесь доминируют UI-тесты, и результирующая форма снова Нет представляет собой пирамиду.

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

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

В Интернете можно найти статьи (не буду на них ссылаться), в которых упоминается конкретное соотношение интеграционных тестов, модульных тестов и UI-тестов.

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

Следующий логический шаг — объяснить, какую именно функциональность необходимо протестировать.

Теоретически конечная цель — охватить 100% кода.

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

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

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

Но не всем разработчикам так повезло.

В большинстве случаев вы наследуете существующее приложение с минимальным тестированием (или без него).

Если вы работаете в крупной и авторитетной компании, то работа с устаревшим кодом — это скорее правило, чем исключение.

В идеале вам будет предоставлено достаточно времени для написания тестов как для нового, так и для существующего устаревшего кода приложения.

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

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

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

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

Покрытие кода подробно анализируется в отдельном разделе.

антипаттерн .

В этом разделе мы поговорим о «важности» кода и о том, как он связан с тестами.

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



Антипаттерны для тестирования программного обеспечения

Это физическая модель кода.

Он показывает папки в файловой системе, содержащие исходный код. Хотя эта иерархия отлично подходит для работы с самим кодом, к сожалению, она не показывает важности.

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

Это неверно, поскольку разные компоненты кода по-разному влияют на общую функциональность приложения.

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

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

  2. Клиенты получают неверные рекомендации при просмотре товаров.

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

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

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



Антипаттерны для тестирования программного обеспечения

Здесь показаны три слоя кода, но их может быть больше в зависимости от размера приложения.

Этот:

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

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

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

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

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

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

Если у вас есть эта информация, ответ очевиден: попробуйте написать тесты, покрывающие 100% критический код .

Если вы это уже сделали, то попробуйте написать тесты, покрывающие 100% основной код .

Однако Не рекомендуется постарайтесь покрыть тестами 100% всего кода.

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

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

В общем, пишите модульные и интеграционные тесты для кода, который:

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

Антипаттерн 5. Тестирование внутренней реализации Больше тестов всегда хорошо.

Верно? Неправильный! Вам также необходимо убедиться, что тесты на самом деле структурированы правильно.

Неправильно написанные тесты наносят двойной ущерб:

  • Во-первых, они тратят драгоценное время разработчиков во время написания.

  • Затем они тратят еще больше времени, когда им приходится их переделывать (при добавлении новой функции).

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

В какой-то момент потребуется рефакторинг для его постепенного улучшения.

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

Я видел, как компании запускают новые проекты, и думаю, что на этот раз они все сделают правильно — начинают писать.

много Теги: #тестовая пирамида #тестирование антипаттернов #юнит-тесты #интеграционные тесты #xunit #Микросервисы #цикломатическая сложность #покрытие кода #автоматическое тестирование #dry #kiss #solid #tdd #Тестирование ИТ-систем #tdd #отладка #Тестирование веб-сервисов #Управление разработкой

Вместе с данным постом часто просматривают: