Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Тестирование и отладка программного обеспечения.

Содержание:

ВВЕДЕНИЕ

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

Следствием применения тестирования при разработке продукта является снижение затрат заказчика и потребителя. Эти затраты связаны с необходимостью устранить ошибки в программе, из-за которых нарушается процесс разработки [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].

Подведем промежуточные итоги. В современном тестировании выделяются два подхода: тестирование «черного ящика» и тестирование «белого ящика». Между ними некоторыми теоретиками выделяется и промежуточный подход – тестирование «серого ящика», который объединяет достоинства двух названных выше.

1.4 Отладка ошибок. Их виды

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

Отладка не является разновидностью тестирования. Тестирование ставит задачу определения наличия ошибок [21; 27], в то время как отладка служит для определения местоположения выявленных тестированием ошибок в исходном коде и их устранения [20]. Если цели этих двух этапов разработки программ различны, то, соответственно, используются различные методика и инструментарий. Важно разделять процесс тестирования и процесс отладки на два различных этапа работы над программой. Важно отметить, что эти два вида деятельности связаны: результаты тестирования являются исходными данными для отладки.

В настоящее время выделяется несколько способов отладки [6]. Перечислим их:

  • интерактивная отладка,
  • командный язык отладки,
  • трассировка,
  • самоотладка,
  • детерминированное воспроизведение выполнения,
  • отладка аппаратных конфигураций,
  • отладка производительности.

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

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

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

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

  • нелогичный пользовательский интерфейс;
  • неудовлетворенные ожидания;
  • низкая производительность;
  • аварийные завершения или разрушение данных [24].

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

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

В случае проектирования интерфейса Web-приложения, эта задача существенно усложняется. Здесь уже нет конкретных стандартов на пользовательский интерфейс. Самое главное, что надо учитывать при разработке интерфейса для Web-клиента, — это возможную низкую скорость трафика, поэтому следует создавать пользовательский интерфейс максимально простым и загружать с сервера только необходимые ресурсы чтобы максимально снизить время загрузки и ожидания пользователя. К примеру, простые решения, подобные CNN.com, нравятся практически всем пользователям. Использование простого набора ссылок выглядит куда лучше и работает быстрее, чем перегруженный различными функциями и графическими материалами интерфейс. Подобный перегруженный интерфейс легко может вызывать неудобство или даже отпугивать пользователя [8].

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

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

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

Есть два основных метода борьбы с подобными ошибками. С одной стороны, необходимо на этапе проектирования установить конкретные требования к производительности программного продукта. Для выявления проблем с производительностью нужно сравнить основные показатели работы приложения под разными нагрузками. Если вдруг происходит потеря производительности допустимый предел, то необходимо принять меры и выяснить – по какой причине это произошло и внести нужные изменения в код. Далее надо убедиться в том, что нагрузка действительно соответствует наиболее близким к реальной жизни сценариям, и делать это нужно на самых ранних этапах проектирования [24].

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

А. Ю. Герасимов предлагает разделять все множество программных ошибок, приводящих к некорректному поведению программы во время исполнения, на следующие классы по видам вредоносного воздействия:

  • «ошибки, приводящие к порче пользовательских данных в процессе обработки: целочисленное переполнение, порча данных в оперативной памяти, обращение к неинициализированному блоку памяти, обращение к памяти по неинициализированному или висящему указателю (англ. – dangling pointer), фальсификация данных (англ. - request forgery) и др.;
  • ошибки, приводящие к неавторизованному доступу к пользовательским данным: получение неавторизованного доступа к базе данных, получение неавторизованного доступа к информации в оперативной или постоянной памяти вычислительного устройства, получение повышенного уровня привилегий доступа к данным и др.; • ошибки, приводящие к исчерпанию системных ресурсов, таких как память на куче, файлы, сокеты и др.;
  • ошибки, приводящие к аварийному завершению исполнения программы: доступ к области памяти, не принадлежащей программе, деление на ноль и др.;
  • ошибки, приводящие к исполнению злонамеренного кода: перехват потока управления злонамеренным кодом, исполнение злонамеренного кода на стороне клиента, внедрение в исполнение команды в командной строке и др.» [7, с. 15].

Каковы причины появления ошибок? Рассмотрим несколько возможных путей их возникновения.

