Разделы портала

Онлайн-тренинги

.
Одновременное использование нескольких тест-фреймворков
21.04.2021 00:00

Автор: Энди Найт (Andy Knight)
Оригинал статьи
Перевод: Ольга Алифанова

Недавно мне задали вот такой вопрос (я его перефразировал для ясности):

Хорошая ли практика – одновременно использовать несколько тест-фреймворков? К примеру, я работаю над Python-проектом. Я хочу применять BDD c behave для фича-тестирования, но pytest лучше подойдет для юнит-тестирования. Можно ли использовать и то, и другое? Если можно, как мне структурировать мой проект?

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

Неприличное слово

Я терпеть не могу неприличное слово "фреймворк". Среди автоматизаторов люди употребляют это слово по отношению к разным вещам. "Фреймворк" – это только тест-пакет вроде pytest или JUnit? Включает ли он сами тесты? Имеются ли в виду инструменты автоматизации вроде Selenium WebDriver?

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

В исходном вопросе использовался термин "фреймворк", но я думаю, что отвечать на него надо в терминах решений. Тут есть два потенциальных решения – одно для юнит-тестов на pytest, а другое для фича-тестов на behave.

Нет универсального способа

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

К примеру, behave – это BDD фреймворк для Python. Разработчики пишут тест-кейсы на языке Gherkin с Python-функциями в качестве определений шагов. Тест-кейсы Gherkin интуитивно читабельны и понятны, и поэтому отлично подходят для тестирования высокоуровневых поведений вроде взаимодействий с веб-страницами. Однако BDD-фреймворки добавляют сложности, препятствующие разработке юнит-тестов. Юнит-тесты по природе своей близки к коду и находятся на низком уровне, потому что напрямую вызывают продуктовый код. Фреймворк pytest лучше подойдет для юнит-тестирования. И наоборот – фича-тесты можно писать на голом pytest, но behave дает более естественную структуру для описания фич. Следовательно, идеальным вариантом будет использование раздельных решений для разных типов тестов.

Один репозиторий или разные?

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

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

Фича-тесты можно размещать как там же, так и в отдельном репозитории. Я рекомендую помещать их вместе с кодом продукта, если они написаны на том же языке и если весь тестируемый код продукта находится в этом же репозитории. В этом случае контроль версий тестов осуществляется вместе с тестируемым продуктом. В противном случае рекомендую хранить фича-тесты в отдельном репозитории. Репозитории на разных языках сложно поддерживать, и контроль версий для продуктов с несколькими репозиториями должен осуществляться иначе.

Структура универсального репозитория

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

Ниже – способы обращения с несколькими тест-решениями на разных языках:

  • Структура проекта на Python довольно гибкая штука. Конвенционально все тесты принадлежат к верхнеуровневой директории "tests". В нее можно добавлять поддиректории – например, "unit" и "feature". Фреймворки вроде pytest и behave могут принимать поисковые пути для запуска нужных тестов. Более того, если использовать pytest-bdd вместо behave, то для фильтрации тестов pytest может использовать маркировки и тэги вместо путей поиска.
  • На языках NET (вроде C#) термины "проект" и "решение" имеют специфические значения. Проект .NET – это коллекция кода, встроенного в один артефакт. .NET-решение – это коллекция взаимосвязанных проектов. Как правило, хорошая практика в .NET – это создание отдельного проекта для каждого типа/набора тестов внутри одного .NET-решения. Я лично настраивал .NET-решение, в котором были отдельные проекты для юнит-тестов NUnit и фича-тестов SpecFlow.
  • На Java структура продукта зависит от проектного инструмента автоматизации. Большинство Java-проектов используют Maven или Gradle. В стандартной структуре директорий Maven тесты находятся в "src/tests". Различные типы тестов можно помещать в отдельные пакеты. Может понадобиться дополнительная конфигурация POM для запуска тестов на разных стадиях билда.
  • В JavaScript размещение тестов сильно зависит от типа проекта. К примеру, Angular создает отдельные директории для юнит-тестов, использующих Jasmine, и end-to-end тестов, использующих Protractor, при инициализации нового проекта.

Выбирайте наилучшее решение

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

Обсудить в форуме