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

Отладка и тестирование программ: основные подходы и ограничения (РАЗРАБОТКА ПРОГРАММ)

Содержание:

ВВЕДЕНИЕ

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

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

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

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

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

Объект исследования данной работы – тестирование и отладка программ.

Предмет исследования – виды тестирования, тестирование надежности, организация процесса тестирования. Финишные этапы разработки программных систем.

Цель работы – описать финишные этапы процесса разработки, а также этап тестирования.

Для достижения данной цели предстоит решить ряд задач:

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

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

1. РАЗРАБОТКА ПРОГРАММ

Ключевым термином данной сферы является «жизненный цикл программного обеспечения» - это промежуток времени от момента принятия решения о необходимости разработки программного продукта до момента его выхода из эксплуатации [1].

Структура жизненного цикла определяется международным стандартом ISO/IEC 12207:1995 «Information Technology – Software Life Cycle Processes». Согласно данному стандарту под процессом понимается совокупность взаимосвязанных действий, направленных на преобразование входных данных в выходные. Характерными чертами процесса являются:

  • поставленные задачи;
  • методы решения задач;
  • исходные данные;
  • результаты работы [9].

Все процессы жизненного цикла можно разделить на три группы (см. рисунок 1):

  • основные процессы:
    • приобретение;
    • поставка;
    • разработка;
    • эксплуатация;
    • сопровождение [2];
  • вспомогательные процессы:
    • документирование;
    • управление конфигурацией;
    • обеспечение качества;
    • верификация;

Основные процессы

Приобретение

Поставка

Разработка

Эксплуатация

Сопровождение

Вспомогательные процессы

Документирование

Управление конфигурацией

Разрешение проблем

Обеспечение качества

Верификация

Аттестация

Совместная оценка

Аудит

Организационные процессы

Управление

Создание инфраструктуры

Усовершенствование

Обучение

Рисунок 1 – Процессы жизненного цикла

  • аттестация;
  • совместная оценка;
  • аудит;
  • разрешение проблем [6];
  • организационные процессы:
    • управление;
    • инфраструктура;
    • усовершенствование;
    • обучение [1].

1.1. Основные процессы

Процесс приобретения включает в себя ряд действий:

  • инициирование приобретения – предполагает формулирование заказчиком своих потребностей, анализ требований, проверку существования документации, подготовку и утверждение плана приобретения программного продукта [2];
  • подготовка заявочных предложений – заявочные предложения отражают общие требования к продукту, а также технические ограничения оборудования;
  • подготовка и корректировка договора – на данном этапе выбирается конкретный поставщик, подготавливается и заключается договор;
  • надзор за деятельностью поставщика – реализуется согласно действий, указанных в аудите;
  • приемка и завершение работ – тестирование программного продукта и передача его заказчику [1].

Процесс поставки содержит следующие действия:

  • инициирование поставки – на данном этапе поставщик рассматривает все предложения;
  • подготовка ответа на заявочные предложения;
  • подготовка договора;
  • планирование – разработка плана управления проектом, отражающего организационную структуру, зоны ответственности, технические требования и т.п.;
  • выполнение и контроль;
  • проверка и оценка;
  • поставка и завершение работ [2].

Процесс разработки – ключевой процесс создания программного продукта. Данный процесс предполагает выполнение следующих действий:

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

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

  • подготовительная работа – планирование работ, требуемых в процессе эксплуатации, установка стандартов эксплуатации, определение процессов тестирования [2];
  • эксплуатационное тестирование – тестирование каждой отдельной версии продукта;
  • эксплуатация системы – проверка эксплуатационных сценариев работы в среде, соответствующей документации;
  • поддержка пользователей – разрешение спорных ситуаций в процессе эксплуатации [1].

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

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

1.2. Вспомогательные процессы

Процесс документирования представляет собой формализованное описание всей созданной информации. Данный процесс состоит из ряда действий:

  • подготовительная работа;
  • проектирование и разработка;
  • издание документации;
  • сопровождение [2].