Во-первых, непонимание разработчиками требований, предъявляемых к программному продукту [24]. Так может происходить, например, когда в приложение вносятся функции без явной необходимости.

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

В-третьих, какие-либо административные причины: слишком сжатые и невозможные для разработки поставленные сроки, отсутствие достаточного времени на отладку и тестирование приложения. Вопрос о приемлемости поставленных сроков должен обсуждаться всеми разработчиками на основании набора реализуемых функций. В случае излишне сжатых сроков лучше стоит сократить функционал или вовсе отказаться от разработки. Одной из частых причин ошибок в программах является недостаточная вовлеченность и чувство ответственности за результат в команде занимающейся разработкой. Так, разработчик может постараться сэкономить время и постараться скрыть недобросовестное отношение к написанию кода. Поэтому очень важно, чтобы все в команде разработки осознавали, насколько важен их вклад в то, каким получится итоговый продукт. Производители программного обеспечения, по-настоящему приверженные качеству, должны опираться на тщательное планирование, персональную ответственность, надлежащий контроль качества и хорошие способности к общению с клиентами и между собой. Только те разработчики, которые уделяют значительное внимание деталям, будут выпускать продукцию в нужные сроки и отличного качества [29].

Т. Н. Лебедева и Л. С. Носова выделили несколько направлений по предотвращению ошибок:

1. «Использование встроенных возможностей системы программирования на этапе разработки программы (дозапись кода, работа с шаблонами, отладка программы и др.).

2. Разработка кода по отраслевым и специальным стандартам программирования.

3. Использование программ для автоматического и автоматизированного тестирования разработанного приложения» [16, с.55].

Принципы тестирования основываются на вопросах психологии. Принципы в основном интуитивно понятны, однако иногда они остаются без должного внимания. Данные позиции перечислены И.В. Степанченко [28].

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

2. Следует избегать тестирования программы ее автором. Отметим, что данные принцип не исключает полностью тестирование программистом своего кода. Однако тестирование является более эффективным, если оно выполняется кем-либо другим.

3. Необходимо досконально изучать результаты применения каждого теста. Неполное изучение результатов оставляет не выявленными ряд ошибок.

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

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

6. Тестирование — процесс творческий. Не исключено, что для тестирования большой программы требуется больший творческий потенциал, чем для ее проектирования.

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

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

В современной практике выделяется две противоположные парадигмы тестирования – поведенческое и структурное. В основе обоих лежит принцип «ящика»: подходы различаются в исходной информации, доступной инженеру тестирования при работе с программой.

В ходе работы мы выяснили отличия между процессом тестирования и отладки. Второе является последующим этапом для тестирования, в ходе которого находится «проблемный» код и исправляется.

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

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

Глава 2. ПРАКТИКА ОТЛАДКИ ПРИЛОЖЕНИЙ В СРЕДЕ JAVASCRIPT

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

2.1 Инструментарий поиска и отслеживания ошибок

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

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

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

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

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

Многих проблем при разработке программных продуктов можно избежать, используя в системе управления версиями, так называемые Модульные тесты (unit tests).

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

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

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

Система управления версиями должна соответствовать потребностям разработчика. По данным сервиса GitHub, в 2019 году аудитория сервиса достигла 41 млн. уникальных пользователей, а число компаний официально представленных на сервисе достигло 2.9 млн [34]. GitHub — крупнейший веб-сервис для хостинга IT-проектов и их совместной разработки. Веб-сервис основан на системе контроля версий Git. Данная статистика позволяет утверждать, что на сегодняшний день система контроля версий Git является наиболее распространенным решением для обеспечения контроля версий приложений среди разработчиков и компаний.

2.2 Применение точек остановки и модификация локальных переменных

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

