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

Отладка и тестирование программ: основные подходы и ограничени

Содержание:

Введение

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

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

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

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

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

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

Предмет исследования - виды тестирования, основные подходы и ограничения.

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

В соответствии с целью, задачами исследования являются:

  1. Определение понятий “тестирование” и “отладка” и рассмотреть этапы развития;
  2. Исследование видов тестирования;
  3. Изучение методов отладки и виды ошибок;
  4. Анализирование методов тестирования и отладки;
  5. Практическое применение изученного материала на основе информационной системы.

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

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

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

  1. Сущность тестирования и отладки. Методика выявления ошибок

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

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

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

Классическими моделями разработки ПО являются:

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

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

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

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

  1. Спиральная - частный случай итерационной инкрементальной модели, в которой особое внимание уделяется управлению рисками, особенно влияющим на организацию процесса разработки проекта и контрольные точки.
    Отличительной особенностью данной модели является специальное внимание рискам, влияющим на организацию жизненного цикла. Главная задача - как можно быстрее показать пользователям системы работоспособный продукт, тем самым активизируя процесс уточнения и дополнения требований. Основная проблема спирального цикла - определение момента перехода на следующий этап. Для ее решения необходимо ввести временные ограничения на каждый из этапов жизненного цикла.
  2. Гибкая - термин для целого ряда подходов и практик, основанных на ценностях Манифеста гибкой разработки программного обеспечения и 12 принципах, лежащих в его основе.
    Манифест гибкой разработки программного обеспечения - основной документ, содержащий описание ценностей и принципов гибкой разработки программного обеспечения, разработанный в феврале 2001 года на встрече 17 независимых практиков нескольких методик программирования, именующих себя «Agile Allance».

К гибким методологиям, чаще всего, относят экстремальное программирование, DSDM, Scrum, FDD, BDD и др. Применяется как эффективная практика организации труда небольших групп в объединении с управлением ими комбинированным методом.

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

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

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

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

  • 1950-1960 гг. - процесс тестирования был предельно формализован, отделен от процесса непосредственной разработки программного обеспечения. На тот момент, тестирование представляло собой скорее отладку программ.
    Существовала концепция «исчерпывающего тестирования» - для проверки всех возможных путей выполнения кода со всеми возможными входными данными. Но очень скоро было выяснено, что применение данной концепции невозможно, так как количество возможных путей и входных данных очень велико, и при таком подходе сложно найти проблемы в документации.
  • 1970-е годы - появились две фундаментальные идеи тестирования:
    1) тестирование рассматривалось как процесс доказательства работоспособности программы в определенных условиях;
    2) тестирование рассматривалось как процесс доказательства неработоспособности программы в определенных условиях.
    Противоречия идей тестирования не только не исчезло со временем, но и в настоящее время отмечается многими авторами как две взаимодополняющие цели тестирования.
    В связи с этим, процесс тестирования строился на двух главных задачах: удостовериться, что программа соответствует требованиям; определить условия, при которых программа ведет себя некорректно.
  • 1980-е годы - ключевое изменение места тестирования в разработке программного обеспечения. Вместо одной из финальных стадий создания проекта тестирование стало применяться на протяжении всего цикла разработки, что позволило в очень многих случаях не только быстро обнаруживать и устранять проблемы, но даже предсказывать и предотвращать их появление.
    На данном этапе также было отмечено бурное развитие и формализация методологий тестирования и появление первых элементарных попыток автоматизировать тестирование.
  • 1990-е годы - смена методики разработки, при которой качество программ проверяется не в конце, а постоянно в процессе разработки. При таком развитии, тестирование становится основной частью любого процесса разработки программы. Но, с другой стороны, требования к квалификации инженера тестирования становятся более высокие: в его ответственность попадает не только функциональное тестирование, но и организация процесса разработки. Поэтому наилучшей кандидатурой становится довольно опытный программист в команде.
  • 2000-е годы - развитие тестирования продолжалось и характеризовалось поиском новых путей, методологий, техник и подходов к обеспечению качества. Особое внимание уделялось при появлении гибких методов разработки и таких подходов, как «разработка под управлением тестированием». Автоматизация тестирования стала восприниматься как обязательная часть большинства проектов, а также стали актуальны идеи о том, что в основание процесса тестирования необходимо ставить не соответствие программы требованиям, а ее способность предоставить конечному пользователю возможность эффективно решать задачи.
  • Современный этап характеризуется активным применением различных гибких методологий, интеграции с процессом разработки, широкого использования автоматизации, а также выбор технологий и инструментальных средств при разработке.
    1. Виды тестирования

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