Процесс управления конфигурацией позволяет организовать и контролировать жизненный цикл программного продукта. К нему относятся:

  • подготовительная работа – планирование процесса;
  • идентификация конфигурации – определение правил, по которым идентифицируются отдельные компоненты продукта [2];
  • контроль за конфигурацией – предполагает систематическую оценку модификаций, а также реализует контроль состояния и развития отдельных компонентов;
  • учет состояния конфигурации – регистрация состояния всех компонентов, а также подготовка отчетов о модификациях;
  • оценка конфигурации – оценка функциональных возможностей продукта, а также соответствия поведения заявленным требованиям;
  • управление выпуском и поставка – копирование продукта и программной документации [1].

Процесс обеспечения качества отвечает за соответствие качества программного продукта установленным требованиям со стороны заказчика. Основные действия данного процесса:

  • подготовительная работа – планирование работ;
  • обеспечение качества продукта – гарантия соответствия функциональных возможностей заявленным требованиям;
  • обеспечение качества процесса – гарантия соответствия процессов жизненного цикла заявленным требованиям;
  • обеспечение прочих показателей качества – реализация условий договора и стандарта качества ISO 9001 [2].

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

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

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

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

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

Процесс разрешения проблем предусматривает анализ проблем и их решение. При этом все проблемы идентифицируются, описываются и решаются [6].

1.3. Организационные процессы

Процесс управления относится к управлению выпуском продукта и управлению проектом. Данный процесс охватывает следующие действия [9]:

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

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

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

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

1.4. Понятие тестирования

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

В настоящее время тестированием называется процесс исполнения программного кода с целью обнаружения ошибок [15].

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

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

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

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

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

  • метод «черного ящика» не позволяет обнаружить взаимоуничтожающиеся ошибки;
  • не все ошибки воспроизводятся стабильно, поэтому они могут быть не выявлены в результате тестирования [10].

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

В таблице 1 приведены показатели эффективности различных методов тестирования [3].

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

Таблица 1 – Показатели эффективности различных методов тестирования

Методика

Минимальная эффективность

Средняя эффективность

Максимальная эффективность

Персональные просмотры проектных документов

15%

35%

70%

Неформальные групповые просмотры

30%

40%

60%

Формальные просмотры проектных документов

35%

55%

75%

Формальные инспекции кода

30%

60%

70%

Моделирование и прототипирование

35%

65%

80%

Проверка за партой

20%

40%

60%

Тестирование модулей

10%

25%

50%

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

20%

35%

55%

Комплексное тестирование

25%

45%

60%

Тестирование в реальных условиях

35%

50%

65%

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

93%

99%

99%

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

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

  • подготовить специальный набор тестов, чтобы обнаружить по возможности максимальное число ошибок. Однако чем дольше продолжается процесс тестирования (и отладки в целом), тем большей становится стоимость программы [17];
  • правильно определить момент окончания отладки. Признаком возможности окончания отладки является полнота охвата, пропущенными через программу, тестами множества различных ситуаций, возникающих при выполнении возможных сценариев, и относительно редкое проявление ошибок на последнем отрезке процесса тестирования. Последнее определяется в соответствии с требуемой степенью надежности, указанной в спецификации его качества [10].

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

  • ручного тестирования;
  • индукции;
  • дедукции;
  • обратного прослеживания.

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

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

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

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

В процессе доказательства пытаются выяснить, все ли проявления ошибки объясняет данная гипотеза, если не все, то либо гипотеза не верна, либо ошибок несколько.

Метод дедукции. По методу дедукции вначале формируют множество причин, которые могли бы вызвать данное проявление ошибки. Затем анализируя причины, исключают те, которые противоречат имеющимся данным. Если все причины исключены, то следует выполнить дополнительное тестирование исследуемого фрагмента. В противном случае наиболее вероятную гипотезу пытаются доказать. Если гипотеза объясняет полученные признаки ошибки, то ошибка найдена, иначе - проверяют следующую причину [12].

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

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