К синтаксическим ошибкам относятся ошибки в написании конструкций языка программирования, неверной записью идентификаторов и иными неверными действиями программиста, которые нарушают строгие правила написания исходного кода на выбранном языке программирования. Такие ошибки препятствуют исполнению программы или делают его невозможным к запуску. Следует постоянно обращать внимание на различные сообщения и предупреждения, выдаваемые интерпретатором при попытке запуске программы. Это может помочь обнаружить найти ошибку в тексте кода. Также существуют среды разработки приложений на языке JavaScript. Например, Microsoft Visual Studio Code[1] или JetBrains WebStorm[2]. Данные программы являются комплексными решениями, помогающими разработчику в написании программ. Они включают в себя редактор исходного кода, обеспечивают статический анализ исходного кода создаваемого приложения, предоставляют систему отладки, подсветку и выделение цветом конструкций языка в исходном коде программы и многие другие полезные для разработчиков функции. Для облегчения процесса написания кода Visual Studio Code и WebStorm имеют встроенный упрощенный компилятор языка JavaScript, который используется для статического анализа написанного кода и предупреждения синтаксических ошибок на этапе написания программы. Таким образом, разработчику значительно проще найти синтаксические ошибки еще на этапе написания программы.

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

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

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

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

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

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

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

let a = 1;

let b = 123;

a += 1;

a += 1;

a += b;

a = 1;

a += 1;

console.log(a);

console.log(a.toString(16));

После запуска данной программы, в журнале исполнения мы увидим значения 2, и 2. Это совсем иные результаты. Поскольку была допущена ошибка в операторе во время выполнения процедуры увеличения переменной “a” на единицу. Для того чтобы быстро выяснить, где же допущена ошибка установим точку остановки на третьей строке и запустим программу:

Рисунок 1

На рисунке 1 видно, что исполнение программы приостановилось на строке 3. Остановка происходит до исполнения инструкций на строке, поэтому в окне Variables видно текущее значение переменных. На данном этапе все работает как задумано, поэтому используем кнопку Step over F8 и продолжаем выполнение программы. Нажатие данной кнопки исполнит программу ровно на одну строку и снова приостановит выполнение программы. После того как программа достигнет строки 7, можно увидеть, что значение переменной “а” равно 1, хотя ожидается что значение будет равно 127.

Уже сейчас можно понять, что допущена ошибка в операторе присваивания значений переменной на строке 6. Но мы пока не будем изменять исходный код и попробуем воспользоваться инструментом Evaluate expression Alt + F8. Данный инструмент позволяет выполнить любое выражение и как бы встроить его в программу на ту точку, где сейчас остановлено выполнение программы. Важно понимать, что данное действие несет временный характер и не сохраняется после завершения процесса отладки. Мы попробуем остановить исполнение программы на строке 8, вручную установить значение переменной на ожидаемое значение и посмотрим каким будет результат исполнения программы. Интерфейс Evaluate expression представлен на рисунке 2.

Рисунок 2

Теперь выполним программу до конца и посмотрим на результат исполнения. В результате исполнения в журнал были выведены ожидаемые значения 128 и 80. Это позволяет нам убедиться, что мы успешно изменили значение переменной “а” с использованием инструмента Evaluate expression.

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

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

2.3 Пошаговая трассировка приложения

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

Сущность трассировки заключается в пошаговой прогонке программного кода. В предыдущем параграфе мы уже коснулись инструмента пошаговой трассировки, когда использовали команду Step over F8. При выполнении трассировки можно использовать команды, представленные в таблице 1.

Наименование команды

Горячая клавиша

Действие отладчика

«Step Into»

«F7»

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

«Step Over»

«F8»

аналогично «Step Into», но вход в тело вызываемой функции не происходит.

«Smart step into»

«Shift+F7»

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

“Force step into”

“Shift+Alt+F7”

используется чтобы зайти в код функции, даже если обычный вызов Step into в нее не зашел.

“Step out”

“Shift+F8”

выходит из кода вызванной функции, возвращает инспектор в метод, вызвавший данную функцию.

«Run to Cursor»

«Alt+F9»

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

“Force run to cursor”

“Ctrl+Alt+F9”

аналогично команде Force step into, принудительно выполняет команду Run to Cursor.

«Force step over»

«Shift+Alt+F8»

принудительно выполняет команду Step over даже если следующая строка — это вызов метода.

«Drop frame»

по умолчанию нет горячей клавиши

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

Таблица 1. Команда трассировки

Вторым по важности инструментом при отладке приложений является окно «Call Stack». Оно содержит описание всех вызовов до возникновения исключения, ошибки или прерывания в точке остановки.

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

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

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

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