Тестирование можно квалифицировать:

  • по запуску кода на исполнение:
  1. Статическое тестирование - проводится без запуска программного кода продукта; осуществляется путем анализа программного кода или скомпилированного кода. Анализ может производиться как вручную, так и с помощью специальных инструментальных средств.
  2. Динамическое тестирование - проводится с запуском программного кода продукта.
  • По степени автоматизации
  1. Ручное тестирование - проводится тестировщиком без использования программных средств, для проверки программы или сайта путем моделирования действий пользователя.
  2. Автоматизированное тестирование - включает проведение основных функций (запуск, инициализация, выполнение, анализ и выдача результата) и шаги теста, автоматически посредством специализированных инструментов.
  • По уровню детализации приложения:
  1. Модульное тестирование - проверка на корректность отдельных модулей исходного кода программы, набора из одного или более программных модулей вместе с соответствующими управляющими данными, процедурами использования и обработки. Главная идея - писать тесты для каждой нетривиальной функции или метода.
  2. Интеграционное тестирование - проверка интеграции модулей, их взаимодействие между собой, а также интеграция подсистем в одну общую систему. Для проведения используются компоненты уже проверенные с помощью модульного тестирования, которые группируются в множества.
  3. Системное тестирование - проверка как функциональных, так и не функциональных требований в системе в целом; при этом выявляются дефекты.
  • По степени важности тестируемых функций
  1. Дымовое тестирование - проверка работоспособности основных функций путем поверхностного тестирования наиболее важных модулей приложения на предмет возможности выполнения требуемых задач и наличия критических и блокирующих дефектов.
  2. Тестирование критического пути - проверка функциональности, используемой типичными пользователями в типичной повседневной деятельности.
  3. Расширенное тестирование - проверка всей функциональности, заявленной в требованиях.
  • По принципам работы с приложением
  1. позитивное тестирование - все действия с приложением выполняются строго по инструкции без никаких недопустимых действий, некорректных данных и т.д.
  2. Негативное тестирование - в работе с приложением выполняются некорректные операции и используются данные, потенциально приводящие в ошибкам.
    1. Сущность и методика отладки программ. Виды ошибок

Отладка программ заключается в проверке правильности работы программы и аппаратуры [3].

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

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

Для отладки программы можно воспользоваться одним из методов:

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

Для отладки программ обычно применяют три способа:

  1. Пошаговая отладка программ с заходом в подпрограммы;
  2. Пошаговая отладка программ с выполнением подпрограммы как одного оператора;
  3. Выполнение программы до точки останова.

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

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

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

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

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

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

В свою очередь, весь спектр возможных ошибок в программных продуктах можно условно разделить на три категории [4]:

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

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

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

  1. Стратегия тестирования и отладки

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

На данный момент, существует две основные стратегии тестирования:

  • «черного ящика», при котором программа рассматривается как объект, внутрення структура которого неизвестна;
  • «прозрачного (белого) ящика» предусматривает знание исходного кода программы и полный доступ к нему.

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

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

Основными методами тестирования ПО являются:

  1. Метод Сандвича
  2. Метод «белого ящика»
  3. Метод «черного ящика»
  4. Метод отладки программ

Перейдем подробнее к изучению методов тестирования.

    1. Метод Сандвича

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

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

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

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

    1. Метод «белого ящика»

Термин "белый ящик" означает, что при разработке тестовых случаев тестировщики используют любые доступные сведения о внутренней структуре или коде. Технологии, применяемые во время тестирования "белого ящика" [5], обычно называют технологиями статического тестирования.

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

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

1. Дают гарантию того, что все независимые пути в модуле проверены по крайней мере один раз.

2. Проверяют все логические решения на предмет того, истины они или ложны.

3. Выполняют все циклы внутри операционных границ и с использованием граничных значений.

4. Исследуют структуры внутренних данных с целыо проверки их достоверности.

