Файл: Практическая значимость выбранной темы. Разработчикам и компаниям,занимающимся разработкой по, всегда следует стремиться найти все возможные ошибки до того, как программа поступит к заказчику или конечному потребителю. Цель.pdf

ВУЗ: Не указан

Категория: Реферат

Дисциплина: Не указана

Добавлен: 07.11.2023

Просмотров: 57

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Содержание:
ВВЕДЕНИЕ
На сегодняшний день информационные технологии проникли практически во все сферы деятельности человека. Чтение новостей, организация и обеспечение бизнес-процессов, обучение, общение, развлечение и многое другое современному человеку сложно представить в отрыве от информационных технологий. Поэтому многие разработчики и организации занимаются прикладным и системным программированием, создавая программное обеспечение для закрытия постоянно растущих потребностей пользователей. При этом созданное программное обеспечение (далее ПО) активно применяется пользователями и становится неотъемлемой частью их деятельности. Поэтому крайне важно обеспечить стабильность работы ПО на этапе разработки.
Следствием применения тестирования при разработке продукта является снижение затрат заказчика и потребителя. Эти затраты связаны с необходимостью устранить ошибки в программе, из-за которых нарушается процесс разработки [9].
На сегодняшний день проблема качества программного продукта становится все более острой, особенно по мере расширения использования информационных технологий и роста сложности программ [23]. Отладка и тестирование являются важными элементами, независимо от выбранного языка программирования и платформы, для которой разрабатывается ПО. Этим обусловлена актуальность
затрагиваемых в работе проблем.
Ошибки в программах неизбежны. Поиск багов и выявление ошибок позволяет снизить финансовые и репутационные риски для разработчиков программы, найти и устранить критически ошибки в программном коде. Этим подтверждается
практическая значимость выбранной темы. Разработчикам и компаниям,
занимающимся разработкой ПО, всегда следует стремиться найти все возможные ошибки до того, как программа поступит к заказчику или конечному потребителю.
Цель исследования: охарактеризовать процессы тестирования и отладки.
Исходя из цели работы были сформулированы следующие задачи:
проанализировать историю развития тестирования;
рассмотреть виды и парадигмы тестирования;
провести сравнительный анализ тестирования и отладки,
провести отладку приложения способом трассировки.
Данная курсовая работа состоит из двух глав. В первой главе мы определим значение терминов «тестирование», «отладка программ», назовем методы тестирования и опишем процесс тестирования. Будут рассмотрены методы тестирования, даны общие рекомендации по отладке приложений. Помимо этого,
мы охарактеризуем различные виды ошибок и способы их выявления. Во второй главе мы коснемся практических моментов на этапах отладки приложения на примере среды разработки приложений JetBrains WebStorm, на языке программирования JavaScript.
Глава 1. СУЩНОСТЬ ТЕСТИРОВАНИЯ И ОТЛАДКИ
Под тестированием понимается процесс выполнения программы с намерением найти ошибки [21; 27]. Но стоит отметить, что тестирование не гарантирует нахождения 100% ошибок и, как следствие, полного отсутствия неисправностей в программе. Иными словами, тестирование показывает, что нам пока неизвестно, в каких случаях программа может дать сбой.
Количество ошибок в ПО можно снизить, но не исключить полностью [26] путем правильного проектирования программного продукта. Но стопроцентный безошибочный результат практически невозможен. Поэтому процесс тестирования и отладки состоит в том, чтобы определить местонахождение немногих ошибок,
присутствующих в хорошо спроектированном программном продукте и убедиться,
что программа работает корректно в рамках ожидаемых пользовательских сценариях взаимодействия с ПО.
В рамках этой главы мы рассмотрим историю развития тестирования, дадим краткую характеристику видам тестирования и существующим парадигмам,
разберем отличия тестирования от отладки.
1.1 История развития тестирования