2. ТЕСТИРОВАНИЕ

2.1. Виды тестирования

Принято выделять два основных вида тестирования:

  • тестирование программы как черного ящика;
  • тестирование программы как белого ящика [19].

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

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

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

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

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

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

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

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

Важно понимать, что некоторые подмаршруты участвуют в других более крупных маршрутах. Пример графа передачи управления представлен на рисунке 2 [10].

Рисунок 2 – Граф передачи управления

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

Для того, чтобы определить количество различных маршрутов, нужно посчитать число всевозможных путей из точки А в точку В. Данное количество определяется по формуле 1 [11]:

520 + 519 + … + 51 = 1014 (1)

В данном случае 5 – это количество различных путей внутри цикла. Таким образом, если на разработку одного теста в среднем тратится пять минут, то для построения полного набора тестов понадобится 5*1014 минут, что составляет примерно один миллиард лет.

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

Реальный путь, применяющийся в тестировании большинства прикладных программ – совокупность обеих стратегий тестирования [19].

Понятие тестирования тесно связано с понятием отладки - исправлением ошибок в программном коде. Поэтому первый вопрос, на который должен ответить программист: в каком случае в программе есть ошибка? [11]

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

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

2.2. Тестирование надежности

Известно, что качество программного обеспечения определяется несколькими признаками:

  • функциональные возможности – набор действий, реализующих потребности пользователя;
  • надежность – способность программного продукта сохранять свой уровень качества функционирования при установленных условиях;
  • практичность - определенный набор атрибутов, относящихся к индивидуальной пользовательской оценке;
  • эффективность – соотношение уровня качества функционирования программного продукта и объема потребляемых им ресурсов;
  • сопровождаемость – набор атрибутов, необходимых для процессов модификации продукта;
  • мобильность – способность переносимости продукта [7].

Понятие надежности также является комплексным свойством. Оно включает в себя следующие понятия:

  • безотказность – способность сохранять работоспособное состояние в течение определенного времени;
  • долговечность – способность сохранять работоспособное состояние до предельного состояния;
  • ремонтопригодность – способность приспосабливаться к поддержанию и восстановлению работоспособного состояния путем обслуживания и ремонта;
  • сохраняемость – способность сохранять значения параметров в заданных пределах [5].

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

Для определения надежности программного обеспечения принято использовать следующие свойства:

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

Важно отметить, что за безотказность здесь отвечают свойства стабильности и устойчивости, а восстанавливаемость является лишь возможностью восстановления функциональности после отказа [8].

Для оценки стабильности программного продукта принято использовать следующие характеристики [11]:

  • вероятность безотказной работы – вероятность того, что в пределах заданного промежутка времени не возникнет поломка. Такой промежуток времени называется наработкой на отказ;
  • гамма-процентная наработка до отказа – наработка, в течение которой поломка не возникнет с заданным процентом вероятности;
  • средняя наработка до отказа – математическое ожидание наработки до возникновения поломки;
  • средняя наработка на отказ – отношение суммарной наработки к его математическому ожиданию;
  • интенсивность отказов – условная плотность вероятности поломки, которая определяется при условии, что до рассматриваемого момента времени поломки не было [5];
  • параметр потока отказов – отношение математического ожидания количества поломок за достаточно малый период наработки к значению этой наработки;
  • осредненный параметр потока отказов – отношение математического ожидания количества поломок за конечный промежуток наработки к значению этой наработки.

Существует целый ряд причин возникновения ошибок в программах:

  • процесс проектирования – преобразование и детализация различных представлений. Ошибки могут вноситься на любом из этапов, имея накопительный эффект. Главной причиной здесь является высокая сложность грамотного процесса проектирования программного обеспечения;
  • ошибки, вносимые на этапе кодирования – в большинстве случаев эти ошибки вызваны невнимательностью разработчиков и неправильной трактовкой исходных требований [8].

