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

Описание тестируемой системы и ее окружения. Планирование тестирования

Разбить на страницы
Показывать лекцию целиком

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

GetStoreStat, GetStoreMessage, SendStoreCom (Store.dll) для склада.

GetAxlePar (Axle.dll) для терминала оси.

GetRollerPar (Bearing.dll) для терминала подшипника.

(рис 1.1) Система и ее окружение

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

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

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

Для нашей системы входными данными является состояние окружения ее компонентов:

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

Статус склада (StoreStat).

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

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

Терминал подшипника. Состояние терминала подшипника задается следующими параметрами:

Статус обмена с терминалом подшипника.

Характеристики (параметры) подшипника (RollerPar):

ФИО мастера, производившего измерения.

Название депо.

Номер рабочей смены.

Номер подшипника.

Номер группы подшипника.

Тип сепаратора подшипника.

Терминал оси. Состояние терминала оси задается следующими параметрами:

Статус обмена с терминалом оси.

Характеристики (параметры) оси (AxlePar):

ФИО мастера, производившего измерения.

Название депо.

Номер оси.

Сторона оси: правая или левая.

Посадочный диаметр задний.

Посадочный диаметр передний.

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

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

В процессе работы последовательность событий (команд) системы, или история системы, записывается в журнал (log) системы. Вы можете использовать SystemLogAnimator (см. п.14 SysLog Animator Manual) для визуализации журнала системы. Выбирая различные log-файлы системы для визуализации, можно получить наглядное и достаточно полное представление о функционировании системы и о том, какие события и в каком порядке могут происходить в системе.

Планирование тестирования

Процесс тестирования

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

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

Планирование тестирования

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

Кто будет тестировать и на каких этапах?

Разработчики продукта, независимая группа тестировщиков или совместно?

Какие компоненты надо тестировать?

Будут ли подвергнуты тестированию все компоненты программного продукта или только компоненты, которые угрожают наибольшими потерями для всего проекта?

Когда надо тестировать?

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

Как надо тестировать?

Будет ли тестирование сосредоточено только на проверке того, что данный продукт должен выполнять, или также на том, как это реализовано?

В каком объеме тестировать?

Как определить, в достаточном ли объеме выполнено тестирование, или как распределить ограниченные ресурсы, выделенные под тестирование?

Кто будет тестировать?

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

(рис 1.2) Кто тестирует

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

Какие компоненты надо тестировать?

Могут быть варианты, когда ничего не надо тестировать (поскольку все компоненты были протестированы ранее), а может потребоваться тестировать каждый компонент с точностью до строки кода. В объектно- ориентированном программировании базовым компонентом является класс. В этом случае область тестирования определяется классами. Область тестирования на уровне классов подлежит выбору (рис. 1.3). Классы, заимствованные из других проектов или взятые из библиотек, чаще всего в повторном тестировании не нуждаются. Существуют различные стратегии по выбору подмножества классов для тестирования.

(рис 1.3) Что тестировать

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

Когда надо тестировать?

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

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

(рис 1.4) Когда тестировать

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

Как надо тестировать?

Основные подходы к тестированию ПО основаны на спецификации и реализации (рис. 1.5).

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

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

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

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

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

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

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

    (рис 1.5) Как тестировать

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

    В каком объеме тестировать?

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

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

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

    (рис 1.6) В каком объеме тестировать

    Мы будем использовать все перечисленные меры.

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

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

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

    GetStoreStat, GetStoreMessage, SendStoreCom (Store.dll) для склада.

    GetAxlePar (Axle.dll) для терминала оси.

    GetRollerPar (Bearing.dll) для терминала подшипника.

    (рис 1.1) Система и ее окружение

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

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

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

    Для нашей системы входными данными является состояние окружения ее компонентов:

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

    Статус склада (StoreStat).

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

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

    Терминал подшипника. Состояние терминала подшипника задается следующими параметрами:

    Статус обмена с терминалом подшипника.

    Характеристики (параметры) подшипника (RollerPar):

    ФИО мастера, производившего измерения.

    Название депо.

    Номер рабочей смены.

    Номер подшипника.

    Номер группы подшипника.

    Тип сепаратора подшипника.

    Терминал оси. Состояние терминала оси задается следующими параметрами:

    Статус обмена с терминалом оси.

    Характеристики (параметры) оси (AxlePar):

    ФИО мастера, производившего измерения.

    Название депо.

    Номер оси.

    Сторона оси: правая или левая.

    Посадочный диаметр задний.

    Посадочный диаметр передний.

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

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

    В процессе работы последовательность событий (команд) системы, или история системы, записывается в журнал (log) системы. Вы можете использовать SystemLogAnimator (см. п.14 SysLog Animator Manual) для визуализации журнала системы. Выбирая различные log-файлы системы для визуализации, можно получить наглядное и достаточно полное представление о функционировании системы и о том, какие события и в каком порядке могут происходить в системе.

    Планирование тестирования

    Процесс тестирования

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

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

    Планирование тестирования

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

    Кто будет тестировать и на каких этапах?

    Разработчики продукта, независимая группа тестировщиков или совместно?

    Какие компоненты надо тестировать?

    Будут ли подвергнуты тестированию все компоненты программного продукта или только компоненты, которые угрожают наибольшими потерями для всего проекта?

    Когда надо тестировать?

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

    Как надо тестировать?

    Будет ли тестирование сосредоточено только на проверке того, что данный продукт должен выполнять, или также на том, как это реализовано?

    В каком объеме тестировать?

    Как определить, в достаточном ли объеме выполнено тестирование, или как распределить ограниченные ресурсы, выделенные под тестирование?

    Кто будет тестировать?

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

    (рис 1.2) Кто тестирует

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

    Какие компоненты надо тестировать?

    Могут быть варианты, когда ничего не надо тестировать (поскольку все компоненты были протестированы ранее), а может потребоваться тестировать каждый компонент с точностью до строки кода. В объектно- ориентированном программировании базовым компонентом является класс. В этом случае область тестирования определяется классами. Область тестирования на уровне классов подлежит выбору (рис. 1.3). Классы, заимствованные из других проектов или взятые из библиотек, чаще всего в повторном тестировании не нуждаются. Существуют различные стратегии по выбору подмножества классов для тестирования.

    (рис 1.3) Что тестировать

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

    Когда надо тестировать?

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

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

    (рис 1.4) Когда тестировать

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

    Как надо тестировать?

    Основные подходы к тестированию ПО основаны на спецификации и реализации (рис. 1.5).

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

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

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

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

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

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

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

    (рис 1.5) Как тестировать

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

    В каком объеме тестировать?

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

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

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

    (рис 1.6) В каком объеме тестировать

    Мы будем использовать все перечисленные меры.

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

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