ЗАКЛЮЧЕНИЕ

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

  • когда стоит завершить отладку программного продукта;
  • когда уже достаточно исправлено ошибок;
  • когда работа программы была опробована во всех возможных ситуациях и появление ошибок сведено к минимуму.

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

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

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

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

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

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

1. Необходимо считать тестирование и отладку важным этапом разработки программ.

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

3. Тестирование следует проводить как с верными, так и с заведомо неверными данными.

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

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

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

БИБЛИОГРАФИЧЕСКИЙ СПИСОК

  1. Атисков А. Ю., Давидович И. И. Тестирование эргономики пользовательского интерфейса мобильных приложений / А. Ю. Атисков, И. И. Давидович // Научный вестник НГТУ. — 2014. — Том 57, № 4. — С. 119-130.
  2. Бейзер Б. Тестирование «черного ящика». Технология функционального тестирования / Б. Бейзер. — СПб: Питер, 2004. — 318 с.
  3. Бирюков С. В. Анализ стратегий тестирования программного обеспечения [Электронный ресурс] / С. В. Бирюков // Cyberleninka. — URL: https://cyberleninka.ru/article/n/analiz-strategiy-testirovaniya-programmnogo-obespecheniya/viewer (дата обращения: 20.02.20).
  4. Брукс Ф., Чапел Х. Мифический человеко-месяц, или Как создаются программные системы / Ф. Брукс, Х. Чапел. — М.: Символ-Плюс, 2010. — 304 с.
  5. Вишневская Т. И. Тестирование программного обеспечения как учебная дисциплина / Т. И. Вишневская // Образовательные ресурсы и технологии. — 2014. — № 1 (4). — С. 83-88.
  6. Галатенко В. А., Костюхин К. А. Проблемы отладки многопроцессных систем [Электронный ресурс] / В. А. Галатенко, К. А. Костюхин // Cyberleninka. — URL: https://cyberleninka.ru/article/n/problemy-otladki-mnogoprotsessnyh-sistem (дата обращения: 21.02.20).
  7. Герасимов А. Ю. Классификация предупреждения о программных ошибках методом динамического символьного исполнения программ: диссерт. канд. физ.-матем. наук. Институт системного программирования им. В. П. Иванникова / А. Ю. Герасимов. — М., 2019.
  8. Глас Р. Руководство по надежному программированию / Р. Глас. — М.: Финансы и статистика, 2010. — 256 с.
  9. Инюшкина О.Г. Проектирование информационных систем (на примере методов структурного системного анализа): учебное пособие / О.Г. Инюшкина. — Екатеринбург: «Форт-Диалог Исеть», 2014. — 240 с.
  10. Калбертсон Р. Быстрое тестирование / Р. Калбертсон, К. Браун, Г. Кобб. – М.: Вильямс, 2002. — 374 с.
  11. Канер К. Тестирование программного обеспечения. Фундаментальные концепции менеджмента бизнес-приложений / К. Канер, Д. Фолк, Е. К. Нгуен. – Киев: ДиаСофт, 2001. – 544 с.
  12. Керман М. К. Программирование и отладка в Delphi. Пер. с англ. — М.: Вильямc, 2003. — 672 с.
  13. Коликова Т. В., Котляров В. П. Основы тестирования программного обеспечения / Т. В. Коликова, В. П. Котляров. — М.: Бином, 2010. — 285 с.
  14. Криспин Л, Грегори Д. Гибкое тестирование: практическое руководство для тестировщиков ПО и гибких команд / Л. Криспин, Д. Грегори. — М.: Вильямс, 2010. — 464 с.
  15. Куликов С. С. Тестирование программного обеспечения. Базовый курс / С. С. Куликов. — Минск: Четыре четверти,

