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

Решение задач и выполнение научно-исследовательских разработок: Отправьте запрос сейчас: irina@bodrenko.org    
математика, IT, информатика, программирование, статистика, биостатистика, экономика, психология
Пришлите по e-mail: irina@bodrenko.org описание вашего задания, срок выполнения, стоимость





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

 

Лекция 6.

 

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

 

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

 

 

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

1.1.  Актуальность процессов обеспечения и контроля качества ПО. 

 

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

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

 

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

 

С 1 марта 2012 года (взамен ГОСТ Р ИСО/МЭК 12207-99)  введен в действие национальный  стандарт  РФ ГОСТ Р ИСО/МЭК 12207-2010 «Информационная технология. Системная и программная инженерия. Процессы жизненного цикла программных средств»,  который идентичен международному стандарту ISO/IEC 12207:2008 «System and software engineeringSoftware life cycle processes».

 

 

Государственный стандарт РФ ГОСТ  Р   ИСО/МЭК   9126—93 « Информационная технология. ОЦЕНКА ПРОГРАММНОЙ  ПРОДУКЦИИ.  Характеристики качества и руководства по их применению» подготовлен на основе аутентичного текста международного стандарта ИСО/МЭК 9126—91 «Информационная технология. Оценка программной продукции. Характеристики качества и руководства по их применению».

 

 

Межгосударственный стандарт ГОСТ ISO 9000-2011 «Системы менеджмента качества. Основные положения и словарь»  введен в действие в качестве национального стандарта Российской Федерации с 1 января 2013 года. Настоящий стандарт идентичен международному стандарту ISO 9000:2005 «Quality management systems. Fundamentals and vocabulary».  

 

Межгосударственный стандарт ГОСТ ISO 9001–2011 «Системы менеджмента качества. Требования» введен  в действие в качестве национального стандарта Российской Федерации с 1 января 2013 года. Настоящий стандарт идентичен международному стандарту ISO 9001:2008 «Quality management systems — Requirements».

 

 

Названные выше стандарты мы подробно рассматривали на лекциях, посвященных моделям ЖЦ ПО, стандартизации и метрологии ПО.

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

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

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

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

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

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

 

ЦЕЛЬ ТЕСТИРОВАНИЯ.

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

 

Вот простой пример: еще в 1979 г. Майерс (Myers) описал некоторый простой алгоритм. В нем был всего один цикл и несколько операторов условного перехода. В большинстве языков программирования для кодирования такого алгоритма потребуется не более 20 строк кода. Но такая программа имеет более 100 триллионов путей выполнения! Самому быстрому тестировщику для полного тестирования потребовался бы как минимум миллион лет.

 

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

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

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

1.2.  Тестирование и качество.

1.2.

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

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

 

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

Перечислим наиболее важные для практики ВИДЫ ТЕСТИРОВАНИЯ программного обеспечения.

1. ФУНКЦИОНАЛЬНОЕ — тестирование возможностей системы, ее реакция на те или иные ситуации. Обычно результат тестирования (реакция системы) сравнивается с постановкой задачи, при несоответствии фиксируется ошибка.

2. РЕГРЕССИОННОЕ — проверка полноты реализуемых функций системы по сравнению с предыдущей версией программного продукта.

3. НАГРУЗОЧНОЕ — тестирование работы системы на пиковую нагрузку, при этом делается вывод о производительности системы. Например, выясняется среднее время ввода одного документа (если программное обеспечение предназначено для хранения и обработки документов). Условием для нагрузочного тестирования является выполнение испытаний на одной и той же конфигурации системы. Если тестируется производительность на 2-х разных СУБД, то конфигурация системы должна быть идентичной (тот же сервер, те же рабочие станции), в испытаниях меняются лишь СУБД. На основе нагрузочного тестирования выдвигаются требования к аппаратной части и программной части системы (операционная система, СУБД).

4. КОНТРОЛЬ ПОСЛЕ ИСПРАВЛЕНИЯ (ОБРАТНАЯ СВЯЗЬ). Этот вид тестирования подразумевает под собой проверку уже исправленных ошибок.

5. СТРЕССОВОЕ ТЕСТИРОВАНИЕ — проверка реакции системы на внештатные ситуации. Примером может служить проверка системы на восстановление работоспособности после отключения питания на сервере базы данных.

