Разновидности юнит тестов (unit testing). Основательный подход.

Я тестирую на продакшене

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

Разновидности тестирования

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

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

Основные виды тестирования:

1. Модульное и интеграционное тестирование

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

2. Системное тестирование

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

3. Регрессионное тестирование

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

4. Функциональное тестирование

В этом случае разработчиком проверяются отдельные части системы на требования, описываемые в user историях, спецификациях и других документациях. Основные уровни функционального тестирования делят тесты на “white” и “black box”, которые создаются исходя из реализации программного кода.

5. Тестирование производительности

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

6. Нагрузочное тестирование

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

7. Стресс-тестирование

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

8. Локализационное тестирование

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

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

Пирамида автоматизации тестирования

Прирамида автоматизированного тестирования

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

Практичная и многофункциональная пирамида тестирования состоит из следующих компонентов:

  1. Unit. Используемые модульные тесты, которые применяются в различных слоях программного обеспечения. С их помощью разработчик может быстро протестировать логику приложения с использованием классов или методов. Во избежание различных искажений, unit тесты обычно изолируются от внешних процессов. Это также позволяет добиться того, что отдельно взятый юнит функционирует в правильном режиме.
  2. Integration. Интеграционные тесты проверяют крупные разделы программного обеспечения в виде нескольких классов или модулей. Также с их помощью можно быстро корректировать функционал внешних компонентов программы. В процессе анализа, автоматизированные тесты компилируют код в готовые приложение и проводят тщательный мониторинг основного функционала. Отличительной особенностью данного вида тестирования является возможность быстрого обнаружения системных ошибок после внесения дополнительных изменений в программу.
  3. Тестирование UI — это определенные программные тесты, с помощью которых анализируется функциональность и работоспособность пользовательского интерфейса приложения.

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

Основные понятия Unit тестирования (Java контекст)

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

Одним из наиболее важных понятий является покрытие тестов — основная оценка качества проведенного тестирования. Определяется процентным соотношением программного кода, проанализированного тестами. Чтобы оценить непосредственно покрытие тестов, разработчики внедряют дополнительный инструментарий: Clover, JaCoCo, Cobertura и многие другие инструменты.

Не менее важные определения, характерные для юнит тестирования:

  1. TDD или Test Drived Develoopment. Представляет собой разработку программного кода одновременно с тестированием необходимых процессов. С помощью данного метода, разработчик сначала создает тесты, под которые будет написано программное обеспечение. Подобный технологический процесс позволяет выявлять ошибки еще до написание основного кода. Основной задачей TDD является упрощение кода и быстрое выявление ошибок. После того, как тест был создан, программист запускает его в программной среде с последующим выполнением рефакторинга основного кода до того момента пока тест не начнет выполняться. Используя данный метод, можно эффективно строить сложные системы с максимальным покрытием тестами.
  2. BDD или Behavior Driven development. Интеграционный тест, который разрабатывается через поведение всей системы или ее отдельных частей в зависимости от условий. Технический метод в большей степени используется тестеровщиками и бизнес аналитиками.
  3. Тестовый сценарий. Определенные сценарии автоматизированного или ручного (manual) типа, в которых содержатся конкретные инструкции определенных кейсов для тестовой программы: условия, шаги выполнения, ограничения и т.д.

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

Этапы юнит тестирования (Java)

Юнит тесты в Java состоят из 3 отдельных этапов: определение задач тестируемых данных, применение тестируемого кода или с вызовом анализируемых методов, а также анализ полученных результатов с их последующей сверкой с предполагаемыми.

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

  1. Моки или Mocks. Определенные объекты с ожиданиями, задающие заранее заготовленные данные, которые разработчик может настроить.
  2. Заглушки или Stub. Программное обеспечение, позволяющее использовать заранее зашитый ответ в код, который вызывается определенными элементами тестирования.
  3. Шпионы или Spy. От заглушек отличаются возможностью сохранять полученную информацию от вызова: число, параметры, надстройки и т.п.

Некоторые разработчики достаточно часто путают термины mock и stubs. Здесь следует понять, что основная разница между двумя определениями — это отсутствие проверки в заглушках, которые лишь выполняют функцию имитации данных. Зачастую тестирование может сломаться из-за мока, но не за заглушки.

Основные среды тестирования (Java)

Перед тем, как писать тесты разработчику необходимо узнать о том, какие фреймворки или среды тестирования существуют в Java. Наиболее популярными из них являются TestNG и JUnit.

Юнит тесты с JUnit — это определенный программный модуль, который применяется исключительно для юнит (определенных модулей) тестирования. Обычно классы юнит тестов именуется таким же образом, как и анализируемый класс с обозначением «Test» в конце названия.

Базовые аннотации среды тестирования (jUnit):

  • @Test. Позволяет обозначить используемый метод в качестве метода тестирования.
  • @Before. Отмечает программный метод для выполнения перед каждым прогоном тестов: чтение данных, заполнение тестовой информации и т.п.
  • @After. Выполняется каждый раз после прогона тестов, в данном случае может быть проведена: чистка данных используемых в тестах, восстановление первичных значений переменных.
  • @BeforeClass. Является аналогом аннотации @Before, однако вызывается в статистическом режиме и единственном числе. Применяется для обработки сложных вычислительных операций и настройки баз данных.
  • @AfterClass. Прямая противоположность аннотации @BeforeClass. Исполняется лишь однажды для определенного класса, после тестирования. Применяется для отключения метода от базы данных и при очистке неизменных ресурсов.
  • @Ignore. Данным значением разработчик указывает метод, который будет игнорироваться в случае общего тестирования. Есть возможность добавления такого показателя, как “Some description”.
  • @Mock. Применяется в классах с библиотекой Mockito для представления класса в виде мока. При необходимости, поведение Mock задается в конкретном методе.
  • @RunWith. Проставляется над определенным классом. Всегда является анотацией, с помощью которой тест прогоняется в исследуемом классе. В качестве Runner-ов могут использоваться различные классы, SpringRunner и другие.
  • @Test(timeout=x). Значение X — это числовой показатель времени за который тест должен выполниться, не более.

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

  • assertEquals(Object expecteds/actuals). Проверка равности исследуемых объектов и массивов.
  • assertTrue(boolean flag). Тест проверяет true в качестве переданного значения.
  • assertFalse(boolean flag). Также проверка возвращения false в качестве переданного значения.
  • assertNull(Object object). Анализ объекта в качестве null.
  • assertSame(Object firstObject/secondObject). Многофункциональная форма для сравнения значений, которые ссылаются на один и тот же объект.

Вышеперечисленные методы являются базовыми.

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

Related posts

Leave a Comment