Самые первые программные продукты начали разрабатывать в рамках программ научных исследований министерств обороны. Тестирование подобных систем проводилось строго формализовано с записью всех тестовых процедур, тестовых данных, полученных результатов [32]. Тестирование было выделено в самостоятельный процесс, который имел место после завершения кодирования, и производилось все, обычно, тем же персоналом.
В 50–60-х годах прошлого века процесс тестирования был чрезвычайно формализован, отделен от процесса непосредственной разработки ПО и
«математизирован». Фактически тестирование представляло собой скорее отладку программ. Однако существовала концепция «исчерпывающего тестирования
(exhaustive testing)». Она состояла в проверке всех возможных путей выполнения кода со всеми возможными входными данными. Но очень скоро разработчики пришли к выводу, что исчерпывающее тестирование невозможно, потому что количество возможных путей и входных данных очень велико, а также при таком подходе сложно найти проблемы в документации [15].
В 70-х годах фактически родились две фундаментальные идеи тестирования:
тестирование сначала рассматривалось как процесс доказательства работоспособности программы в некоторых заданных условиях (positive testing), а затем — строго наоборот: как процесс доказательства неработоспособности программы в некоторых заданных условиях (negative testing). Это внутреннее противоречие не только не исчезло со временем, но и в наши дни многими авторами совершенно справедливо отмечается как две взаимодополняющие цели тестирования [17].
Отметим, что в современной практике разработки «процесс доказательства неработоспособности программы» ценится чуть больше. Это связано с тем, что negative testing не позволяет закрывать глаза на обнаруженные проблемы.
Итак, ещё раз самое важное, что тестирование «приобрело» в 70-е годы:
тестирование позволяет удостовериться, что программа соответствует требованиям;
тестирование позволяет определить условия, при которых программа ведёт себя некорректно.
В 80-х годах произошло ключевое изменение места тестирования в разработке ПО:
вместо одной из финальных стадий создания проекта тестирование стало применяться на протяжении всего цикла разработки (software lifecycle), что
позволило в очень многих случаях не только быстро обнаруживать и устранять проблемы, но даже предсказывать и предотвращать их появление. В этот же период времени отмечено бурное развитие и формализация методологий тестирования, а также появление первых попыток автоматизировать тестирование.
В 90-х годах произошёл переход от тестирования как такового к более всеобъемлющему процессу, который называется «обеспечение качества» (quality assurance), охватывает весь цикл разработки ПО и затрагивает процессы планирования, проектирования, создания и выполнения тест-кейсов, поддержку имеющихся тест-кейсов и тестовых окружений. Тестирование вышло на качественно новый уровень, который естественным образом привёл к дальнейшему развитию методологий, появлению достаточно мощных инструментов управления процессом тестирования и инструментальных средств автоматизации тестирования, уже вполне похожих на своих нынешних потомков [15].
С переходом в новый век развитие тестирования продолжалось в контексте поиска всё новых и новых путей, методологий, техник и подходов к обеспечению качества.
Серьёзное влияние на понимание тестирования оказало появление гибких методологий разработки и таких подходов, как «разработка под управлением тестированием (test-driven development, TDD)» [33]. Автоматизация тестирования уже воспринималась как обычная неотъемлемая часть большинства проектов, а также стали популярны идеи о том, в тестировании наиболее важно не соответствие программы требованиям, а её способность предоставить конечному пользователю возможность эффективно решать свои задачи.
Из вышесказанного можно сделать вывод, что тестирование является важнейшим составляющим процесса разработки ПО. Мы можем наблюдать, как подходы к тестированию развивались и улучшались с течением времени. Несмотря на уже отмеченное развитие, подходы к тестированию продолжают изменяться.
Интеграция с процессом разработки становится более глубокой. Появляются более гибкие методологии, развиваются решения по автоматизации тестирования, во многих командах применяется кроссфункциональность, когда программист и тестировщик могут во многом дополнять друг друга.
1.2 Виды тестирования
В зависимости от целей, преследуемых в процессе тестирования, его можно разделить на три группы:

