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

Неразрешимость проблемы тестирования программного обеспечения. Виды и уровни тестирования. Стратегии восходящего и нисходящего тестирования. Методы "белого" и "черного" ящика. Автоматизированное и ручное тестирование. Разработка через тестирование.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 22.03.2015
Размер файла 112,2 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

Министерство образования и науки Российской Федерации

Федеральное государственное бюджетное образовательное

учреждение высшего профессионального образования

«ТВЕРСКОЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ»

Математический факультет

Кафедра компьютерной безопасности и математических методов управления

КУРСОВАЯ РАБОТА

по дисциплине “Методы программирования”

на тему

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

Выполнила:

студентка 35 группы математического факультета

специальность

Компьютерная безопасность

Кушнер Кристина Александровна

Проверила:

доцент кафедры КБиММУ

Цирулева Валентина Михайловна

Тверь, 2013 г.

Тестирование ПО. Неразрешимость проблемы тестирования. Виды и уровни тестирования. Стратегии восходящего и нисходящего тестирования. Методы "белого" и "черного" ящика. Автоматизированное и ручное тестирование. Разработка через тестирование (TDD). Непрерывная интеграция. Покрытие кода тестами.

Содержание

1. Вступление.

1.1 Общие понятия.

1.2 Основные определения.

2. Тестирование ПО.

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

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

3. Виды и уровни тестирования.

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

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

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

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

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

4.3 Технология восходящего и нисходящего тестирования.

5. Методы "белого" и "черного" ящика.

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

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

5.3 Метод «серого ящика».

6. Автоматизированное и ручное тестирование.

6.1 Автоматизированное тестирование.

6.2 Ручное тестирование.

7. Разработка через тестирование (TDD).

7.1 Основные понятия TDD.

7.2 Требования.

7.3 Цикл разработки через тестирование.

7.4 Запуск всех тестов: убедиться, что новые тесты не проходят.

7.5 Запуск всех тестов: убедиться, что все тесты проходят.

7.6 Рефакторинг

7.7 Стиль разработки.

7.8 Преимущества.

7.9 Слабые места.

8. Непрерывная интеграция.

8.1 Понятие непрерывной интеграции.

8.2 Требования к проекту.

8.3 Организация. 6

8.4 Сборка по расписанию.

8.5 Преимущества.

8.6 Недостатки.

8.7 Средства непрерывной интеграции.

9. Покрытие кода тестами.

9.1 Покрытие кода.

9.2 Практическое применение.

Литература.

Приложение 1.

Приложение 2.

1. Введение

1.1 Общие понятия

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

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

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

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

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

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

Сформулируем основополагающий вывод:

· Если ваша цель -- показать отсутствие ошибок, то вы их найдете не слишком много.

· Если же ваша цель -- показать наличие ошибок, вы найдете значительную их часть.

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

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

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

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

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

удовлетворен.

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

1.2 Основные определения

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

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

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

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

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

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

Отладка (debugging) не является разновидностью тестирования. Хотя слова «отладка» и «тестирование» часто используются как синонимы, под ними подразумеваются разные виды деятельности. Тестирование -- деятельность, направленная на обнаружение ошибок; отладка направлена на установление точной природы известной ошибки, а затем -- на исправление этой ошибки. Эти два вида деятельности связаны -- результаты тестирования являются исходными данными для отладки.

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

Тестирование сопряжении (integration testing) -- контроль сопряжении между частями системы (модулями, компонентами, подсистемами).

Тестирование внешних функций (external function testing) -- контроль внешнего поведения системы, определенного внешними спецификациями.

Комплексное тестирование (system testing) -- контроль и/или испытание системы по отношению к исходным целям. Комплексное тестирование является процессом контроля, если оно выполняется в моделируемой среде, и процессом испытания, если выполняется в среде реальной, жизненной.

Тестирование приемлемости (acceptance testing) -- проверка соответствия программы требованиям пользователя.

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

2. Тестирование ПО

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

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

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

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

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

1. По объекту тестирования

· Функциональное тестирование (functional testing)

· Нагрузочное тестирование (performance/load/stress testing)

· Тестирование удобства использования (usability testing)

· Тестирование интерфейса пользователя (UI testing)

· Тестирование безопасности (security testing)

· Тестирование локализации (localization testing)

· Тестирование совместимости (compatibility testing)

2. По знаниям о тестируемой системе

· Тестирование методом «черного ящика» (black box)

· Тестирование методом «белого ящика» (white box)

· Тестирование методом «серого ящика» (grey box)

3. По уровню автоматизации

· Ручное тестирование (manual testing)

· Автоматизированное тестирование (automated testing)

4. По степени изолированности

· Модульное тестирование (unit testing)

· Интеграционное тестирование (integration testing)

· Системное тестирование (system testing)

5. По уровню готовности

· Альфа-тестирование (alpha testing)

· Бета-тестирование (beta testing)

· Приемосдаточные испытания (acceptance testing)

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

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

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

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

· Время отклика (время выполнения операции)

· Число операций, выполняемых в единицу времени (например, transactions per second, TPS).

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

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

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

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

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

· Тестирование на соответствие стандартам графических интерфейсов;

· Тестирование с различными разрешениями экрана;

· Тестирование локализованных версий: проверка длины названий элементов интерфейса и т.п.;

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

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

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

· Тестирование авторизации пользователей - выявляет дефекты, связанные с авторизацией отдельных пользователей и г8рупп пользователей и с проверкой их подлинности;

· Тестирование процедур проверки корректности ввода - имеет целью выявление ошибок в процедурах проверки данных, поступающих в систему извне;

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

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

