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

  • pdf
  • 26.09.2022
Публикация на сайте для учителей

Публикация педагогических разработок

Бесплатное участие. Свидетельство автора сразу.
Мгновенные 10 документов в портфолио.

Иконка файла материала Раздел 4.pdf

3.11 Какие методы проектирования ПО используются при нисходящем подходе? 

3.12. Чем характеризуется иерархическая структура программной системы?

3.13. Перечислите основные принципы структурного подхода разработки ПО.

3.14. Как осуществляются анализ требований и определение спецификаций при структурном подходе (диаграммы DFD, ERD, STD, SADT)?

3.15. Какие вспомогательные средства проектирования ПО используются при структурном подходе (функциональная схема, схемы Джексона)?

3.16. Перечислите основные принципы объектно-ориентированного представления программных систем (абстрагирование, инкапсуляция, модульность, иерархическая организация).

3.17. Дайте общую характеристику объектов. 

3.18. Какие виды отношений могут быть между объектами?

3.19. Что такое класс? Какие виды отношений могут быть между классами?

3.20. Что такое архитектура ПО?

3.21. Что такое UML?

3.22. Какие виды отношений используются в UML?

3.23. Охарактеризуйте диаграмму классов.

3.24. Охарактеризуйте диаграмму объектов (пакетов).

3.25. Охарактеризуйте диаграмму Use Case (диаграмма прецедентов или вариантов использования).

3.26. Охарактеризуйте диаграмму последовательности.

3.27. Охарактеризуйте диаграмму сотрудничества (кооперации).

3.28. Охарактеризуйте диаграмму UML: диаграмма состояний.

3.29. Охарактеризуйте диаграмму деятельности.

3.30. Охарактеризуйте диаграмму компонентов.

3.31. Охарактеризуйте диаграмму размещения (развертывания).

4. ОТЛАДКА И ТЕСТИРОВАНИЕ 

ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

4.1. Оценка стоимости и причины ошибок  в программном обеспечении

Ряд компаний по разработке ПО провели исследование оценки стоимости ошибок, возникающих на разных этапах создания программ. Каждая фирма действовала независимо, но результаты получены примерно одинаковые: если стоимость усилий, необходимых для обнаружения и устранения ошибок на стадии написания кода, принять за единицу, то стоимость выявления и устранения ошибки на стадии выработки требований будет в 5–10 раз меньше, а стоимость обнаружения и устранения ошибки на стадии сопровождения — в 20 раз больше (рис. 4.1). 

 

Рис. 4.1

Оценка стоимости ошибок на разных этапах создания ПО

В зависимости от того, где и когда при работе над проектом разработки программного приложения был обнаружен дефект, цена его может разниться в 50–100 раз. Причина состоит в том, что для его исправления придется затратить средства на некоторые (или все) нижеперечисленные действия: 

   повторная спецификация; 

   повторное проектирование; 

   повторное кодирование; 

   повторное тестирование; 

   внесение исправлений (выявить и устранить все неточности и ошибки); 

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

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

   выплаты по гарантийным обязательствам; 

   затраты на обслуживание (установка новой версии); 

   создание документации. 

Источники ошибок в программных средствах

Э. Дейкстра выделяет три интеллектуальные возможности человека, используемые при разработке ПС:

      способность к перебору; 

      способность к абстракции;

      способность к математической индукции.

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

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

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

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

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

Для понимания природы ошибок рассмотрим модель, изображенную на рисунке 4.2. На ней человек осуществляет перевод информации из представления A в представление B. 

 

Рис. 4.2

Модель перевода

При этом он совершает четыре основных шага перевода:

                получает информацию, содержащуюся в представлении A, с помощью своего читающего механизма R;

                анализирует и запоминает полученную информацию в своей памяти M;

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

                с помощью этого механизма он фиксирует представление B.

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

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

                сужение пространства перебора (упрощение создаваемых систем);

                обеспечение требуемого уровня подготовки разработчика (это функции менеджеров коллектива разработчиков); 

                обеспечение однозначности интерпретации представления информации;

                контроль правильности перевода (включая и контроль однозначности интерпретации).

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

                технологические, включающие возможности описания задачи, ее решения;

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

                психологические, включающие желание сотрудничать, распределение ролей, микроклимат в коллективе;

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

 4.2. Основные понятия отладки и тестирования ПО

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

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