функциональное,
нефункциональное,
связанное с изменениями [20].
Рассмотрим первую группу. Под функциональным тестированием понимается тестирование непосредственно функций и задач продукта. Функциональное тестирование рассматривает заранее указанное поведение и основывается на анализе спецификаций функциональности компонента или системы в целом. Эти тесты описываются в спецификациях и основываются на функциях, выполняемых системой, и могут проводиться на всех уровнях тестирования: модульном,
интеграционном, системном и приемочном [14].
На модульном уровне тестирования проверяется корректная работа одного отдельного модуля внутри себя [15]. Тесты для такого тестирования обычно пишутся самим разработчиком еще до написания основного кода программы. Если код модуля успешно проходит на соответствие всем проверкам, которые были описаны до его написания, он считается завершенным.
Интеграционный уровень тестирования делится на модульный интеграционный уровень и системный интеграционный уровень. В модульном интеграционном уровне проверяется взаимодействие между модулями системы после проведения модульного тестирования. Все написанные модули объединяют и происходит проверка на соответствие корректной работы не одного модуля, а взаимодействия нескольких [14].
В системном интеграционном уровне проверяется взаимодействие между разными системами после проведения системного тестирования. Это проверка на соответствие корректной работы разных приложений, программ, сайтов между собой. На системном уровне полностью проверяется работа всей системы,
взаимодействия всех ее модулей и всех программ между собой [14].
На приемочном уровне тестирования выполняется проверка соответствия разрабатываемой системы требованиям клиента. Таким образом, основная функция приемочного тестирования заключается не в тестировании кода, а в создании именно такой системы, которая требуется клиенту или предприятию [31].
Преимуществом функционального тестирования является имитация фактического использования программы, а к недостаткам можно отнести возможность упущения логических ошибок в продукте и возможную вероятность избыточного тестирования. Широко используется автоматизация функционального
тестирования [20].
В функциональной группе тестирования выделяются несколько видов. Назовем и охарактеризуем наиболее распространенные.
1. Функциональное тестирование. В рамках этого вида тестирования проверяется соответствие реализованных функций требованиям, техническому заданию,
спецификациям, различным другим проектным документам и просто ожиданиям пользователя. Разработчики проверяют каждую из функций приложения и всех их в комплексе, исследуя все сценарии использования [20].
2. Тестирование безопасности. В ходе тестирования проверяется фактическая реакция защитных механизмов, встроенных в систему, на проникновение [5].
Данный вид тестирования используется для проверки безопасности системы, а также для анализа рисков, связанных с обеспечением целостного подхода к защите приложения, атак хакеров, вирусов, несанкционированного доступа к конфиденциальным данным. Для проверки безопасности программы тестировщику разрешается найти ключ входа в систему, используя несекретные данные, и выполнить атаку системы с помощью специальных утилит, анализирующих защиты.
3. Тестирование взаимодействия. Функция названного вида тестирования –
проверить способность приложения взаимодействовать с одним и более компонентами или системами [18; 20]. Важность применения данного вида тестирования обусловлена развитием сетевых технологий и Интернета. В случае успешного прохождения теста взаимодействия программное обеспечение может быть легко интегрировано с другими системами без каких-либо серьезных модификаций.
Перейдем ко второй группе тестирования – нефункциональному.
Нефункциональное тестирование основывается на тестах, необходимых для определения различных характеристик продукта, которые измеряются всевозможными величинами, т.е. показывает, как программа ведет себя в работе
[14]. Нефункциональное тестирование включает в себя ряд подвидов:
тестирование производительности, установки, удобства использования, на отказ и восстановление и конфигурационное тестирование [20].
1. Главная функция тестирования производительности - выявить, насколько система корректна работает при одновременном использовании данного продукта многими пользователями. В ходе тестирования выявляются потери данных

