Серия «Java, которую необходимо знать: среда тестирования и модульное тестирование»

Автор: Дзен и искусство компьютерного программирования

1. Введение

Что такое модульное тестирование? Зачем модульное тестирование? На какие аспекты следует обратить внимание при модульном тестировании? Каковы трудности и проблемы модульного тестирования? Если вы инженер или рабочий с большим опытом программирования, готовы ли вы прочитать эту статью с самого начала? Если вы уже обладаете соответствующими знаниями и полностью понимаете содержание этой статьи, приглашаем вас присоединиться к этой серии исследований, чтобы обсудить и изучить новейшие технологии в области «тестирования» для повышения конкурентоспособности вашего рабочего места!

1. Почему модульное тестирование?

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

Хороший модульный тест должен иметь следующие характеристики:

  1. Повторяемость: модульные тесты должны иметь возможность запускаться несколько раз и давать одни и те же результаты, гарантируя, что тестируемый код не зависит от внешних сред, таких как базы данных или сети;
  2. Тестируемость: модульное тестирование должно охватывать каждый модуль всей программной системы, а не тестировать функцию по отдельности;
  3. Автоматизация. Модульное тестирование должно выполняться автоматически с помощью сценариев или инструментов, что экономит время и энергию ручного труда и ускоряет тестирование;
  4. Быстрая обратная связь. Чем быстрее будут выполняться модульные тесты, тем легче будет получить обратную связь.

2. Принципы модульного тестирования

При написании модульных тестов следует следовать следующим принципам:

  1. Каждый класс имеет по крайней мере один метод тестирования;
  2. Именование метода тестирования должно начинаться с test_, например test_myFunc;
  3. Каждый метод тестирования должен проверять определенную комбинацию ввода-вывода;
  4. Пишите модульные тесты, используя подход разработки через тестирование (TDD).

3. Цели и процесс модульного тестирования

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

  1. Настройте тестовую среду: подготовьте тестовые данные, настройте операционную среду и внедрите различные ресурсы, необходимые для тестирования, обычно включая соединения с базой данных, веб-серверы, очереди сообщений и т. д.;
  2. Выполните тестовый пример: выполните тестируемую функцию в соответствии с входными условиями, сравните фактические результаты с ожидаемыми и подтвердите правильность выходных данных;
  3. Очистите тестовую среду: перезапустите ресурсы, занятые тестом, очистите ненужные файлы в среде и т. д.

4. Введение в JUnit и Mockito

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

Mockito — это среда макетирования Java, которая предоставляет макеты объектов или заглушки во время тестирования, что упрощает написание, понимание и выполнение модульных тестов. Mockito поддерживает различные средства сопоставления макетов, и вы можете подтвердить правильность вывода, проверив параметры вызова.

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

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

  1. Тестирование ввода: проверка легальности ввода, граничных значений, исключений и т. д. с целью обнаружения потенциальных ошибок в коде.
  2. Логическое тестирование: проверьте, соответствует ли бизнес-логика функции требованиям проектирования, например определение правильности ввода и вывода и т. д.
  3. Граничное тестирование: проверьте, является ли код отказоустойчивым при обработке экстремальных ситуаций, таких как исключения нулевого указателя, исключения переполнения и т. д.
  4. Тестирование производительности: проверьте скорость работы кода и улучшите надежность и эффективность кода.
  5. Тестирование совместимости: проверка совместимости с различными версиями и платформами.
  6. Тестирование интерфейса: проверьте, соответствует ли интерфейс функции ожиданиям пользователя, например, верны ли параметры, правильный ли тип возвращаемого значения и т. д.
  7. Автоматизированное тестирование. Используйте сценарии и инструменты для реализации автоматизированного модульного тестирования и повышения эффективности.

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

  1. Тестирование глубокой логики. Ключом к модульному тестированию является тестирование глубокой логики, но тестирование глубокой логики неизбежно включает в себя сложные структуры данных и алгоритмы, поэтому это также очень сложно.
  2. Управление зависимостями: Модульное тестирование часто включает взаимодействие между несколькими компонентами. Как интегрировать эти компоненты вместе и эффективно управлять зависимостями этих компонентов, является одной из трудностей модульного тестирования.
  3. Сложность отладки. Поскольку модульные тесты обычно пишутся во время разработки, обнаружить ошибки сложно. Чтобы решить эту проблему, необходимо написать инструменты отладки для модульных тестов, такие как печать стека вызовов в случае сбоя утверждения.

6. План практики модульного тестирования

Практический план модульного тестирования показан на рисунке ниже:

(1) Входной тест

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

(2) Проверка логики

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

(3) Граничное тестирование

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

(4) Тест производительности

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

(5) Тест на совместимость

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

(6) Тест интерфейса

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

(7) Автоматизированное тестирование

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

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

1. В чем разница между JUnit и Mockito?

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

  1. Функция: Mockito может создавать поведение моделируемых объектов и проверять правильность вывода кода на основе проверки параметров вызова. JUnit может создавать модульные тесты, а также запускать модульные тесты.
  2. Назначение: Mockito подходит для более сложных сценариев, в которых необходимо моделировать поведение класса. JUnit больше фокусируется на написании, выполнении и анализе результатов модульных тестов.
  3. Установка: JUnit необходимо установить плагин в IDE, Mockito можно скачать напрямую и добавить в проект.

2. Почему модульное тестирование?

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

  1. Улучшите качество кода. С помощью модульного тестирования вы можете обнаружить в коде грамматические ошибки, логические ошибки, функциональные дефекты и т. д., улучшая читаемость и удобство сопровождения кода. В то же время модульное тестирование также может эффективно обеспечить надежность кода и избежать сбоев продукта.
  2. Сократите затраты на обслуживание: после написания модульных тестов вы можете сосредоточиться на поведении кода и игнорировать то, как он реализован. Таким образом можно сократить затраты на обслуживание, сократить цикл разработки и повысить стабильность и жизнеспособность кода.
  3. Повышение эффективности разработки. Модульное тестирование может не только улучшить качество кода, но и снизить затраты на обслуживание. Написав модульные тесты, вы можете снизить вероятность ошибок в коде, повысить эффективность разработки, сократить цикл разработки и сэкономить время и ресурсы разработки.

3. Как писать модульные тесты?

  1. Напишите тестовые примеры, используя подход TDD. Сначала вам нужно уточнить требования, а затем определить минимально жизнеспособный продукт (MVP). Ключом к определению MVP является сначала тестирование, то есть сначала написание модульных тестов, а затем код для реализации функций.
  2. Отдельные опасения. При написании модульных тестов вам необходимо разделить задачи и не сосредотачивать все тесты на одной функции или модуле. Это облегчает сопровождение и масштабируемость.
  3. Тестируйте только важные функции. Модульные тесты должны тестировать только действительно важные функции, а не тривиальные функции или зависимые сторонние библиотеки.
  4. Используйте тестовые данные и структуры данных. Модульные тесты должны использовать конкретные тестовые данные или структуры данных, иначе невозможно оценить, правильно ли ведет себя функция.

4. Почему юнит-тесты не могут полностью охватить все ситуации?

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

рекомендация

отblog.csdn.net/universsky2015/article/details/133446773