Всего существует два вида ошибок в программном обеспечении:

  • функциональные – нарушения программной спецификации – несоответствие каким-либо заявленным требованиям. Такие ошибки ведут к ухудшению функциональности (точности и пригодности);
  • нефункциональные – нарушение правил языка программирования, а также некорректное использование библиотечных функций. Такие ошибки являются причинами снижения надежности и ухудшения функциональности. Примеры таких ошибок [11]:
    • ошибки использования неинициализированных указателей;
    • утечки памяти;
    • игнорируемые участки кода;
    • отсутствие инициализации интервальных переменных;
    • выход за границы диапазонов;
    • отсутствие проверки возвращаемых значений и т.п.

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

  • действие программиста, которое приводит к возникновению ошибки – незнание, опечатка, неверное понимание функциональных особенностей;
  • программная ошибка – совокупность конструкций исходного кода, способных привести к некорректным действиям [8];
  • срабатывание ошибки – возникновение таких условий в рамках программного кода, при которых выполняются некорректные действия;
  • проявление ошибки – негативное влияние ошибки на работоспособность программного обеспечения – аварийное завершение, получение некорректных результатов и т.п. [16]

Принято выделять несколько категорий тяжести ошибки в программном обеспечении, нарушение работоспособности которого могут привести к катастрофическим последствиям [7]:

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

Для оценки надежности программных продуктов применяются различные методы:

  • динамические – опираются на результаты выполнения программы. Такие методы позволяют получать абсолютные показатели надежности, однако они характеризуются высокой трудоемкостью сбора исходных данных, используют упрощающие предположения о взаимном влиянии ошибок, а также сильно зависят от качества и объема исходных данных;
  • статические – опираются на анализ различных артефактов, полученных на этапе проектирования. Такие методы характеризуются низкой трудоемкостью, они позволяют выполнять оценку автоматически. Минус данных методов в сложности реализации, а также в том, что они не обеспечивают абсолютных показателей надежности [12];
  • архитектурные – базируются на анализе архитектуры всей системы, могут включать в себя как статические, так и динамические подходы;
  • эмпирические – методы, полученные только на базе информации о процессе проектирования [14].

Все эти методы обладают общими свойствами:

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

2.3. Финишные этапы разработки

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

Цель вносимых изменений бывает разная:

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

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

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

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

С целью защиты интересов разработчиков вводится понятие интеллектуальной собственности – совокупность исключительных прав на результаты творческой деятельности и средства индивидуализации.

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

  • разработчиком;
  • заказчиком;
  • пользователем.

Интеллектуальные права бывают двух видов:

  • авторские права – интеллектуальные права на произведение. Возникают с момента создания и всегда принадлежат гражданам, создавшим произведение. При этом они не зависят от факта регистрации;
  • исключительное право – право пользования результатом интеллектуальной деятельности по личному усмотрению [13].

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

3. ПРАКТИЧЕСКАЯ ЧАСТЬ

3.1. Разработка приложения

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

  • ввод размерности;
  • ввод матрицы;
  • вывод матрицы на экран;
  • поиск максимального и минимального значений.

Исходный код программы выглядит следующим образом:

#include <iostream>

using namespace std;

void main()

{

int m,n,min,max;

int mas[][];

cout<<"m = ";

cin>>m;

cout<<"n = ";

cin>>n;

cout<<"Enter matrix:"<<endl;

for (int i=0; i<m; i++)

for (int j=0; j<n; j++)

cin>>mas[i][j];

min=0; max=0;

for (int i=0; i<m; i++)

for (int j=0; j<n; j++)

{

if (mas[i][j]<min)

min=mas[i][j];

if (mas[i][j]<max)

max=mas[i][j];

}

cout<<"Matrix:"<<endl;

for (int i=0; i<m; i++)

{

for (int j=0; j<n; j++)

cout<<mas[i][j]<<" ";

cout<<endl;

}

cout<<"Max = "<<max<<endl;

cout<<"Min = "<<min<<endl;

system("pause");

}