6. АДАПТАЦИОННОЕ ТЕСТИРОВАНИЕ — проверка корректности пере вода программного обеспечения на другой национальный язык.

 

1.3.  Уровни тестирования.

 

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

 

В целом разработчики различают дефекты программного обеспечения и сбои.

 

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

 

Дефект — это ошибка/неточность, которая может быть (а может и не быть) следствием сбоя.

Различают следующие УРОВНИ ТЕСТИРОВАНИЯ.

 

1)   МОДУЛЬНОЕ ТЕСТИРОВАНИЕ. Тестируется минимально  возможный для тестирования компонент, например отдельный класс или функция.

 

2)   ИНТЕГРАЦИОННОЕ ТЕСТИРОВАНИЕ. Проверяется, есть ли какие-либо проблемы в интерфейсах и взаимодействии между интегрируемыми компонентами, например, не передается информация, передается некорректная информация.

2)

3)   СИСТЕМНОЕ ТЕСТИРОВАНИЕ. Тестируется интегрированная  система на ее соответствие исходным требованиям:

3)

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

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

 

 

Виды ошибок и способы их  обнаружения приведены в следующей таблице (рисунок 1).

 

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

 

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

 

ТЕСТ — это набор контрольных входных данных совместно с ожидаемыми  результатами.

 

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

 

Ключевой вопрос — полнота тестирования: какое количество каких тестов  гарантирует, возможно, более полную проверку программы?

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

 

ВЫВОДЫ.

- в любой нетривиальной программе на любой стадии ее  готовности содержатся необнаруженные ошибки;

- тестирование — технико-экономическая проблема,  основанная на компромиссе «время — полнота». Поэтому нужно стремиться к возможно меньшему количеству хороших  тестов с желательными свойствами.

1.4.  Требования, предъявляемые к тестам.

 

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

Покрывающая способность: один тест должен выявлять как можно больше ошибок.

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

 

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

 

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

 

ФУНКЦИОНАЛЬНЫЕ ТЕСТЫ составляются,  исходя из  спецификации программы.

СТРУКТУРНЫЕ ТЕСТЫ составляются,  исходя из текста  программы.

На рисунке 3, случай а),  видно отличие тестирования команд  (достаточен один тест) от критерия С1 (необходимы два теста как минимум).

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

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

 

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

 

ПРИМЕР.

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

Решение представлено в следующей таблице (рисунок 4).

 

 

Рисунок 4. Поиск  минимального набора тестов.

 Р

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

 

  1. ПРОЦЕСС ТЕСТИРОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ И ЕГО АВТОМАТИЗАЦИЯ.

 

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

2.1.

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

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

 

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

Если альфа- и бета-тестирование относятся к стадиям до  выпуска продукта (а также, неявно, к объему тестирующего  сообщества и ограничениям на методы тестирования), тестирование «белого ящика» и «черного ящика» имеет отношение к  способам, которыми тестировщик достигает цели.

Бета-тестирование в целом ограничено техникой «черного ящика» (хотя постоянная часть тестировщиков обычно  продолжает тестирование «белого ящика» параллельно  бета-тестированию).

 

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

 

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

2.2.  Порядок разработки тестов.

 

По внешней спецификации разрабатываются следующие тесты.

Тесты для каждого класса входных данных.

Тесты для граничных и особых значений входных данных.

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

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

 

По тексту программы проверяется, все ли условные  переходы выполнены в каждом направлении (критерий С1). При необходимости добавляются новые тесты.

 

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

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

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

 

Классы входных/выходных данных должны быть  определены в плане тестирования уже во внешней спецификации.  Проверка по критерию С1 обычно выявляет 90 % всех ошибок, найденных при тестировании.

 

Систематическое тестирование предполагает также ведение журнала отладки (Bug Book), в котором фиксируется ошибка (описание, дата обнаружения, автор модуля) и в дальнейшем — исправление (дата, автор).

Приведем так называемые АКСИОМЫ ТЕСТИРОВАНИЯ.

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

2. Автор теста — не автор программы.

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

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

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

6. Следует повторять полное тестирование после внесения изменений в программу или после переноса ее в другую среду.

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

2.3.  Автоматизация тестирования.

Автоматизация тестирования применяется широко при таких видах тестирования, как регрессионное тестирование, приемочное тестирование.