· Тестирование на переполнение буфера - выявляет выход за границы буферов при обработке данных;

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

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

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

Тестирование совместимости (compatibility testing) - проверка совместимости системы с различными вариантами программно-аппаратного окружения (операционными системами, различными браузерами, сетевым ПО, СУБД, сторонним ПО, аппаратной платформой).

3. Виды и уровни тестирования

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

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

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

Модульные тесты проверяют, что определенные воздействия на модуль приводят к желаемому результату. Как правило. Модульные тесты создаются с использованием метода «белого ящика». При наличии зависимостей тестируемого модуля от других модулей вместо них используются так называемые mock-объекты, предоставляющие фиктивную реализацию их интерфейсов. С использованием mock-объектов могут быть протестированы такие аспекты функционирования, которые невозможно проверить с использованием реальных зависимых модулей. Существуют специальные библиотеки (например, Moq), упрощающие задачу создания mock-объектов. В работе (Месарош Дж. «Шаблоны тестирования xUnit. Рефакторинг кода тестов») описываются наиболее удачные подходы к организации модульного тестирования.

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

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

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

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

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

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

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

3.2 Уровни тестирования

· Приемочное тестирование (Acceptance/ qualification testing).

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

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

· Установочное тестирование (Installation testing).

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

· Альфа- и бета-тестирование (Alpha and Beta testing).

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

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

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

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

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

· Функциональные тесты/тесты соответствия (Conformance testing/Functional testing/Correctness testing)

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

Достижение и оценка надежности (Reability achievement and evaluation)

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

· Регрессионное тестирование (Regression testing)

Определение успешности регрессионных тестов (IEEE 610-90 “Standart Glossary of Software Engineering Terminology”) гласит: « повторное выборочное тестирование системы или компонент для проверки сделанных модификаций не должно приводить к непредусмотренным эффектам». На практике это означает, что если система успешно проходила тесты до внесения модификаций, она должна их проходить и после внесения таковых. Основная проблема регрессионного тестирования заключается в поиске компромисса между имеющимися ресурсами и необходимостью проведения таких тестов по мере внесения каждого изменения. В определенной степени, задача состоит в том, чтобы определить критерии «масштабов» изменений, с достижением которых необходимо проводить регрессионные тесты.

· Тестирование производительности (Perfomance testing)

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

· Нагрузочное тестирование (Stress testing)

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

· Сравнительное тестирование (Back-to-back testing)

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

· Восстановительные тесты (Recovery testing)

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

· Конфигурационное тестирование (Configuration testing)

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

· Тестирование удобства и простоты использования (Usability testing)

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

· Разработка, управляемая тестированием (Test-driven development)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Интересен и второй вопрос: в какой форме готовятся тестовые данные и как они передаются программе? Если бы головной модуль содержал все нужные операции ввода и вывода, ответ был бы прост:

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

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

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

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

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

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

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

4.3 Технология восходящего и нисходящего тестирования

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

· от периферии к центру (восходящее тестирование) или, наоборот,

· от центра к периферии (нисходящее тестирование).

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

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

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

К сожалению, часто неверно понимают функции, выполняемые заглушками. Так, порой можно услышать, что заглушка должна выполнять лишь запись сообщения, устанавливающего: "Модуль подключился". В большинстве случаев эти утверждения ошибочны. Когда модуль A вызывает модуль B, A предполагает, что B выполняет некую работу, то есть модуль A получает результаты работы модуля B. Когда же модуль B просто возвращает управление или выдает некоторое сообщение без передачи в A определенных осмысленных результатов, модуль A работает неверно не вследствие ошибок в самом модуле, а из-за несоответствия ему модуля-заглушки. Более того, результат может оказаться неудовлетворительным, если "ответ" модуля-заглушки не меняется в зависимости от условий теста. Если заглушка всегда возвращает один и тот же фиксированный результат вместо конкретного значения, предполагаемого вызывающим модулем именно в этом вызове, то вызывающий модуль сработает как ошибочный (например, зациклится) или выдаст неверное выходное значение. Следовательно,

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

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

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

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

Проведем сравнение нисходящего и восходящего тестирования [Таблица 1].

Значительное повышение корректности и надежности программ достигается применением двойного или N-кратного программирования (Duplication Check - двойной просчет, двойная проверка).

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

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

· либо модуль имеет ошибку;

· либо неверны предполагаемые результаты (ошибки в тесте).

Для устранения такого рода недоразумений нужно тщательно проверять набор тестов ("тестировать" тесты).

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

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

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

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

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

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

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

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

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

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

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


Подобные документы

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

    курсовая работа [3,0 M], добавлен 19.11.2009

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

    дипломная работа [1,7 M], добавлен 03.05.2018

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

    курсовая работа [36,9 K], добавлен 21.07.2012

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

    курсовая работа [309,5 K], добавлен 16.12.2015

  • Автоматизация регрессионного тестирования. Классификация по способу сопровождения. Построение потового графа. Набор модульных тестов. Покрытие тестами классов эквивалентности. Тестирование методом "черного ящика". Тесты регрессии на "закрытых" багах.

    курсовая работа [1,8 M], добавлен 16.01.2017

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

    курсовая работа [1,6 M], добавлен 20.12.2012

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

    курсовая работа [2,8 M], добавлен 05.01.2013

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

    презентация [585,4 K], добавлен 19.09.2016

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

    курсовая работа [2,8 M], добавлен 09.07.2013

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

    дипломная работа [3,2 M], добавлен 11.09.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.