3.2. Корректность программы

Корректностью программного кода называется степень соответствия исходных программ формализованным правилам языков спецификаций и программирования [7].

В современных средах программирования корректность программы определяется на этапе компиляции.

Компиляция написанной программы в среде разработки Dev-C++ 5.11 происходит с ошибками, представленными на рисунке 3 [8].

Данные сообщения говорят о следующих ошибках:

  • функция main() должна иметь целочисленный тип и возвращаемое значение [19];
  • неверно объявлен двумерный массив.

Рисунок 3 – Проверка корректности программы

Для устранения ошибок компиляции выполняются следующие действия:

  • функции main присвоен тип int;
  • добавлена строка «return 0»;
  • инициализация массива изменена на «int mas[10][10]».

Результат компиляции исправленной программы приведен на рисунке 4 [2].

Рисунок 4 – Результат успешной компиляции

3.3. Тестирование, отладка и анализ

Этап отладки программы неразрывно связан с ее тестированием. Тестирование будет проводиться на трех примерах (см. таблицу 2). Результаты тестов приведены на рисунках 5-7 [11].

Таблица 2 – Тестирование

Тест

Исходные данные

Ожидаемый результат

1

n=3 m=3

1 2 3

4 5 6

7 8 9

1 2 3

4 5 6

7 8 9

min = 1, max = 9

2

n = 3 m = 3

-1 0 3

2 4 5

0 9 1

-1 0 3

2 4 5

0 9 1

min = -1, max = 9

3

n = 3, m = 3

-1 -2 -3

-4 -5 -6

-7 -8 -9

-1 -2 -3

-4 -5 -6

-7 -8 -9

min = -9, max = -1

Рисунок 5 – Результат теста № 1

Рисунок 6 – Результат теста № 2

Рисунок 7 – Результат теста № 3

Как видно из таблицы 2, тесты завершились неуспешно.

В результате анализа исходного кода можно сделать выводы [9, 12]:

  • не стоит инициализировать начальные значения минимума и максимума нулями, т.к. значения, хранящиеся в матрице заранее неизвестны. Следовательно, за исходное значение стоит брать существующий элемент матрицы, например, mas[0][0];
  • при поиске максимума была допущена ошибка в знаке условия. Необходимо изменить «<» на «>».

Исправленный код программы выглядит следующим образом [15]:

#include <iostream>

using namespace std;

int main()

{

int m,n,min,max;

int mas[10][10];

cout<<"m = ";

cin>>m;

cout<<"n = ";

cin>>n;

cout<<"Enter matrix:"<<endl;

for (int i=0; i<m; i++)

for (int j=0; j<n; j++)

cin>>mas[i][j];

min=mas[0][0]; max=mas[0][0];

for (int i=0; i<m; i++)

for (int j=0; j<n; j++)

{

if (mas[i][j]<min)

min=mas[i][j];

if (mas[i][j]>max)

max=mas[i][j];

}

cout<<"Matrix:"<<endl;

for (int i=0; i<m; i++)

{

for (int j=0; j<n; j++)

cout<<mas[i][j]<<" ";

cout<<endl;

}

cout<<"Max = "<<max<<endl;

cout<<"Min = "<<min<<endl;

system("pause");

return 0;

}

Результаты повторного тестирования приведены на рисунках 8-10.

Рисунок 8 – Результат теста № 1

Рисунок 9 – Результат теста № 2

Рисунок 10 – Результат теста № 3

Как видно из рисунков, тестирование прошло успешно.

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

ЗАКЛЮЧЕНИЕ

В рамках выполнения данной работы была раскрыта тема «Тестирование и отладка программ: виды тестирования, тестирование надежности, организация процесса тестирования. Финишные этапы разработки программных систем».

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

  • основные;
  • вспомогательные;
  • организационные.