Отладка = Тестирование + Поиск ошибок + Редактирование.

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

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

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

                свой набор исходных данных и условий для запуска программы;

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

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

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

Тестирование обеспечивает: 

                обнаружение ошибок;

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

                отображение надежности как индикатора качества программы. 

Тем не менее тестирование не может показать отсутствие дефектов (оно может показывать только присутствие дефектов). Информационные потоки процесса тестирования показаны на рисунке 4.3.

На входе процесса тестирования три потока: 

                текст программы;

                исходные данные для запуска программы; 

                ожидаемые результаты.

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

 

Рис. 4.3

Информационные потоки процесса тестирования

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

качество и надежность ПО удовлетворительны; тесты не способны обнаруживать серьезные ошибки.

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

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

4.3. Тестирование интеграции

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

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

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

Тесты проводятся для обнаружения ошибок интерфейса. Некоторые категории ошибок интерфейса:

   потеря данных при прохождении через интерфейс;

   отсутствие в модуле необходимой ссылки;

   неблагоприятное влияние одного модуля на другой;

   подфункции при объединении не образуют требуемую главную функцию;

   отдельные (допустимые) неточности при интеграции выходят за допустимый уровень;

   проблемы при работе с глобальными структурами данных.

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

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

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

   монолитный, характеризующийся одновременным объединением всех модулей в тестируемый комплекс; 

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

   «сверху вниз» и соответствующее ему восходящее тестирование;  «снизу вверх» и соответствующее ему нисходящее тестирование. 

Особенностью монолитного тестирования является необходимость разрабатывать драйверы (test driver) и/или заглушки (stub), замещающие отсутствующие модули нижних уровней. 

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

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

Нисходящее тестирование интеграции

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

Рассмотрим пример (рис. 4.4). Интеграция поиском в глубину будет подключать все модули, находящиеся на главном управляющем пути структуры (по вертикали). Выбор главного управляющего пути отчасти произволен и зависит от характеристик, определяемых приложением. Например, при выборе левого пути прежде всего будут подключены модули Ml, М2, М5. Следующим подключается модуль М8 или М6 (если это необходимо для правильного функционирования М2). Затем строится центральный или правый управляющий путь. 

При интеграции поиском в ширину структура последовательно проходится по уровням-горизонталям. На каждом уровне подключаются модули, непосредственно подчиненные управляющему модулю — «начальнику». В этом случае прежде всего подключаются модули М2, М3, М4. На следующем уровне — модули М5, М6 ит. д.

 

Рис. 4.4

Нисходящая интеграция системы

Возможны следующие шаги процесса нисходящей интеграции:

1.                     Главный управляющий модуль (находится на вершине иерархии) используется как тестовый драйвер. Все непосредственно подчиненные ему модули временно замещаются заглушками.

2.                     Одна из заглушек заменяется реальным модулем. Модуль выбирается поиском в ширину или в глубину.

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

4.                     Если в модуле-драйвере уже нет заглушек, производится смена модуля-драйвера (поиском в ширину или в глубину).

5.                     Выполняется возврат на шаг 2 (до тех пор, пока не будет построена целая структура).

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

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

Существуют три возможности борьбы с этим недостатком:

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

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

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

   заглушка А — отображает трассируемое сообщение; 

   заглушка В — отображает проходящий параметр; 

   заглушка С — возвращает величину из таблицы;

   заглушка D — выполняет табличный поиск по ключу (входному параметру) и возвращает связанный с ним выходной параметр. Категории заглушек представлены на рисунке 4.5.

 

Рис. 4.5

Категории заглушек

Очевидно, что заглушка А наиболее проста, а заглушка D наиболее сложна в реализации.

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

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

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

                модули нижнего уровня объединяются в кластеры (группы, блоки), выполняющие определенную программную подфункцию;

                для координации вводов-выводов тестового варианта пишется драйвер, управляющий тестированием кластеров;

                тестируется кластер;

                драйверы удаляются, а кластеры объединяются в структуру движением вверх. 

 

Рис. 4.6

Восходящая интеграция системы

Модули объединяются в кластеры 1, 2, 3. Каждый кластер тестируется драйвером. Модули в кластерах 1 и 2 подчинены модулю Ма, поэтому драйверы D1 и D2 удаляются и кластеры подключают прямо к Ма. Аналогично драйвер D3 удаляется перед подключением кластера 3 к модулю Mb. В последнюю очередь к модулю Мс подключаются модули Ма и Mb.

          Рассмотрим различные типы драйверов: 

          драйвер А — вызывает подчиненный модуль;

          драйвер В — посылает элемент данных (параметр) из внутренней таблицы; 

          драйвер С — отображает параметр из подчиненного модуля;  драйвер D — является комбинацией драйверов В и С.

