Нестабильные(Flaky) тесты — одна из основных проблем автоматизированного тестирования

Автор оригинала: George Pirocanac
  • Перевод

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

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

Данная статья призвана рассказать как бороться с каждой из причин.

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

  • Сами тесты;

  • Фреймворк для запуска тестов;

  • Сервисы и библиотеки, от которых зависит тестируемая система и тестовый фреймворк;

  • Операционная система и устройство с которым взаимодействует фреймворк автотестирования.

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

Однако в распределенной системе каждая служба приложения и службы, от которых она зависит, могут находиться в другом аппаратном / программном стеке, как и служба, выполняющая тест. Это проиллюстрировано на рисунке 2 как полная среда выполнения теста

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

Сами тесты

Сами тесты могут вызвать нестабильность. Типичные причины:

  • Неправильная инциализация или очистка;

  • Неправильно подобранные тестовые данные;

  • Неправильное предположение о состоянии системы. Примером может служить системное время;

  • Зависимость от асинхроных действий;

  • Зависимость от порядка запуска тестов.

Фреймворк для запуска тестов

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

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

  • Неправильное планирование тестов, поэтому они "противоречат" и приводят к сбою друг друга;

  • Недостаточно системных ресурсов для выполнения требований тестирования.

Сервисы и библиотеки, от которых зависит тестируемая система и тестовый фреймворк

Приложение (или тестируемая система) может быть источником нестабильности

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

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

Типичные причины:

  • Состояние гонки;

  • Непроинициализированные переменные;

  • Медленный ответ или отсутствие ответа при запросе от теста;

  • Утечки памяти;

  • Избыточная подписка на ресурсы;

  • Изменения в приложении и в тестах происходят с разной скоростью.

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

Герметичная среда менее подвержена нестабильности.

Операционная система и устройство с которым взаимодействует фреймворк автотестирования

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

  • Сбои или нестабильность сети;

  • Дисковые ошибки;

  • Ресурсы, потребляемые другими задачами / службами, не связанными с выполняемыми тестами.

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

В следующих статьях мы рассмотрим способы решения этих проблем.

Ссылки на источники

Vivid Money
Компания

Комментарии 5

    0

    Во время работы в разных компаниях у нас всегда возникала проблема с прекондишнами для UI тестов и всегда это было основной причиной "нестабильности". Если мы возьмем банальный пример, — у нас есть кнопка, после нажатия на которую фон становится зеленым. То есть, тест состоит из того, что заходит на страницу, кликает на кнопку и проверяет фон. Но проблема в том, к примеру, что чтобы нажать на кнопку, ее нужно активировать в админке. Заходим в админку, находим тогл, активируем, выходим (тратим на это минуту), заходим в систему, кликаем на кнопку, проверяем фон (тратим на это 20 секунд). Получается, что больше времени мы тратим на прекондишн для теста, чем на сам тест, а тестирование самого этого прекондишна является, как бы, сказкой другой ночи и проверяется в другом тесте… Пробовали использовать 2 варианта. 1й это заранее мануально приготовленные фикстуры, дампы БД с нужными настройками, которые накатываются перед выполнением теста, но, по-хорошему, для каждого теста нужен отдельный дамп, а поддерживать и обновлять их это ад. Вторым вариантом был вызов метода, который был написан заранее и который отправлял API запрос и сетил все нужные нам прекондишны на уровне API… Вопрос: как вы решаете подобные задачи на своих проектах? Спасибо

      0
      Мы используем разные подходы:
      Вариант 1 — Моки. Мы используем мок сервер для того чтобы тесты проходили стабильно и можно было получить нужное состояния для тестового сценария благодаря мокам.
      Вариант 2 — Api запрос. Мы конфигурируем нужные нам предусловия, дергая метод перед прогоном тестов.
        0

        К ответу выше, я бы еще добавил:


        1. Эмулятор, я общался с разными командами с разных компаний, очень многие используют эмулятор- т.е. напрямую дергают код;
        2. SQL запросы. Дампы БД — путь в никуда, при росте БД, вы будете увеличивать время прогона теста. С таким подходом нельзя параллельно исполнять тесты;
        3. Через взаимодействие с шиной событий приложения.
          0

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

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

          Эмулятор - вот тут поясните, что вы имеете ввиду, т.к. не очень понятно.

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

            0

            Шина довольно проблемное место, т.к. является асинхронщиной по-умолчанию.


            Интересное замечание. Вы же понимаете, что шина сейчас основной метод коммуникации внутри систем, которые должны быть доступны 24/7. Она априори не может являться проблемным местом. В одном из проектов компании все "Contract Test" реализованы через шину событий. В этом проекте планируется автоматическая доставка релизов, соответственно нестабильных тестов там быть не может.

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

            Если на проекте актуальный frontend framework и команда разработки имеет опыт работы с ним и умеет правильно управлять state-ом приложения - головной боли не будет.

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

            Да, Plain SQL запросов в коде автотестов должно быть минимум. Вся логика уезжает в stored procedures и накатывается миграциями. Мы в проектах стараемся объединять миграции интеграционных тестов и e2e в отдельный контекст, они всегда в актуальном состоянии, иначе интеграционные тесты не проходят, это блокирует исполнение e2e. Если нет желания бороться с stored procedures, можно попробовать code-first подход по взаимодействию с БД.

            Эмулятор - вот тут поясните, что вы имеете ввиду, т.к. не очень понятно.

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

            Вообще, самый надёжный способ все же использовать API.

            У меня есть задача, чтобы можно было параллельно исполнять тесты, мне надо клонировать сущности, при формировании которых участвует 30+ таблиц, с небольшими изменениями(имя заменить плюс еще пару параметров). Данные шаги вызываются в 3000 сценариях. Через UI их выполнять примерно 4.5 минуты. Через существующие методы API ~3 минуты. Через Stored Procedure 15 секунд. Когда стоит задача быстрой верификации качества, нужны шаги по взаимодействию с базой.

            P.S. я не выделяю ни один из подходов. когда я последний раз писал систему для e2e тестов, были реализованы все подходы, кроме шины событий. Это был монолит, а для него данный подход неактуален.

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

      Самое читаемое