Тестирование посредством белого ящика [6], как правило, включает в себя стратегию модульного тестирования, при котором тестирование ведется на модульном или функциональном уровне и работы по тестированию направлены на исследование внутреннего устройства модуля. Данный тип тестирования называют также модульным тестированием, тестированием прозрачного ящика (clear box) или прозрачным (translucent) тестированием, поскольку сотрудники, проводящие тестирование, имеют доступ к программному коду и могут видеть работу программы изнутри. Данный подход к тестированию известен также как структурный подход.

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

Методы тестирования на основе стратегии белого ящика:

  • Ввод неверных значений

При вводе неверных значений тестировщик заставляет коды возврата показывать ошибки и смотрит на реакцию кода. Это хороший способ моделирования определенных событий, например переполнения диска, нехватки памяти и т.д. Популярным методом является замена alloc() функцией, которая возвращает значение NULL в 10% случаев с целью выяснения, сколько сбоев будет в результате. Такой подход еще называют тестированием ошибочных входных данных. При таком тестировании проверяется обработка как верных, так и неверных входных данных. Тестировщики могут выбрать значения, которые проверяют диапазон входных/выходных параметров, а также значения, выходящие за границу диапазона.

  • Модульное тестирование

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

  • Тестирование обработки ошибок

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

  • Утечка памяти

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

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

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

  • Тестирование цепочек

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

  • Исследование покрытия

При выборе инструмента для исследования покрытия важно, чтобы группа тестирования проанализировала тип покрытия, необходимый для приложения. Исследование покрытия можно провести с помощью различных технологий. Метод покрытия операторов часто называют С1, что также означает покрытие узлов. Эти измерения показывают, был ли проверен каждый исполняемый оператор. Данный метод тестирования обычно использует программу протоколирования (profiler) производительности.

  • Покрытие решений

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

  • Покрытие условий

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

    1. Метод «черного ящика»

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

Согласно ISTQB (Международный совет по тестированию программного обеспечения) [8]:

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

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

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

Пример:

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

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

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

Техники тест-дизайна, основанные на использования черного ящика, включают:

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

Преимущества:

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

Недостатки:

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

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

  • Отладочный вывод;
  • Интегрированные средства отладки;
  • Независимые отладчики.

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

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

Интегрированные средства отладки позволяют:

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

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

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

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

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

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

  1. Практическое применение на основе информационной системы

Для проведения тестирования и отладки была выбрана разработанная программа для шифрования/дешифрования текстовых файлов, написанная на языке программирования C# (рисунок 1).

Рисунок 1 - Форма программы шифрования/дешифрования

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

Рисунок 2 - Результат шифрования/дешифрования текстовых документов

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

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

Целью отладки является анализ причины появления ошибки и устранение ее на этапе разработки.

Процесс тестирования разделен на этапы:

  1. Проектирование тестов - разработка стратегии тестирования, разработка планов тестирования, разработка и документирование тестовых кейсов;
  2. Выполнение тестового цикла - анализ спецификаций и кода, кодирование и прогон тестовых кейсов;
  3. Улучшение тестирования программного обеспечения [11] - проведение исследований по результатам выполненного тестирования с получением информации по покрытию тестовыми кейсами исходного коа или функциональности программы; разработка рекомендаций по улучшению тестирования;
  4. Улучшение качества программного продукта - выдача рекомендаций по улучшению программного обеспечения в целом или с целью соответствия поставленным требованиям и задачам;
  5. Оптимизация тестирования программного обеспечения [10] - разработка программ, позволяющих в автоматическом режиме обрабатывать исходные коды и делать необходимые заключения по качеству.
    1. Отладка программы

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

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

  • Точки останова на конкретных строчках кода
  • Остановка при изменении переменных
  • Остановка при присваивании конкретного значения
  • Прохождение кода строчка за строчкой
  • Откат по программе и т.д.

В разработанной программе была рассмотрена отладка с применением точки останова:

  1. Случай 1: проверка зашифрованного текста (рисунок 3). Устанавливается точка останова на переменную, которой назначается хранение зашифрованного текста.

Рисунок 3 - Проверка зашифрованного текста

  1. Случай 2: проверка расшифрованного текста (рисунок 4). Устанавливается точка останова на переменную, которой назначается хранение расшифрованного текста.

Рисунок 4 - Проверка расшифрованного текста

    1. Тестирование программного продукта

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

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