Очевидно, что драйвер А наиболее прост, а драйвер D наиболее сложен в реализации. Различные типы драйверов представлены на рисунке 4.7.

 

Рис. 4.7

Различные типы драйверов

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

Сравнение нисходящего и восходящего тестирований интеграции

Нисходящее тестирование:

                основной недостаток — необходимость заглушек и связанные с ними трудности тестирования;

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

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

                основной недостаток система не существует как объект до тех пор, пока не будет добавлен последний модуль;

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

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

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

1)           реализует несколько требований к программной системе;

2)           имеет высокий уровень управления (находится достаточно высоко в программной структуре);

3)           имеет высокую сложность или склонность к ошибкам (как индикатор может использоваться цикломатическая сложность — ее верхний разумный предел составляет 10);

4)           имеет определенные требования к производительности обработки. 

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

Уровни тестирования могут быть следующими: 

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

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

                системное тестирование. Тестируется интегрированная система на ее соответствие исходным требованиям: 

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

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

Виды ошибок и способы их обнаружения приведены в таблице 4.1. 

Используется два вида критериев для оценки достаточности проверки программы с некоторой полнотой (степень полноты определяется экспериментально) (табл. 4.2): 

                функциональные тесты составляются исходя из спецификации программы (метод «черного ящика»); 

                структурные тесты составляются исходя из текста программы (метод «белого ящика»). 

Таблица 4.1

Виды программных ошибок и способы их обнаружения 

Виды программных ошибок

Способы обнаружения

Синтаксические

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

Ошибки выполнения, выявляемые автоматически: а) переполнение, защита памяти;

б) несоответствие типов;

в) зацикливание

Динамический контроль: аппаратурой процессора; run-time системы программирования; операционной системой — по прерыванию лимита времени

Программа не соответствует спецификации

Целенаправленное тестирование

Спецификация не соответствует требованиям

Испытания, бета-тестирование

На рисунке 4.8а видно отличие тестирования команд (достаточно одного теста) от С1 (необходимы два теста как минимум). Рисунок 4.8б иллюстрирует различие С1 (достаточно двух тестов, покрывающих пути 1, 4 или 2, 3) от С2 (необходимо четыре теста для всех четырех путей). С2 недостижим в реальных программах из-за их цикличности, поэтому ограничиваются тремя путями для каждого цикла: 0, 1 и N повторений цикла. 

Таблица 4.2

Виды критериев и их функциональность 

Вид критерия

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

Фун

кциональные

Тестирование классов входных данных

Содержать представителей всех классов входных или выходных классов и точки на границах классов

Тестирование классов выходных данных

Тестирование функций

Каждая функция внешнего интерфейса должна быть проверена ≥ 1 раза

С

труктурные

Критерий С0 — тестирование команд

Каждая команда (оператор) должна быть выполнена ≥ 1 раза

Критерий С1 — тестирование ветвей

Каждая ветвь должна быть выполнена ≥ 1 раза

Критерий С2 — тестирование путей

Каждый путь в графе программы должен быть выполнен > 1 раза

 

 

Рис. 4.8

Траектории вычислений при структурном тестировании

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

Пример

Найти минимальный набор тестов для программы нахождения вещественных корней квадратного уравнения ах2 + bх + с = 0.

Решение представлено в таблице 4.3. 

Таблица 4.3 Поиск численного решения минимального набора тестов 

Номер теста

а

b

с

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

Что проверяется

1

2

–5

2

х1 = 2, х2 = 0,5

Случай вещественных корней

2

3

2

5

Сообщение

Случай комплексных корней

3

3

–12

0

х1 = 4, х2 = 0

Нулевой корень

4

0

0

10

Сообщение

Неразрешимое уравнение

5

0

0

0

Сообщение

Неразрешимое уравнение

6

0

5

17

Сообщение

Неквадратное уравнение 

7

9

0

0

х1 = х2 = 0

Нулевые корни

 

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

Заповеди по отладке программного средства, предложенные Г. Майерсом:

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

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

Заповедь 3. Готовьте тесты как для правильных, так и для неправильных данных.

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

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

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

                статическое тестирование — ручная проверка программы за столом;

                детерминированное тестирование — при различных комбинациях исходных данных;

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

