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

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

Содержание:

ВВЕДЕНИЕ

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

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

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

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

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

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

1. ПОНЯТИЕ ТЕСТИРОВАНИЯ И ОТЛАДКИ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

1.1 Принципы тестирование и отладка программного обеспечения 

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

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

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

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

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

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

Сформулируем основной вывод:

  • Если ваша цель — доказать отсутствие ошибок, то вы их найдете не слишком много.
  • Если же ваша цель — доказать наличие ошибок, вы обязательно найдете значительную их часть.

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

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

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

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

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

Есть ещё причина, из-за которой тяжело говорить о тестировании — это тот факт, что о нем известно очень мало. Допустим, сегодня мы имеем 20% тех знании о конструировании и фактически, о программировании (кодировании), то о тестировании нам известно менее 5%.

1.2 Основные понятия

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

Тестирование (testing), как мы уже выяснили,—процесс выполнения программы с намерением найти ошибки.

Доказательство (proof) — попытка найти ошибки в программе безотносительно к внешней для программы среде. Большинство методов доказательства предполагает формулировку утверждений о поведении программы и затем вывод и доказательство математических теорем о правильности программы.

Контроль (verification) — попытка найти ошибки, выполняя программу в тестовой, или моделируемой, среде.

Испытание (validation) — попытка найти ошибки, выполняя программу в заданной реальной среде.

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

Отладка (debugging) не является разновидностью тестирования.

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

Тестирование сопряжении — контроль сопряжении между частями системы.

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

Комплексное тестирование — контроль и/или испытание системы по отношению к исходным целям.

Тестирование приемлемости — проверка соответствия программы требованиям пользователя.

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

1.3 Классификация видов тестирования

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

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

Состав и содержание документации, сопутствующей процессу тестирования, определяется зарубежным стандартом IEEE 829-2008 Standard for Software Test Documentation.

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

  1. По объекту тестирования
  • Функциональное тестирование
  • Нагрузочное тестирование
  • Тестирование удобства использования
  • Тестирование интерфейса пользователя
  • Тестирование безопасности
  • Тестирование локализации
  • Тестирование совместимости
  1. По знаниям о тестируемой системе
  • Тестирование методом «черного ящика»
  • Тестирование методом «белого ящика»
  • Тестирование методом «серого ящика»
  1. По уровню автоматизации
  • Ручное тестирование
  • Автоматизированное тестирование
  1. По степени изолированности
  • Модульное тестирование
  • Интеграционное тестирование
  • Системное тестирование
  1. По уровню готовности
  • Альфа-тестирование
  • Бета-тестирование
  • Приемосдаточные испытания

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

Функциональное тестирование проводится для проверки выполнения системой функциональных требований.

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

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

  • Время отклика
  • Число операций, выполняемых в единицу времени

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

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

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

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

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

В ходе тестирования безопасности производится проверка на уязвимость к атакам. Тестирование безопасности проверяет систему на попытки взлома и обхода. Во время тестирования безопасности проверяются следующие аспекты безопасности системы:

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

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

В процессе тестирования локализации проверяются различные аспекты, связанные с региональными особенностями (Языковые данные, системное время, дата и т.д.).

Тестирование совместимости - проверка совместимости системы с различными вариантами программно-аппаратного окружения.

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

Отмечают три уровня тестирования: модульное, интеграционное и системное.

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

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

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

В большей части известных ЯП высокого уровня существуют инструменты и библиотеки модульного тестирования (например, NUnit, JUnit, CppUnit).

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

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

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

1.6 Этапы тестирования программного обеспечения 

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

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

Существуют разные подходы к построению стратегии тестирования:

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

Определение масштаб тестовых работ

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

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

Тестировать в первую очередь запросы с наивысшим приоритетом.

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

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

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

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

Определение подхода к тестированию

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

Стадия системного проектирования

Стадия формулирования требований

Системные испытания

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

Регрессионное тестирование

Приемочные испытания

Определение критериев тестирования и точек контроля качества

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

Существует пять типов критериев, которые могут определяться перед началом системного тестирования:

Критерий выхода. Описывает то, что вы считается необходимым для завершения испытаний.

Критерий входа. Описывает, что нужно сделать перед началом тестирования.

Критерий успешного/неудачного прохождения теста. Прогон каждого теста должен давать заранее известные результаты.

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

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

Установление стратегии автоматизации.

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

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

1.7 Цели и задачи тестирования программного обеспечения

Цели тестирования:

Увеличить вероятность того, что приложение, предназначенное для тестирования, работать будет правильно при всех обстоятельствах.

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

Задачи тестирования:

Проверить, что данная система работает в соответствии с определенными временами отклика сервера и клиента.

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

Проконтролировать работу пользовательских интерфейсов

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

При конструировании тестов свести к минимуму переработку тестов при вероятных изменениях приложения.

Пускать в дело инструменты автоматизированного тестирования там, где это рационально.

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

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

1.8 Комплексное тестирование программного обеспечения

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

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

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

1.9 Восходящее и нисходящее тестирование

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

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

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

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

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

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

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

Трудно организовать исправление ошибок. Если программу пишут несколько программистов (в крупных проектах именно так и работают), и при этом никто не знает, в каком модуле ошибка, кто её найдёт и исправит? Первый разработчик переведёт стрелки на второго, тот проверит свой код и в случае, если всё хорошо, переведёт стрелки обратно на первого, а в результате будет сильно страдать скорость разработки.

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

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

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

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

2. СТРАТЕГИЯ ТЕСТИРОВАНИЯ И ОТЛАДКИ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

2.1 Метод Сандвича

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Исчерпывающее тестирование входных данных обычно неосуществимо. Именно поэтому следует проводить тестирование с использованием подмножества входных данных.

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

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

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

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

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

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

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

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

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

2.4 Методы отладки программного обеспечения

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

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

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

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

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

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

ЗАКЛЮЧЕНИЕ

Невозможно гарантировать отсутствие ошибок в нетривиальной программе; в лучшем случае можно попытаться показать наличие ошибок. Если программа правильно ведет себя для солидного набора тестов, нет оснований утверждать, что в ней нет ошибок; со всей определённостью можно лишь утверждать, что не известно, когда эта программа не работает. Конечно, если есть причины считать данный набор тестов способным с большой вероятностью обнаружить все возможные ошибки, то можно говорить o некотором уровне уверенности в правильности программы, устанавливаемом этими тестами. Надёжность невозможно внести в программу в результате тестирования, она определяется правильностью этапов проектирования. Наилучшее решение проблемы надёжности - с самого начала не допускать ошибок в программе. Однако вероятность того, что удастся безупречно спроектировать большую программа, бесконечно мала.

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

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

БИБЛИОГРАФИЯ:

1.Бейзер Б. Тестирование черного ящика. Технологии функционального тестирования программного обеспечения и систем [текст] / Б. Бейзер; - Питер, 2004, 320 с. ISBN 5-94723-698-2.

2.Брауде Э.Д. Технология разработки программного обеспечения [текст] / Э.Д. Брауде; - Питер, 2004, 656 с. ISBN 5-94723-663-X.

3.Винниченко И.В. Автоматизация процессов тестирования [текст] / И. В. Винниченко; - Питер, 2005, 208 с. ISBN 5-469-00798-7.

4.Канер С. Тестирование программного обеспечения. Фундаментальные концепции менеджмента бизнес-приложений [текст] / С. Канер; - ДиаСофт, 2001, 544 с, ISBN 966-7393-87-9.

5.Калбертсон Р. Быстрое тестирование [текст] / Р. Калбертсон, К. Браун, Г. Кобб; - Вильямс, 2002, 384 с. ISBN 5-8459-0336-X.

6.Коликова Т.В. Основы тестирования программного обеспечения. Учебное пособие [текст] / Т.В. Коликова, В.П. Котляров; - Интуит, 2006, - 285 с. ISBN 5-85582-186-2.

7.Касперски К. Техника отладки программ без исходных текстов [текст] / К. Касперски; - БХВ-Петербург, 2005, 832 с. ISBN 5-94157-229-8.

8.Макгрегор Д. Тестирование объектно-ориентированного программного обеспечения. Практическое пособие [текст] / Д. Макгрегор, Д. Сайкс; - ТИД «ДС», 2004, 432 с. ISBN 966-7992-12-8.

9.Плаксин М. Тестирование и отладка программ - для профессионалов будущих и настоящих [текст] / М. Пласкин; - Бином. Лаборатория знаний, 2007, - 168 с. ISBN 978-5-94774-458-3.

10.Роберт М. Быстрая разработка программ: принципы, примеры, практика [текст] / М. Роберт, Д. Ньюкирк; - Вильямс, 2004, 752 с. ISBN 5-8459-0558-3.

11.Фолк Д. Тестирование программного обеспечения [текст] / Д. Фолк, Е. К. Нгуен, С. Канер; - Диасофт, 2003 , 400 с. ISBN 966-7393-87-9.

12.Элфрид Д. Автоматизированное тестирование программного обеспечения. Внедрение, управление и эксплуатация [текст] / Элфрид Д., Джефф Р., Джон П.;- Лори, 2003, ISBN 5-85582-186-2.