-
Notifications
You must be signed in to change notification settings - Fork 14
exam_14
Классификация — это разделение множества объектов на подмножества по сходству или различию в соответствии с принятыми методами.
Классификационный признак — это свойство или характеристика объекта, по которому производится классификация. Признак классификации имеет также синоним — основание деления. Признаки могут иметь качественное или количественное выражение, называемое значением признака классификации. [1]
Множество — это объединение в единое целое определенных различимых однотипных объектов, которые называются элементами множества. [2]
Классифицируемое множество — множество объектов, разделяемое на подмножества, по их сходству или различию в соответствии с принятыми методами.
Объект классификации — это элемент классифицируемого множества. Объект классификации изначально не принадлежит множеству.
Распознавание образов — это отнесение исходных данных к определенному классу с помощью выделения существенных признаков, характеризующих эти данные, из общей массы несущественных данных. [3] Классическая постановка задачи распознавания образов:
- Дано множество объектов, относительно которых необходимо провести классификацию
- Множество представлено подмножествами, которые называются классами.
- Заданы:
- информация о классах
- описание всего множества и
- описание информации об объекте, принадлежность которого к определенному классу неизвестна
- Требуется по имеющейся информации о классах и описании объекта установить - к какому классу относится этот объект
Модульное тестирование, или юнит-тестирование (англ. unit testing) — процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы, наборы из одного или более программных модулей вместе с соответствующими управляющими данными, процедурами использования и обработки.
Идея состоит в том, чтобы писать тесты для каждой нетривиальной функции или метода. Это позволяет достаточно быстро проверить, не привело ли очередное изменение кода к регрессии, то есть к появлению ошибок в уже оттестированных местах программы, а также облегчает обнаружение и устранение таких ошибок. [4]
На рисунке 1 изображены этапы тестирования. По рисунку становится понятно, что юнит-тестирование – это первый бастион на борьбе с багами. За ним еще интеграционное, приемочное и, наконец, ручное тестирование, в том числе «свободный поиск». [5]
Рис. 1. Этапы тестирования
Цель модульного тестирования — изолировать отдельные части программы и показать, что по отдельности эти части работоспособны. Этот тип тестирования обычно выполняется программистами. [4]
Модульное тестирование позже позволяет программистам проводить рефакторинг, будучи уверенными, что модуль по-прежнему работает корректно (регрессионное тестирование). Это поощряет программистов к изменениям кода, поскольку достаточно легко проверить, что код работает и после изменений.
Модульное тестирование помогает устранить сомнения по поводу отдельных модулей и может быть использовано для подхода к тестированию «снизу вверх»: сначала тестируя отдельные части программы, а затем программу в целом.
Модульные тесты можно рассматривать как «живой документ» для тестируемого класса. Клиенты, которые не знают, как использовать данный класс, могут использовать юнит-тест в качестве примера.
Поскольку некоторые классы могут использовать другие классы, тестирование отдельного класса часто распространяется на связанные с ним. Например, класс пользуется базой данных; в ходе написания теста программист обнаруживает, что тесту приходится взаимодействовать с базой. Это ошибка, поскольку тест не должен выходить за границу класса. В результате разработчик абстрагируется от соединения с базой данных и реализует этот интерфейс, используя свой собственный mock-объект. Это приводит к менее связанному коду, минимизируя зависимости в системе.
Тестирование программного обеспечения — комбинаторная задача. Например, каждое возможное значение булевской переменной потребует двух тестов: один на вариант TRUE, другой — на вариант FALSE. В результате на каждую строку исходного кода потребуется 3−5 строк тестового кода. Как и любая технология тестирования, модульное тестирование не позволяет отловить все ошибки программы. В самом деле, это следует из практической невозможности трассировки всех возможных путей выполнения программы, за исключением простейших случаев.
Например, в математическом моделировании. Бизнес-приложения зачастую работают с конечными и счётными множествами, научные — с континуальными. Поэтому сложно подобрать тесты для каждой из ветвей программы, сложно сказать, верен ли результат, выдерживается ли точность, и т. д. А во многих случаях качество моделирования определяется «на глаз», и последний результат записывается как «опорный». Если найдено расхождение, новый результат проверяют вручную и выясняют, какой качественнее: старый или новый.
Код, взаимодействующий с портами, таймерами и прочими «нестабильными» частями системы, крайне сложно проверить в изолированном окружении. Но это не значит, что модульное тестирование здесь полностью непригодно: оно вынуждает программиста перейти от файлов и портов, например, на абстрактные потоки. Это делает код более общим (например, без проблем можно перейти с файлов на сетевые сокеты), более тестируемым (можно даже проверить ситуацию «пропала связь»), ограничивает те части, которые не подлежат модульному тестированию.
При выполнении юнит-тестов происходит тестирование каждого из модулей по отдельности. Это означает, что ошибки интеграции, системного уровня, функций, исполняемых в нескольких модулях, не будут определены. Кроме того, данная технология бесполезна для проведения тестов на производительность. Таким образом, модульное тестирование более эффективно при использовании в сочетании с другими методиками тестирования.
Для получения выгоды от модульного тестирования требуется строго следовать технологии тестирования на всём протяжении процесса разработки программного обеспечения. Нужно хранить не только записи обо всех проведённых тестах, но и обо всех изменениях исходного кода во всех модулях. С этой целью следует использовать систему контроля версий ПО. Таким образом, если более поздняя версия ПО не проходит тест, который был успешно пройден ранее, будет несложным сверить варианты исходного кода и устранить ошибку. Также необходимо убедиться в неизменном отслеживании и анализе неудачных тестов. Игнорирование этого требования приведёт к лавинообразному увеличению неудачных тестовых результатов.
За исключением простейших случаев, тестируемый объект должен взаимодействовать с другими объектами. Этих «товарищей по взаимодействию» — объекты-заглушки — делают предельно простыми: либо крайне упрощёнными (память вместо БД), либо рассчитанными на конкретный тест и механически повторяющими сессию обмена. Вопросы начинаются, когда протокол обмена меняется; надо отыскивать эти заглушки во всех тестах и переводить под новый протокол. [4]
Проведём классификацию видов тестирования. Классификационным признаком будет уровень тестирования. Уровень тестирования определяет то, над чем производятся тесты: над отдельным модулем, группой модулей или системой, в целом. [6] Классификация видов тестирования по уровню:
- Модульное (Unit testing) — проверяет функциональность и ищет дефекты в частях приложения, которые доступны и могут быть протестированы по-отдельности (модули программ, объекты, классы, функции и т.д.).
- Интеграционное (Integration Testing) — предназначено для проверки связи между компонентами, а также взаимодействия с различными частями системы (операционной системой, оборудованием либо связи между различными системами).
- Системное (System Testing) — проверка как функциональных, так и не функциональных требований в системе в целом.
В модульном тестировании тест должен проверять только одну вещь. Если процесс слишком сложен, то необходимо разделить его на несколько частей и протестировать их отдельно. При выборе что именно тестировать, а что нет? Можно разделить код по алгоритмической сложности и количество зависимостей. Получим 4 группы:
- Простой код без зависимостей.
- Сложный код с большим количеством зависимостей.
- Cложный код без зависимостей.
- Не очень сложный код с зависимостями.