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

Все о модульном тестировании Изучение

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

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

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

Обзор модульного тестирования

Что такое модульное тестирование?

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

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

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

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

Читайте также:  Расширение команды или Выделенная команда разработчиков

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

  • Модульное тестирование проверяет каждый программный модуль.
  • Интеграционное тестирование проверяет объединенные модули в соответствии с проектной документацией системы и функциональными требованиями.
  • Функциональное тестирование проверяет желаемую функциональность программы на основе документов анализа требований и руководства пользователя (т. е. обеспечение ожидаемого результата для заданных входных данных). Это иногда делится на системное тестирование и приемочное тестирование.

Тестирование «черного ящика» и «белого ящика» — это два подхода к тестированию программного обеспечения, в которых:

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

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

Преимущества модульного тестирования

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

  • Упрощает отладку : тестируя функциональность небольших модулей, вы можете обнаруживать ошибки до того, как они повлияют на другие модули в интегрированном приложении.
  • Поощряет более слабосвязанный код : намеренно уменьшая взаимозависимости между модулями, мы получаем более слабосвязанный код, что является передовой практикой кодирования.
  • Быстрее, чем функциональное тестирование : поскольку модули очень маленькие, вы можете запустить несколько модульных тестов за секунды (при условии, что вы их автоматизировали).
  • Минимизация регрессии кода : после рефакторинга или расширения кода вы можете повторно запустить все наборы тестов, чтобы убедиться, что ваш новый или обновленный код не нарушает существующие функции.
  • Лучшее покрытие кода. Разбивая приложение на мельчайшие тестируемые компоненты, модульное тестирование помогает увеличить покрытие кода.

Тестовое покрытие

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

Тестовое покрытие можно дополнительно классифицировать следующим образом:

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

Среды модульного тестирования

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

Существуют десятки фреймворков для модульного тестирования, доступных для различных языков программирования. Некоторые популярные среды модульного тестирования включают Cunit, Moq, Cucumber, Selenium, Embunit, Sass True, HtmlUnit и JUnit (одна из наиболее широко используемых сред с открытым исходным кодом для языка программирования Java).

Мы можем сэкономить много времени и ресурсов с помощью фреймворков модульного тестирования, которые включают следующие функции:

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

9 лучших практик модульного тестирования

1. Напишите тесты для ряда сценариев

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

2. Напишите хорошие названия тестов

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

3. Настройте автоматические тесты

Выберите автоматизированное модульное тестирование с помощью среды модульного тестирования. Еще лучше автоматизировать тесты в конвейере непрерывной интеграции (CI/CD).

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

4. Пишите детерминированные тесты

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

5. Организовать, действовать и утверждать (ААА)

Протокол AAA является рекомендуемым подходом для структурирования модульных тестов. В качестве передовой практики модульного тестирования это улучшает читабельность вашего теста, придавая ему логическую последовательность. ААА иногда называют протоколом «Дано/Когда/Тогда».

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

  • Упорядочить: Упорядочить настройку и инициализацию для теста.
  • Act: Действуйте на единицу для данного теста.
  • Утвердить: Утвердить или проверить результат

Следующий код демонстрирует структуру AAA при тестировании функции абсолютного значения в Python:

def test_abs_for_a_negative_number():
 
  # Arrange
  negative = -2
   
  # Act
  answer = abs(negative)
   
  # Assert
  assert answer == 2

6. Пишите тесты до или во время разработки

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

Процесс TDD выглядит следующим образом:

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

Следующий рисунок иллюстрирует этот процесс:

Цикл разработки через тестирование

Цикл разработки через тестирование

7. Один вариант использования на модульный тест

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

8. Избегайте логики в тестах

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

9. Сокращение тестовых зависимостей

Тесты не должны зависеть друг от друга. Уменьшая зависимости между модулями, исполнители тестов могут одновременно запускать тесты для разных фрагментов кода. Модуль может считаться пригодным для тестирования только в том случае, если его зависимости размещены (т. е. заглушки) в тестовом коде. Никакие реальные или внешние зависимости не должны влиять на результат теста.

10. Стремитесь к максимальному охвату тестами

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

11. Храните надлежащую тестовую документацию

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

Тестовая документация должна соответствовать следующим критериям:

  • Рецензируемый: тест любого данного ресурса может быть рецензирован другими.
  • Повторяемость: тест документируется таким образом, что его можно повторять несколько раз. Это позволяет нам убедиться, что ошибка исправлена ​​в обновленном фрагменте кода, повторив тот же тест.
  • Возможность архивирования: тесты и связанные с ними ошибки могут быть заархивированы в документации, которая служит ценным ресурсом для будущих расширений проекта.
Оцените статью
bestprogrammer.ru
Добавить комментарий