2017. — 312 с.

  1. Лебедева Т. Н. Подводные камни при разработке программных решений / Т. Н. Лебедева // Управление в современных системах. — 2017. — № 3(14). — С. 49-56.
  2. Липаев В. В. Программная инженерия: методологические основы : учебник / В. В. Липаев. — М.-Берлин: Директ-Медиа, 2015. — 608 с.
  3. Майерс Г., Баджетт Т., Сандлер К. Искусство тестирования программ, 3-е изд.: Пер. с англ. / Г. Майерс, Т. Баджетт, К. Сандлер. — М.: Вильямс, 2012. — 272 с.
  4. Моисеев Д. А. Методология и процесс ручного тестирования / Д. А. Моисеев // Надежность и качество сложных систем. — 2017. — № 3 (19). — С. 107-112.
  5. Осипенко Н.Б. Основы стандартизации и сертификации программного обеспечения: тестирование программного обеспечения: практ. рук-во для студентов специальности 1–40 01 01 «Программное обеспечение информационных технологий» / Н. Б. Осипенко. — Гомель: ГГУ им. Ф. Скорины, 2014. — 36 с.
  6. Прокин А. А. Современное состояние и основные проблемы интернетторговли в российской федерации / А. А. Прокин, В. А. Богатырская, Е. С. Сергушина, И. С. Листратов // E-Scio. — 2018. — № 3 (18). — С. 36-41.
  7. Прокин А. А. Создание и актуальные проблемы продвижения «трансрегионавтоматика») [Электронный ресурс] / А. А. Прокин, В. А. Богатырская, Е. С. Сергушина, Е. В. Кренделев // Cyberleninka. — URL: https://cyberleninka.ru/article/n/sozdanie-i-aktualnye-problemy-prodvizheniya-sayta-na-primere-sayta-ooo-transregionavtomatika/viewer (дата обращения: 20.02.20).
  8. Прокин А. А., Баландин И. А. Способы тестирования учебных программ [Электронный ресурс] / А. А. Прокин, И. А. Баландин // Cyberleninka. — URL: https://cyberleninka.ru/article/n/sposoby-testirovaniya-uchebnyh-programm/viewer (дата обращения: 20.02.20).
  9. Роббинс Д. Отладка приложений для Microsoft .NET и Microsoft Windows / Д. Роббинс. — М.: «Русская Редакция», 2004. — 736 с.
  10. Синицын С. В., Налютин Н. Ю. Верификация программного обеспечения / С. В. Синицын, Н. Ю. Налютин. — М.: Бином, 2008. — 368 с.
  11. Соловьев С. В., Цой Р. И., Гринкруг Л. С. Тестирование и отладка [Электронный ресурс] / С. В. Соловьев, Р. И. Цой, Л. С. Гринкруг // Научная электронная библиотека. — URL: https://www.monographies.ru/ru/book/section?id=4632 (дата обращения: 23.02.20).
  12. Софронова Н. В. Теория и методика обучения информатике: уч. пособие / Н. В. Софронова. — М.: Высшая школа, 2003. — 186 с.
  13. Степанченко И. В. Методы тестирования программного обеспечения: уч. пособие / И. В. Степанченко. — Волгоград: ВолгГТУ, 2006. — 76 с.
  14. Тамре Л. Введение в тестирование программного обеспечения / Л. Тамре. — М.: Дрофа, 2009. — 368 с.
  15. Ховард М., Лебланк Д. Защищенный код: Пер. с англ, — 2-е изд., испр. / М. Ховард, Д. Лебланк. — М.: Русская Редакция, 2004. — 704 с.
  16. Холл Б. Автоматизация приемочного тестирования с помощью IronRuby [Электронный ресурс] / Б. Холл // Microsoft.docs. — URL: https://docs.microsoft.com/ru-ru/archive/msdn-magazine/2009/march/net-interop-automate-acceptance-testing-with-ironruby (дата обращения: 21.02.20).
  17. Чушкин М. С., Шелехов В. И. Генерация и доказательство условий корректности предикатных программ [Электронный ресурс] / М. С. Чушкин, В. И. Шелехов // Институт систем информатики им. А. П. Ершова СО РАН. — URL: https://www.iis.nsk.su/files/preprints/166.pdf (дата обращения: 21.02.20).
  18. Scott W. A. Introduction to Test Driven Development (TDD) [Электронный ресурс] / W. A. Scott // Agile Data. — URL: http://agiledata.org/essays/tdd.html (дата обращения: 22.02.20).
  19. The State of the Octoverse [Электронный ресурс] // GitHub. — URL: https://octoverse.github.com/ (дата обращения: 19.02.20).
  1. https://code.visualstudio.com/

  2. https://www.jetbrains.com/webstorm/