Процесс тестирования проводится на основе рассмотренных ранее этапов:

  1. Проектирование тестов:
    1. Разработка стратегии тестирования. В связи с тем, что функционал программы ограничен всего на несколько методов, был сделан выбор проведения модульного тестирования. Данный метод удобен, так как позволяет делать проверку с каждым модулем (методом) разрабатываемой программы.
    2. Тест план:
  2. Объект тестирования - программа по шифрованию/дешифрованию текстовых файлов.
  3. Методы и функции, которые выполняют основные операции программы.
  4. Используемый метод тестирования - модульный.
  5. Подготовка (разработка макета программы) - Написание тестов - анализ результатов.
  6. Тестирование функционала работы модуля в отдельности.
    1. Тест кейс: Разработка тестов под функции
  7. создать методы которые выполняют шифрование и дешифрование;
  8. Написать тест по проверке предыдущей операции, насколько качественно выполняется задача;

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

  1. Выполнение тестового цикла. Тестирование выполнено с помощью среды разработки Visual Studio на основе шаблона Unit-тест. Для тестирования был создан тестовый драйвер UnitTest1, в котором реализована вся функциональность тестов:
    1. Тест 1: Тестирование методов Encrypt и Decrypt класса Form1
      Описание тестового случая: проверка шифрования данных, и работа обратной работы алгоритма, с сравнением полученных значений.
      Начальные условия: указана строковая переменная, которая содержит данные. Проведение алгоритма работы двух методов на основе данных в переменной.
      Ожидаемый результат: полученная переменная должна быть равной указанным данным.
      Полученный результат: тест выполнен успешно (рисунок 3).

Рисунок 3 - Тесты выполнены успешно

    1. Тест 2: Тестирование класса исключения KeyException
      Описание тестового случая: проверка методов при нулевом значении переменной «Ключа».
      Начальные условия: «Ключ» пустой.
      Ожидаемый результат: Оповещение пользователя об ошибке.
      Полученный результат: тест выполнен успешно (рисунок 3).
    2. Тест 3: Тестирование класса исключения TextException
      Описание тестового случая: проверка методов при нулевом значении переменной «Данные».
      Начальные условия: «Данные» пустой.
      Ожидаемый результат: Оповещение пользователя об ошибке.
      Полученный результат: тест выполнен успешно (рисунок 3).

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

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

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

Заключение

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

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

Практическая значимость полученных результатов:

  • Определение понятий “тестирование” и “отладка” и рассмотреть этапы развития;
  • Исследование видов тестирования;
  • Изучение методов отладки и виды ошибок;
  • Анализирование методов тестирования и отладки;
  • Практическое применение изученного материала на основе информационной системы.

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

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

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

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

Библиография

  1. Тестирование программного обеспечения, фундаментальные концепции менеджмента бизнес-приложений / Канер Сэм и др.; Под ред. Ю. Н. Артеменко; ДиСофт, 2001.
  2. Программное обеспечение и его разработка / Дж. Фокс; - Мир, 1985. - С. 179-295.
  3. Индивидуальная отладка программ / Ю.М. Безбородов; - Наука, 1982. - С. 9-79.
  4. Тестирование программ / В.В. Липаев; - Радио и связь, 1986. - С. 15-47.
  5. Введение в технологию программирования (конспект лекций) / Е. А. Жоголев; - ДИАЛОГ-МГУ, 1994.
  6. Индивидуальная отладка программ / Ю. М. Безбородов; - Наука, 1982. - С. 9-79.
  7. Стиль, разработка, эффективность, отладка и испытание программ / Д. Ван Тассел; - Мир, 1985. - С. 179-295.
  8. Тестирование программного обеспечения (Базовый курс / 2-е издание) / С. С. Куликов; - Четыре четверти, 2017. - 312 с.
  9. Тестирование программного обеспечения. Фундаментальные концепции менеджмента бизнес-приложения / Канер Сэм и др.; - ДиаСофт, 2001. - 544 с.
  10. Управление качеством разработки программного обеспечения / Учебно-методическое пособие; - С-ПГУИТМО.
  11. Тестирование и отладка программного обеспечения. Методические указания для выполнения контрольной работы / Ю. Б. Попова.

Приложение А. Листинг программы по шифрованию файлов

using System;

using System.Text;

using System.Windows.Forms;

using System.IO;

using System.Security.Cryptography;