4.4. Тестирование по методу «белого ящика»

При тестировании «белого ящика» (англ. white-box testing, также говорят — прозрачный ящик) разработчик теста имеет доступ к исходному коду и может писать код, который связан с библиотеками тестируемого ПО. Это типично для юнит-тестирования (англ. unit testing), при котором тестируются только отдельные части системы. Оно обеспечивает то, что компоненты конструкции работоспособны и устойчивы до определенной степени. 

Известна внутренняя структура программы, исследуются внутренние элементы программы и связи между ними (рис. 4.9).

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

 

Рис. 4.9

Тестирование «белого ящика»

Особенности тестирования «белого ящика»

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

                гарантируется проверка всех независимых маршрутов программы;

                проходятся ветви True, False для всех логических решений;

                выполняются все циклы (в пределах их границ и диапазонов);

                анализируется правильность внутренних структур данных. Недостатки тестирования «белого ящика»:

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

k m = ni.

i=1

При п = 5 и k = 20 количество маршрутов т = 10–14. Примем, что на разработку, выполнение и оценку теста по одному маршруту расходуется 1 мс. Тогда при работе 24 часа в сутки 365 дней в году на тестирование уйдет 3170 лет.

2.                     Исчерпывающее тестирование маршрутов не гарантирует соответствия программы исходным требованиям к ней.

3.                     В программе могут быть пропущены некоторые маршруты.

4.                     Нельзя обнаружить ошибки, появление которых зависит от обрабатываемых данных (это ошибки, обусловленные выражениями типа if abs (a – b)

< eps..., if (a + b + c)/3 = a...).

Достоинства тестирования «белого ящика»:

1.                     Количество ошибок минимально в «центре» и максимально на «периферии» программы.

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

3.                     При записи алгоритма ПО в виде текста на языке программирования возможно внесение типовых ошибок трансляции (синтаксических и семантических).

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

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

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

4.5. Функциональное тестирование  программного обеспечения 

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

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

Как показано на рисунке 4.10, основное место приложения тестов «черного ящика» — интерфейс ПО.

 

Рис. 4.10

Тестирование «черного ящика»

Эти тесты демонстрируют:

      как выполняются функции программ;

      как принимаются исходные данные;

      как вырабатываются результаты;

      как сохраняется целостность внешней информации.

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

Особенности тестирования «черного ящика»

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

                набор, образуемый такими входными данными, которые приводят к аномалиям поведения программы (назовем его IT);

                набор, образуемый такими выходными данными, которые демонстрируют дефекты программы (назовем его ОТ).

Как показано на рисунке 4.11, любой способ тестирования «черного ящика» должен:

                выявить такие входные данные, которые с высокой вероятностью принадлежат набору IT;

                сформулировать такие ожидаемые результаты, которые с высокой вероятностью являются элементами набора ОТ.

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

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

 

Рис. 4.11

Тестирование «черного ящика»

Тестирование «черного ящика» обеспечивает поиск следующих категорий ошибок:

1) некорректных или отсутствующих функций; 2) ошибок интерфейса;

3)                    ошибок во внешних структурах данных или в доступе к внешней базе данных;

4)                    ошибок характеристик (необходимая емкость памяти и т. д.); 5) ошибок инициализации и завершения.

Подобные категории ошибок способами «белого ящика» не выявляются.

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

Техника «черного ящика» ориентирована на решение следующих задач:

          сокращение необходимого количества тестовых вариантов (из-за проверки не статических, а динамических аспектов системы);

          выявление классов ошибок, а не отдельных ошибок.

4.6. Методика тестирования программных систем

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

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

 

Рис. 4.12

Спираль процесса тестирования ПС

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

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

1.                     Тестирование элементов. Цель — индивидуальная проверка каждого модуля. Используются способы тестирования «белого ящика».

2.                     Тестирование интеграции. Цель — тестирование сборки модулей в программную систему. В основном применяют способы тестирования «черного ящика».

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

4.                     Системное тестирование. Цель — проверка правильности объединения и взаимодействия всех элементов компьютерной системы, реализации всех системных функций.

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

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

λ( )t = λ0 , (4.1)  λ0 × p× +t 1