пользователей, максимальное количество одновременный пользователей [11].
2. Тестирование установки призвано выполнить проверку, насколько корректно программа устанавливается на рабочую машину пользователя и удаляется с нее
[11]. В настоящее время получила установка программ с помощью специальных программных модулей – инсталляторов. Если инсталлятор не предусмотрен,
установка производится самостоятельно согласно инструкциям и спецификациям,
либо специальному плану установки [18].
3. Тестирование удобства пользования характеризует усилия, необходимые для использования программного продукта, и индивидуальную оценку результатов его использования. Программа признается удобной в использовании тогда, когда обладает следующими свойствами: полезность, эффективность,
производительность, осваиваемость, удовлетворенность, доступность [1].
Тестирование удобства может проводить не только тестировщик, но и группа конечных пользователей в тестовых режимах продукта. Это помогает собрать нужную и общую информацию о том, насколько конечным клиентам будет удобно пользоваться продуктом [19].
4. Тестирование на отказ и восстановление выполняет проверку программного продукта на возможность восстановиться после сбоя. В рамках тестирования специалисты занимаются рассмотрением всех возможных вариантов отказа системы и проверяют программу на адекватную реакцию на эти отказы [10].
Тестировщиками проверяются системы отката и восстановления, обеспечивающие целостность и сохранность данных ПО в случае сбоя в нормальной работе программы или окружения. Данное тестирование необходимо при проектировании продуктов, так как следствием потери данных является уход клиентов и снижение репутации компании [18].
5. Конфигурационное тестирование производит проверку работоспособности программы в разных конфигурациях системы, платформах, средах, устройствах и т.д. Цель тестирования - определить набор конфигураций, которые будут достаточны для работы системы на конкретном устройстве [10]. В качестве самого популярного примера такого тестирования можно назвать минимальные и подходящие системные требования для игр [19].
Последняя группа – тестирование, связанное с изменениями. Его функция –
проверить систему после каких-либо внесенных изменений в ней. Это наиболее распространенное на практике тестирование, так как любое внесение изменений в
программу может привести к ошибкам, которых не было до изменений [19]. Ф.
Брукс в своей книге «Мифический человеко-месяц» писал: «Фундаментальная проблема при сопровождении программ состоит в том, что исправление одной ошибки с большой вероятностью (20–50 %) влечёт появление новой» [4, с. 70].
Связанные с изменениями виды тестирования применяются внесения необходимых изменений и корректировки в продукт. Программа должна быть заново протестирована, чтобы подтвердить, что ошибка была устранена [8].
Основными видами этого тестирования являются дымовое тестирование,
регрессионное тестирование, тестирование сборки, санитарное тестирование.
1. Понятие «дымовое тестирование» пришло в тестирование из инженерной среды.
При вводе в эксплуатацию нового оборудования считалось, что тестирование прошло удачно, если из установки не пошел дым. В области же тестирования программного обеспечения оно направлено на поверхностную проверку всех модулей приложения на предмет работоспособности и наличие быстро находимых критических и блокирующих дефектов. Результатом дымового тестирования является заключение о том, принимается или нет установленная версия программного обеспечения в тестирование, эксплуатацию или на поставку заказчику. Для облегчения работы, экономии времени и людских ресурсов рекомендуется внедрить автоматизацию тестовых сценариев для дымового тестирования [20].
2. Регрессионное тестирование представляет собой полное тестирование продукта
[11]. Это тестирование считается самым длительным и трудозатратным. На его этапе обнаруживается большинство багов и несоответствий системы и технического задания. Трудность заключается в том, что при обнаружении бага на финальном этапе тестирования и его устранения необходим повторный цикл тестирования [19].
3. Тестирование сборки служит для определения соответствия, выпущенной версии, критериям качества для начала тестирования. По цели оно схоже с дымовым тестированием, так как направленно на приемку новой версии в дальнейшее тестирование или эксплуатацию [20].
4. Санитарное тестирование применяется при проверке работы конкретной функции или блока. Относится к подмножествам регрессионного тестирования и определяет работоспособность части продукта после изменения. Следует различать дымовое и санитарное тестирование: дымовое тестирование – это