namespace FileEncryption

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void buttonFile_Click(object sender, EventArgs e)

{

openFileDialog1.FileName = null;

if (openFileDialog1.ShowDialog() == DialogResult.Cancel)

return;

textBoxFile.Text = openFileDialog1.FileName;

}

public static string Encrypt(string text, string key)

{

if (key.Length == 0)

throw new KeyException();

if (text.Length == 0)

throw new TextException();

TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider();

MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();

byte[] keyToByte = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(key));

byte[] textToByte = Encoding.UTF8.GetBytes(text);

provider.Key = keyToByte;

provider.Mode = CipherMode.ECB;

string encrypted = Convert.ToBase64String(provider.CreateEncryptor().TransformFinalBlock(textToByte, 0, textToByte.Length));

return encrypted;

}

public static string Decrypt(string encryptedText, string key)

{

if (key.Length == 0)

throw new KeyException();

if (encryptedText.Length == 0)

throw new TextException();

TripleDESCryptoServiceProvider provider = new TripleDESCryptoServiceProvider();

MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();

byte[] keyToByte = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(key));

byte[] textToByte = Convert.FromBase64String(encryptedText);

provider.Key = keyToByte;

provider.Mode = CipherMode.ECB;

string decryptText = Encoding.UTF8.GetString(provider.CreateDecryptor().TransformFinalBlock(textToByte, 0, textToByte.Length));

return decryptText;

}

public void EncryptFile()

{

try

{

try

{

string s = File.ReadAllText(textBoxFile.Text);

string FileText = Encrypt(s, textBoxKey.Text);

StreamWriter sw = new StreamWriter(textBoxFile.Text);

sw.WriteLine(FileText);

sw.Close();

timer1.Start();

}

catch (KeyException ex)

{

MessageBox.Show(ex.Message);

}

}

catch(TextException e)

{

MessageBox.Show(e.Message);

}

}

public void DecryptFile()

{

try

{

try

{

string s = File.ReadAllText(textBoxFile.Text);

string FileText = Decrypt(s, textBoxKey.Text);

StreamWriter sw = new StreamWriter(textBoxFile.Text);

sw.WriteLine(FileText);

sw.Close();

timer1.Start();

}

catch (KeyException ex)

{

MessageBox.Show(ex.Message);

}

}

catch (TextException e)

{

MessageBox.Show(e.Message);

}

}

private void buttonStart_Click(object sender, EventArgs e)

{

progressBar1.Value = 0;

if (radioButtonEncrypt.Checked == true)

{

EncryptFile();

}

else

{

DecryptFile();

}

}

private void timer1_Tick(object sender, EventArgs e)

{

if(progressBar1.Value == 100)

{

timer1.Stop();

}

else

{

progressBar1.Value = progressBar1.Value + 10;

}

}

private void buttonCancel_Click(object sender, EventArgs e)

{

if (textBoxFile.Text == "")

{

this.Close();

}

else

{

timer1.Stop();

progressBar1.Value = 0;

if (radioButtonEncrypt.Checked == true)

{

DecryptFile();

}

else

{

EncryptFile();

}

}

}

}

[Serializable]

public class KeyException:Exception

{

public KeyException() : base("Поле Ключ пустое. Введите ключ.") { }

}

[Serializable]

public class TextException : Exception

{

public TextException() : base("Файл не найден. Добавьте файл.") { }

}

}

Приложение B. Листинг тестового проекта

using Microsoft.VisualStudio.TestTools.UnitTesting;

using FileEncryption;

namespace UnitTest

{

[TestClass]

public class UnitTestEncryptor

{

[TestMethod]

public void TestMethodEncryptText()//проверка шифрования данных

{

string key = "5421";

string text = "Дорогие друзья, консультация с профессионалами из IT обеспечивает актуальность экономической...";

string encryptText = Form1.Encrypt(text, key);

string decryptText = Form1.Decrypt(encryptText, key);

Assert.AreEqual<string>(text, decryptText);

}

[TestMethod]

[ExpectedException(typeof(KeyException), "Поле Ключ пустое. Введите ключ.")]

public void TestMethodKeyCheck() => Form1.Encrypt("text", "");

[TestMethod]

[ExpectedException(typeof(TextException), "Файл не найден. Добавьте файл.")]

public void TestMethodTextCheck() => Form1.Encrypt("", "5421");

}

}