К основным процессам разработки относятся:

  • приобретение;
  • поставка;
  • разработка;
  • эксплуатация;
  • сопровождение.

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

Вторая глава работы посвящена непосредственно тестированию. Здесь рассмотрены основные виды тестирования:

  • тестирование программы как черного ящика;
  • тестирование программы как белого ящика.

Также уделяется внимание тестированию надежности. Данное понятие определяет следующие свойства программного продукта:

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

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

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

  • разработчиком;
  • заказчиком;
  • пользователем.

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

СПИСОК ИСПОЛЬЗОВАННОЙ ЛИТЕРАТУРЫ

  1. Адигеев М.Г. Жизненный цикл программного обеспечения. – Ростов-на-Дону: ЮФУ, 2013. – 41 с.
  2. Берг Д.Б. Модели жизненного цикла. – Екатеринбург: Изд-во Уральского университета, 2014. – 78 с.
  3. Буздалов Д.В. Практикум по дедуктивной верификации программ. – М.: Изд-во МГУ, 2014. – 100 с.
  4. Вендров А.М. Проектирование программного обеспечения. – М.: Финансы и статистика, 2016. – 544 с.
  5. Гудов А.М. Технология разработки программного обеспечения / А.М. Гудов, С.Ю. Завозкин, С.Н. Трофимов. – Кемерово: КемГУ, 2015. – 138 с.
  6. Гусятников В.Н. Стандартизация и разработка программных систем / В.Н. Гусятников, А.И. Безруков. – М.: Финансы и статистика; ИНФРА-М, 2013. – 288 с.
  7. Дроботун Е.Б. Надежность программного обеспечения. Виды и критичность ошибок. – Тверь: ВАВКО, 2014. – 8 с.
  8. Евсеева О.Н. Отладка и тестирование приложений в среде Visual Studio / О.Н. Евсеева, А.Б. Шамшев. – Ульяновск: УлГТУ, 2014. – 96 с.
  9. Калайда В.Т. Технология разработки программного обеспечения / В.Т. Калайда, В.В. Романенко. – Томск: Томский межвузовский центр дистанционного образования, 2017. – 257 с.
  10. Кропачева М.С. Формальная верификация программ, написанных на функционально-потоковом языке параллельного программирования / М.С. Кропачева, А.И. Легалов. – Новосибирск: Изд-во СФУ, 2012. – 19 с.
  11. Куликов С.А. Тестирование программного обеспечения. – М.: МГТУ, 2014. – 298 с.
  12. Моисеев М.. Формальные методы обеспечения качества ПО. – М.: МГТУ, 2012. – 52 с.
  13. Пацей Н.В. Технология разработки программного обеспечения / Н.В. Пацей, Д.В. Шиман, И.Г. Сухорукова. – Минск: БГТУ, 2014. – 130 с.
  14. Плаксин М.А. Тестирование и отладка программ для профессионалов будущих и настоящих. – М.: БИНОМ, 2015. – 170 с.
  15. Попова Ю.Б. Тестирование и отладка программного обеспечения. – Минск: Изд-во БНТУ, 2013. – 35 с.
  16. Савенко И.И. Технология разработки программного обеспечения. – Томск: Изд-во ТПУ, 2014. – 67 с.
  17. Соловьев С.В. Технология разработки прикладного программного обеспечения / С.В. Соловьев, Л.С. Гринкруг, Р.И. Цой. – М.: БИНОМ, 2012. – 321 с.
  18. Соммервилл И. Инженерия программного обеспечения. – М.: «Вильямс», 2012. – 624 с.
  19. Степанченко И.В. Методы тестирования программного обеспечения. – Волгоград: ВолгГТУ, 2016. – 74 с.
  20. Якунин Ю.Ю. Технологии разработки программного обеспечения. – Красноярск: ИПК СФУ, 2013. – 225 с.