А. Автоматизация прогона тестов актуальна для 5-й и 6-й  аксиом Майерса. Пишутся командные файлы для запуска  программы с каждым тестом из набора и сравнением реального  результата с ожидаемым.

 

Б. Средства автоматизации подготовки тестов и анализа их  результатов.

1. Генераторы случайных тестов в заданных областях  входных данных.

2. Отладчики (для локализации ошибок).

3. Анализаторы динамики (profilers). Обычно входят в состав отладчиков; применяются для проверки соответствия тестовых наборов структурным критериям тестирования.

4. Средства автоматической генерации структурных тестов методом «символического выполнения» Кинга.

 

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

1)   Время по поддержке и сложность теста должны быть меньше, чем сложность кода, которую он тестирует.

1)

2)   Время по адаптации — минимальное.

2)

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

3)

4)   Необходимо анализировать значащие элементы экрана (элементы, содержащие информацию).

4)

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

5)

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

6)

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

 

ПРЕИМУЩЕСТВА ИСПОЛЬЗОВАНИЯ АВТОМАТИЧЕСКИХ ТЕСТОВ перед тестированием очевидны:

• они беспристрастны;

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

• не устают и не ошибаются;

• могут протестировать гораздо больше за меньшее количество времени;

• не требуют дополнительной оплаты при работе по ночам и выходным;

• более четко отвечают на вопрос, что протестировано и с каким результатом.

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

 

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

 

- на пакеты, поддерживающие стратегию «белого ящика» и

 

- на пакеты,  поддерживающие стратегию «черного ящика».

ПАКЕТЫ, РЕАЛИЗУЮЩИЕ СТРАТЕГИЮ «БЕЛОГО ЯЩИКА», ПОЗВОЛЯЮТ:

• записывать, а потом воспроизводить последовательность пользовательского ввода (нажатие клавиатуры, движения «мышью»);

• распознавать объекты и их свойства;

• запоминать копию экрана;

• сравнивать состояние программы относительно предыдущего тестового прогона;

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

• замерять выполнение одной и той же последовательности действий в различных условиях;

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

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

• другие функции.

ПАКЕТЫ, РЕАЛИЗУЮЩИЕ СТРАТЕГИЮ «ЧЕРНОГО ЯЩИКА», ПОЗВОЛЯЮТ:

• отслеживать выполнение того или иного фрагмента кода программы;

• подсчитывать количество выполнения того или иного фрагмента кода программы;

 

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

• подсчитывать общее «покрытие» программы;

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

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

• получать различные статистические данные о программе.

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

 

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

2.4.

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

 

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

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

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

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

 

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

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

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

 

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

• на основе анализа потока управления. В этом случае  элементы, которые должны быть покрыты при прохождении тестов, определяются на основе структурных критериев тестирования С0, C1, C2. К ним относятся вершины, дуги, пути управляющего графа программы (УГП), условия,  комбинации условий и т. п.

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

 

 

ТЕСТИРОВАНИЕ НА ОСНОВЕ ПОТОКА УПРАВЛЕНИЯ.

 

К структурным критериям тестирования С0, C1, C2 следует добавить критерий покрытия условий, заключающийся в покрытии всех логических (булевых) условий в программе. Критерии покрытия решений (ветвей —  это критерий С1) и условий не заменяют друг друга, поэтому на практике используется комбинированный критерий покрытия условий/решений, совмещающий требования по покрытию и решений, и условий.

К популярным критериям относится критерий покрытия функций программы, согласно которому каждая функция  программы должна быть вызвана хотя бы 1 раз, и критерий  покрытия вызовов, согласно которому каждый вызов каждой функции в программе должен быть осуществлен хотя бы 1 раз. Критерий покрытия вызовов известен также как критерий покрытия пар вызовов (call pair coverage).

ТЕСТИРОВАНИЕ НА ОСНОВЕ ПОТОКА ДАННЫХ.

 

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

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

 

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

 

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

1)   конструирование УГП (управляющего графа программы);

1)

2)   выбор тестовых путей;

2)

3)   генерация тестов, соответствующих тестовым путям.

3)

 

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

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

Вторая фаза обеспечивает выбор тестовых путей.

 

Выделяют ТРИ ПОДХОДА К ПОСТРОЕНИЮ ТЕСТОВЫХ ПУТЕЙ:

