Вход |  Регистрация

Все Тэги

Тестирование с помощью VS 2012: Как писать хорошие модульные тесты

08.08.20131238 просм.

Мы продолжаем серию заметок о тестировании ПО на основе книги “Testing for Continuous Delivery with Visual Studio 2012″. В предыдущей заметке мы рассказывали об оптимальном цикле разработки и покрытии кода модульными тестами. В этой заметке рассмотрим как писать хорошие модульные тесты.

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

Подготовка – Действие – Проверка

Общему подходу {Подготовка; Действие; Проверка} отдают предпочтение многие разработчики:

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

Например:

 

Каждый тест должен осуществлять только одну проверку

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

Нужно всегда помнить, что тестовый фреймворк MSTest по умолчанию не гарантирует, что тесты будут выполняться в определенном порядке. Следовательно, нельзя переносить состояние из одного теста в другой. Однако в Visual Studio, можно использовать функцию Ordered Test, для выполнения тестов в определенной последовательности.

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

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

У каждого тестового класса могут быть методы TestInitialize и TestCleanup. (Это атрибуты MSTest; в других тестовых фреймворках есть эквиваленты, обычно называемые Setup and Teardown). Используйте методы инициализации или подготовки для выполнения общих задач, которые необходимы для настройки начальных условий для модульного теста. Например, создания объекта для тестирования, открытия соединений с базой данных или загрузки данных. Методы очистки или уничтожения вызываются всегда, даже если тестовый метод выполнился с ошибкой. Это полезный функционал, благодаря которому не надо писать весь свой тестовый код внутри блоков try…finally.

Тестируйте обработку исключений

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

Более надежный способ тестировать исключения показан ниже:

 

Функция наподобие AssertThrows встроена во многие тестовые фреймворки.

Не тестируйте только одно входное значение или состояние

Проверка 2.0==МойМетодНахожденияКвадратногоКорня(4.0), не покажет того, что функция работает правильно для всех значений. Инструменты покрытия кода могут показать, что проверен весь код, но все равно есть вероятность того, что другие входные данные, или другие начальные состояния, или другие последовательности входных данных, дадут неверный результат.

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

Ищите граничные случаи: такие, в которых есть особенные значения или особые отношения между значениями. Протестируйте эти граничные случаи и протестируйте репрезентативные значения между границами. Например, входные значения 0 и 1 могут считаться граничными для функции излечения квадратного корня, так как входные и выходные значения равны. Поэтому тестируйте, например, значения -10, -1, -0.5, 0, 0.5, 1, и 10.

Тестируйте во всем диапазоне. Если ваша функция должна работать для входных данных вплоть до 4096, попробуйте значения 4095 и 4097.
Подход тестирования от выбранной модели разделяет все пространство входных данных, состояний на границах полученных областей, и соответственно старается генерировать тестовые данные.
Для объектов более сложных, чем простые числовые функции, понадобится учитывать связи между разными состояниями и значениями: например, между списком и индексом в списке.

Отделяйте генерацию тестовых данных от проверки

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

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

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

  • Пост-условие непосредственно представляет текущие требования и может рассматриваться отдельно от вопросов, какие именно точки данных тестировать.
  • Пост-условие может принимать диапазон значений; не обязательно указывать единственный правильный ответ для каждого входного значения.
  • Генератор тестовых данных может меняться отдельно от пост-условия. Самым важным требованием к генератору данных является то, что он должен генерировать входные значения (или состояния) так, что они будут распределены вокруг граничных значений.

Генератор тестовых данных Pex

На закуску кратко упомянем Pex, дополнение для Visual Studio (существует и отдельная онлайн версия).

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

Метки: , ,

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

Для отправки комментария вам необходимо авторизоваться.

Партнеры DevOpsHub и DevOpsWiki