где λ(t) — текущая интенсивность программных отказов (количество отказов в единицу времени); λ0 — начальная интенсивность отказов (в начале тестирования); р — экспоненциальное уменьшение интенсивности отказов за счет обнаруживаемых и устраняемых ошибок; t — время тестирования.

С помощью уравнения (4.1) можно предсказать снижение ошибок в ходе тестирования, а также время, требующееся для достижения допустимо низкой интенсивности отказов.

Тестирование правильности

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

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

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

1) системную спецификацию;

2) план программного проекта;

3) спецификацию требований к ПС, работающий или бумажный макет;

4) предварительное руководство пользователя;

5) спецификацию проектирования;

6) листинги исходных текстов программ;

7) план и методику тестирования, тестовые варианты и полученные результаты;

8) руководства по работе и инсталляции;

9) ехе-код выполняемой программы; 

10)                     описание базы данных;

11)                     руководство пользователя по настройке;

12)                     документы сопровождения, отчеты о проблемах ПС, отчеты о конструкторских изменениях;

13)                     стандарты и методики конструирования ПС.

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

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

Альфа-тестирование проводится заказчиком в организации разработчика. Разработчик фиксирует все выявленные заказчиком ошибки и проблемы использования.

Бета-тестирование проводится конечным пользователем в организации заказчика. Разработчик в этом процессе участия не принимает. Фактически бетатестирование — это реальное применение ПС в среде, которая не управляется разработчиком. Заказчик сам записывает все обнаруженные проблемы и сообщает о них разработчику. Бета-тестирование проводится в течение фиксированного срока (около года). По результатам выявленных проблем разработчик изменяет ПС и тем самым подготавливает продукт полностью на базе заказчика.

Системное тестирование

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

Системное тестирование производится над проектом в целом с помощью метода «черного ящика». Категории тестов системного тестирования: 

         полнота решения функциональных задач; 

         стрессовое тестирование — на предельных объемах нагрузки входного потока;

         корректность использования ресурсов (утечка памяти, возврат ресур-

сов); 

         оценка производительности; 

         эффективность защиты от искажения данных и некорректных дейст-

вий; 

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

Классическая проблема системного тестирования — указание причины. Она возникает, когда разработчик одного системного элемента обвиняет разработчика другого элемента в причине возникновения дефекта. Для защиты от подобного обвинения разработчик программного элемента должен:

1)                     предусмотреть средства обработки ошибки, которые тестируют все вводы информации от других элементов системы;

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

3)                     записать результаты тестов, чтобы использовать их как доказательство невиновности в случае «указания причины»;

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

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

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

Тестирование восстановления и безопасности

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

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

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

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

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

Ему разрешено:

                узнать пароль с помощью внешних средств;

                атака системы с помощью специальных утилит, анализирующих защиты;

                подавление, ошеломление системы (в надежде, что она откажется обслуживать других клиентов);

                целенаправленное введение ошибок в надежде проникнуть в систему в ходе восстановления;

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

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

Стрессовое тестирование

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

Стрессовое тестирование производится при ненормальных запросах на ресурсы системы (по количеству, частоте, размеру-объему).

Например:

                генерируется 10 прерываний в секунду (при средней частоте 1,2 прерывания в секунду);

                скорость ввода данных увеличивается прямо пропорционально их важности (чтобы определить реакцию входных функций);

                формируются варианты, требующие максимума памяти и других ре-

сурсов; 

                генерируются варианты, вызывающие переполнение виртуальной па-

мяти; 

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

Powered by TCPDF (www.tcpdf.org)

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

Тестирование производительности

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

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

4.7. Контрольные вопросы

4.1. Как оценивается стоимость ошибок?

4.2. Какие причины ошибок в программных средствах могут быть из-за неправильного перевода информации? 

4.3. Определите основные понятия отладки и тестирования.

4.4. Что такое нисходящее тестирование интеграции?

4.5. Что такое восходящее тестирование интеграции?

4.6. Сравните нисходящее и восходящее тестирования интеграции.

4.7. Назовите заповеди по отладке программного средства, предложенные Майерсом.

4.8. Назовите особенности тестирования по методу «белого ящика».

4.9. Каковы особенности тестирования «черного ящика»?

4.10. В чем суть методики тестирования программных систем?

4.11. Когда и зачем выполняется тестирование правильности?

4.12. Когда и зачем выполняется системное тестирование?

4.13. В чем суть тестирования восстановления и безопасности?

4.14. В чем суть стрессового тестирования?

4.15. В чем суть тестирования производительности?