1)   статические методы;

1)

2)   динамические методы;

2)

3)   методы реализуемых путей.

3)

СТАТИЧЕСКИЕ МЕТОДЫ. Самое простое и легко реализуемое  решение — построение каждого пути посредством постепенного его удлинения за счет добавления дуг, пока не будет достигнута выходная вершина управляющего графа программы. Эта идея может быть усилена в так называемых адаптивных методах,  которые каждый раз добавляют только один тестовый путь  (входной тест), используя предыдущие пути (тесты) как руководство для выбора последующих путей в соответствии с некоторой стратегией. Чаще всего адаптивные стратегии применяются по отношению к критерию С1. Основной недостаток статических методов заключается в том, что не учитывается возможная  нереализуемость построенных путей тестирования.

ДИНАМИЧЕСКИЕ МЕТОДЫ. Такие методы предполагают  построение полной системы тестов, удовлетворяющих заданному  критерию, путем одновременного решения задачи построения  покрывающего множества путей и тестовых данных. При этом можно автоматически учитывать реализуемость или нереализуемость ранее рассмотренных путей или их частей.

 

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

1) не терять при этом реализуемости вновь полученных путей;

2) покрыть требуемые элементы структуры программы.

МЕТОДЫ РЕАЛИЗУЕМЫХ ПУТЕЙ. Данная методика  заключается в выделении из множества путей подмножества всех реализуемых путей. После этого покрывающее множество путей строится из полученного подмножества реализуемых путей.

 

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

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

ДИНАМИЧЕСКИЕ МЕТОДЫ требуют значительно больших ресурсов как при  разработке, так и при эксплуатации, однако увеличение затрат происходит в основном за счет разработки и эксплуатации  аппарата определения реализуемости пути (символический  интерпретатор, решатель неравенств). Достоинство этих методов заключается в том, что их продукция имеет некоторый качественный уровень — реализуемость путей. Методы реализуемых путей дают самый лучший результат.

2.5.               Интеграционное тестирование.

2.5.

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

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

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

 

На рисунке 5 приведена структура комплекса программ К,  состоящего из оттестированных на этапе модульного тестирования модулей М1, М2, М11, М12, М21, М22.  Задача, решаемая  методом интеграционного тестирования, — тестирование  межмодульных связей, реализующихся при исполнении программного обеспечения комплекса К.

 

Рисунок 5.  Пример структуры комплекса программ.

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

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

 

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

ИЗВЕСТНЫ ДВА МЕТОДА СБОРКИ МОДУЛЕЙ:

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

1)

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

 

 

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

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

1)

2)   «снизу вверх» и соответственно нисходящее  тестирование.

2)

Особенности монолитного тестирования заключаются в  следующем:

 

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

СРАВНЕНИЕ МОНОЛИТНОГО И ИНТЕГРАЛЬНОГО ПОДХОДОВ ДАЕТ  СЛЕДУЮЩИЕ РЕЗУЛЬТАТЫ.

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

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

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

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

НЕДОСТАТКИ НИСХОДЯЩЕГО ТЕСТИРОВАНИЯ:

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

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

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

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

НЕДОСТАТКИ ВОСХОДЯЩЕГО ТЕСТИРОВАНИЯ:

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

• необходимость в разработке и использовании драйверов.

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

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

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

 

Системное тестирование производится над проектом в целом с помощью метода «черного ящика». Структура программы не имеет никакого значения, для проверки доступны только входы и выходы, видимые пользователю. Тестированию подлежат коды и пользовательская документация. КАТЕГОРИИ ТЕСТОВ СИСТЕМНОГО ТЕСТИРОВАНИЯ следующие.

 

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

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

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

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

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

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

7. Корректность документации.

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

 

3.     ОТЛАДКА ПРОГРАММ.

3.

Локализация и исправление ошибок называется отладкой.

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

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

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

3.1.               Ошибки синтаксиса языка.

3.1.

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

3.2.               Ошибки во время выполнения.

3.2.

К ошибкам во время выполнения программы относятся ошибки в логике и алгоритмах программы.

 

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

 

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

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

3.3.               Ошибки логики взаимосвязанных CGI-программ.

3.3.

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

 

3.4.               Ошибки многопользовательского доступа.

3.4.

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

3.5.               Невоспроизводимые ошибки.