больше тестирование основного функционала «вширь», для проверок «вширь», при санитарном же тестировании происходить проверка одной конкретной функции или модуля «вглубь» [19].
Подведем итог. В данном параграфе мы рассмотрели виды тестирования.
Тестирование является сложной деятельностью, направленной на решение множества проблем, из-за чего оно представлено в разных группах, вида и подвидах.
1.3 Парадигмы тестирования
На современном этапе развития тестирования сформировались две противоположные парадигмы – поведенческое и структурное тестирование [3].
Рассмотрим стратегию поведенческого тестирования. Она основана на технических требованиях к программному обеспечению. Другое название парадигмы -
тестирование «черного ящика» (black-box testing). Подход заключается в том, что проведении процедуры тестирования не обязательно знать, как программа сконструирована внутри, известна только информация о его входах и выходах. При этом нет никаких данных о том, как именно программа преобразует входные данные в выходные. В связи с этим парадигма и получила свое название.
В рамках проведения тестирования «черного ящика» в соответствии с требованиями к программному продукту определяется набор тестовых входных данных и предсказывается корректное поведение программы. После этого программа выполняется на подготовленном наборе и результат сравнивается с предсказанным [2].
Критерием исчерпывающего входного тестирования является обнаружение всех ошибок в программе. Критерий может быть достигнут, если в качестве тестовых наборов использовать все возможные наборы входных данных. Однако построение исчерпывающего входного теста невозможно. Это объясняется двумя причинами:
отсутствует возможность создания теста, гарантирующего отсутствие ошибок;
разработка таких тестов противоречит экономическим требованиям [20].
С. В. Бирюков выделяет такие методы поведенческого тестирования, как тестирование потока управления, тестирование потоков данных, тестирование доменов, синтаксическое тестирование, тестирование систем с конечным числом
состояний, тестирование циклов [3].
Перейдем к рассмотрению стратегии структурного тестирования. Она определяется структурой исследуемого программного обеспечения. Второе название парадигмы - тестирование «белого ящика» (white-box testing) или тестирование «прозрачного ящика». Как и в предыдущем случае, название происходит из структуры тестирования. В данном случае тестировщик исходит из знания того, как программный продукт сконструирован внутри. Нам известна не только информация о его входах и выходах, но, прежде всего, известен механизм преобразования входных данных в выходные [18].
Набор тестовых входных данных определяется исходя из ряда параметров. К ним относится структура программы, наличие и взаимное расположение в коде определенных конструкций языка программирования – циклов, условных операторов и т.п. Набор данных определяется с одной целью – обеспечить необходимое (в зависимости от выбранного метода структурного тестирования)
покрытие программного кода. Предсказание результатов заключается в указании правильного направления потока управления и корректного состояния внутренних переменных на каждом шаге выполнения программы [3].
Основные методы структурного тестирования - покрытие операторов программы,
покрытие ветвей программы, покрытие условий [3].
Помимо двух названных парадигм тестирования, некоторыми исследователями выделяется и промежуточный подход, который использует идеи первых двух –
тестирование «серого ящика». В случае применения этого подхода тестировщик получает доступ к алгоритмам работы программы.
У данного подхода есть достоинства и недостатки. Одним из главных достоинств данного метода является то, что он включает в себя положительные черты тестирования «белого ящика» и тестирования «черного ящика». К достоинствам подхода можно отнести то, что человек, тестирующий программу, видит программу со стороны «черного ящика», а анализирует данные с позиции тестирования
«белого ящика». Изначально при данном методе тестировщик и разработчик работают вместе, что позволяет избежать избыточные наборы тестовых данных, но и увеличивает время для исправления выявленных ошибок. Выделяются и недостатки, такие как отсутствие возможности протестировать все возможные тестовые наборы данных и ограниченность в анализе тестового покрытия, так как доступ к программному коду закрыт [23].