3.5.

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

 

ПРИМЕР.

Например, в одной тестовой системе была непонятная ошибка, которая проявлялась 1 раз на несколько сот случаев. Непонятным образом некоторые студенты после сдачи теста получали не результаты, а сбой системы. На исправление этой ошибки ушло два рабочих дня.  Оказалось, что проблема в скрипте на JavaScript, который отправлял данные HTML-формы на сервер после истечения допустимого времени ответа на вопрос.  Проблема в том, что если время подходило к концу и пользователь нажимал кнопку «Ответить», а в это же время уже начала работать функция JavaScript form.submit(), то отправка данных HTML-формы происходила дважды, т. е. скрипт проверки правильности ответа вызывался 2 раза. А это за собой тянуло ошибку во взаимосвязанных CGI-скриптах, и внешнее проявление сбоя системы мы наблюдали уже при  подсчете результатов, а не непосредственно сразу после двойной  отправки HTML-формы. Сам код JavaScript был написан верно, и с теоретической точки зрения даже если пользователь нажимает кнопку «Отправить» в последнюю секунду, HTML-форма  должна была отправляться только 1 раз. Но на практике все  оказалось совсем по-другому. На самом деле ничего мистического нет, или, как говорится, чудес на свете не бывает. Просто  невозможно воспроизвести условия, в которых наблюдалась  невоспроизводимая ошибка. Надо искать в программе случайности: одновременный доступ к одному ресурсу, генератор случайных чисел, неинициализированные переменные, некорректная  работа с памятью или преобразование типов, которые могут  проявлять себя не каждый раз.

3.6.               Ошибки инструментария и других компонентов системы.

3.6.

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

3.7.               Методы поиска ошибок в программах.

 

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

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

Итак, допустим, вами, пользователем или тестирующим, было зафиксировано некорректное поведение программы. Что делать?

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

 

ЛОКАЛИЗАЦИЯ ОШИБКИ. Программа — это черный ящик, который что-то принимает на вход и выдает что-то на выходе.  Первое, что вам необходимо сделать, — понять, где именно в этом черном ящике происходит сбой. Для этого уменьшайте  количество параметров, передаваемых на вход программы. Добейтесь двух малоразличимых наборов входных параметров, чтобы при одном из них программа работала, а при другом нет.

ОТКЛЮЧЕНИЕ НЕНУЖНЫХ МОДУЛЕЙ ПРОГРАММЫ. Закомментируйте все лишнее. Тем самым вы упростите вашу программу. Имеет смысл комментировать отдельные куски программы до тех пор, пока ошибка не исчезнет.

ИСПОЛЬЗОВАНИЕ ОТЛАДЧИКА. Возможности современных  отладчиков перечислены ниже:

• точки останова на конкретных строчках кода;

• остановка на n-й итерации цикла;

• остановка при изменении переменных;

• остановка при присваивании конкретного значения;

• прохождение кода строчка за строчкой;

• откат по программе (далеко не все);

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

• присваивание новых значений переменным;

• продолжение исполнения программы;

• многоязыковая отладка (язык1, язык2, ассемблер...);

• запоминание установок.

 

 

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

СПИСОК РЕКОМЕНДУЕМОЙ ЛИТЕРАТУРЫ.

 

[1] Благодатских В.А., Волнин В.А., Поскакалов К.Ф. Стандартизация разработки программных средств. Учебное пособие /Под ред. О.С. Разумова. М.: Финансы и статистика, 2005. – 288 с., ил.

 

[2] Брауде Э. Технология разработки программного обеспечения. СПб.: Питер, 2004. – 655 с.: ил.

[3] Вигерс К. Разработка требований к программному обеспечению /Пер. с англ. – М.: ИТД «Русская Редакция», 2004. – 576.: ил. 

 

[4] Гагарина Л.Г., Кокорева Е.В., Виснадул Б.Д. Технология разработки программного обеспечения. Учебное пособие /Под ред. Л.Г. Гагариной. – М.: ИД «Форум»: ИНФРА-М, 2008. – 400 с.: ил. – (Высшее образование).

 

[5] Котов С.Л., Палюх Б.В., Федченко С.Л. Разработка, стандартизация и сертификация программных средств и информационных технологий и систем. Учебное пособие. Тверь.: ТГТУ, 2006. – 104 с.