Тестирование процесс поиска ошибок

Главная / Программирование /
Основы тестирования программного обеспечения / Тест 2

Упражнение 1:


Номер 1

Является ли программа аналогом математической формулы?

Ответ:

(1) да 

(2) нет 

(3) математические формулы и программы не сводятся друг к другу 


Номер 2

Какие подходы используются для обоснования истинности программ?

Ответ:

(1) доказательство программы 

(2) эксперимент над программой 

(3) формальный и интерпретационный 

(4) использование аналогий 


Номер 3

Отметьте верные утверждения

Ответ:

(1) тестирование – процесс поиска ошибок 

(2) в фазу тестирования входят поиски и исправление ошибок  

(3) отладка – процесс локализации и исправления ошибок 


Упражнение 2:


Номер 1

Зачем нужна спецификация тестирования?

Ответ:

(1) для формирования команды тестировщиков 

(2) для разработки тестового набора 

(3) для понимания смысла программы 


Номер 2

Какие существуют методы анализа и локализации ошибки?

Ответ:

(1) выполнение программы в уме 

(2) пошаговое выполнение 

(3) метод контрольных точек и анализа трасс 


Номер 3

Зачем нужен Log-файл?

Ответ:

(1) для изучения результатов тестирования в режиме on-line 

(2) для фиксации результатов прогона test-suite 

(3) для записи комментариев после прогона тестов 


Упражнение 3:


Номер 1

Какие существуют фазы  процесса тестирования?

Ответ:

(1) разработка тестового набора 

(2) прогон программы на тестовом наборе 

(3) анализ результатов тестирования 

(4) доказательство правильности программы 


Номер 2

Каковы особенности разработки тестового набора?

Ответ:

(1) определение областей эквивалентности входных параметров 

(2) анализ покрытия тестами всех возможных случаев поведения 

(3) проверка граничных значений 


Номер 3

Какие существуют способы получения эталонных значений теста?

Ответ:

(1) предсказание ожидаемого результата 

(2) независимое вычисление результата 

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


Упражнение 4:


Номер 1

Что такое управляющий граф программы (УГП)?

Ответ:

(1) множество операторов программы. 

(2) граф, вершины которого кодируют операторы программы, а дуги — управления (порядок исполнения) операторов. 

(3) множество операторов управления 


Номер 2

Что такое путь в УГП?

Ответ:

(1) последовательность вершин и дуг УГП с фиксированными начальной и конечной вершиной 

(2) последовательность ветвей УГП с фиксированными начальной вершиной первой ветви и конечной вершиной последней ветви пути 

(3) множество связанных дуг УГП 


Номер 3

Что такое ветвь УГП?

Ответ:

(1) последовательность вершин и дуг УГП с фиксированными начальной и конечной вершиной, которые кодируют либо условные операторы, либо первый и последний операторы УГП соответственно 

(2) часть пути, в котором все внутренние вершины кодируют линейные операторы 

(3) начальная и конечная вершина пути 


Упражнение 5:


Номер 1

Отметьте верные утверждения:

Ответ:

(1) нереализуемый путь недоступен при корректном исполнении программы 

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

(3) нереализуемый путь доступен при сбое 


Номер 2

Какова мощность множества тестов, формально необходимая для тестирования операции в машине с 32-разрядным машинным словом?

Ответ:

(1) 232 

(2) 49 

(3) 264 


Номер 3

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

Ответ:

(1) один 

(2) неопределенное количество 

(3) зависит от критерия достаточности проверок 


Упражнение 6:


Номер 1

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

Ответ:

(1) никогда 

(2) да, всегда 

(3) возможно в отдельных случаях 


Номер 3

Можно ли гарантировать остановку программы на любом тесте?

Ответ:

(1) в общем случае нет 

(2) возможно в частных случаях 

(3) задача в общей постановке алгоритмически неразрешима 


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

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

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

Поиск багов

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

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

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

А что делать с багами, которые сложно воспроизвести? Давайте подумаем: лучше найти 1 серьезный, но сложно воспроизводимый, баг или 10 обычных. Конечно 10 обычных. Ведь задача просто найти баги. И чем больше, тем лучше.

Что мы имеем в итоге?

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

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

Теперь к тестированию. Какими наши действия будут тут?

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

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

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

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

Что мы имеем в итоге?

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

Разница

Давайте на примере из жизни. Есть стиральная машина. При поиске ошибок мы будем пробовать нажать на кнопку выключения 50 раз подряд. Потом во время стирки покрутим переключатель программ во все стороны 20 минут без перерыва.
Но мы не проверим, запускается ли она при одинарном нажатии на кнопку пуск или нет. Ведь в этом месте вряд ли найдется ошибка. А если в этом месте она будет, то мне, как пользователю, такая стиральная машинка будет не нужна и я от нее откажусь.

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

Чувствуете разницу? Она просто колоссальная.

________________________________

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

________________________________

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

Как верно отметил Дмитрий Безносов, продукт может быть без единого дефекта (условно), но совершенно непригоден к использованию юзерами как в плане UI/IX, так и в плане функциональности.

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

***

Кто-то может сказать, что я сильно преувеличиваю. Может в краткосрочной перспективе так и покажется. Но на длинной дистанции однозначно придем к тому, что продукт перестанет соответствовать ожиданиям пользователей и от него попросту отвернутся.

Как бы это смешно не звучало, но многие тестировщики не знают правильного определения, что такое тестирование. Они могут много лет работать, тестировать разнообразные продукты, но вопрос «Что такое тестирование?» может поставить их в ступор. Разберём же что значит это понятие на самом деле.

Большинство источников, отвечая на вопрос «Что такое тестирование?» трактуют его следующим образом:

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

Для того, чтобы понять, что такое тестирование нужно понять цели этого процесса.

В тестировании есть 3 цели:

  1. Верификация (Verification)
  2. Валидация (Validation)
  3. Поиск ошибок (Error detection)

Напомним в двух словах:

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

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

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

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

Поэтому правильное определение тестирования в соответствии с ISTQB будет звучать следующим образом:

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

Это, конечно, правильно, но что-то уж очень «много букв».
Я предпочитаю говорить намного короче:

Тестирование — это верификация, валидация и поиск ошибок.

И всё 🙂

Библиографическое описание:


Пивоваров, Д. О. Отладка и тестирование программного обеспечения / Д. О. Пивоваров. — Текст : непосредственный // Молодой ученый. — 2022. — № 25 (420). — С. 14-15. — URL: https://moluch.ru/archive/420/93470/ (дата обращения: 06.06.2023).




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



Ключевые слова:



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

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

Процесс отладки состоит из нескольких этапов:

– определение ошибки;

– определение местонахождения ошибки;

– анализ ошибки;

– автоматизация тестирования;

– покрытие ущерба.

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

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

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

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

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

Ниже приведен список преимуществ отладки:

– экономия времени;

– создание отчетов об ошибках;

– простая интерпретация.

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

Существуют различные стратегии отладки:

– стратегия обучения;

– опыт;

– форвардный анализ;

– обратный анализ.

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

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

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

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

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

Типы тестирования, зависящие от объекта тестирования:

– модульное/unit-тестирование — проверка корректной работы отдельных модулей;

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

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

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

Все эти типы необходимы и используются в тестировании ПМ ОО.

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

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

– тестирование производительности — работа ПОпод сильной нагрузкой;

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

– тестирование UX — правильность логики использования;

– тестирование защищенности — определение безопасности ПО;

– инсталляционное тестирование — поиск возникновения проблем при установке;

– тестирование совместимости — тестирование работы ПО в определенном окружении;

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

– тестирование локализации — оценка правильности версии.

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

– тестирование белого ящика;

– тестирование черного ящика;

– тестирование серого ящика.

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

– нерабочие и неоптимизированные участки кода;

– безопасность;

– ввод данных;

– условные процессы;

– неправильная работа объектов;

– некорректное отображение информации.

Основным подходом в этой стратегии является анализ кода программы.

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

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

Литература:

  1. Гленфорд Майерс. Тестирование программного обеспечения. Базовый курс / Майерс Гленфорд, Баджетт Том, Сандлер Кори. — 3-е изд., 2022. — 298 c. — Текст: непосредственный.
  2. Отладка (debugging): что это. — Текст: электронный // Skillfactory: [сайт]. — URL: https://blog.skillfactory.ru/glossary/otladka-debugging/ (дата обращения: 22.06.2022).

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

Автомобили
Астрономия
Биология
География
Дом и сад
Другие языки
Другое
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Металлургия
Механика
Образование
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Туризм
Физика
Философия
Финансы
Химия
Черчение
Экология
Экономика
Электроника

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

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

Отладка программы – это процесс поиска и устранения неисправностей (ошибок) в программе, производимый по результатам её прогона на компьютере.

Тестирование (англ. test – испытание) – это испытание, проверка правильности работы программы в целом либо её составных частей.

Отладка и тестирование – это два четко различимых и непохожих друг на друга этапа:

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

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

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

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

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

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

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

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

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

· ручной отладки;

· индукции;

· дедукции;

· обратного прослеживания.

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

Отладка программ сегодня производится в основном с использованием специализированных программных пакетов на ЭВМ, но прежде чем «нагружать» ее этой работой можно проверку программы осуществить и в «ручном режиме», что всегда полезно как первый этап отладки программы перед дальнейшей ее отладкой на ЭВМ. В этом случае нужно представить, что Вы – машина, и, начав с первого оператора программы, выполнять оператор за оператором до обнаружения ошибки. Эту работу нужно вести методично и терпеливо, стремясь не делать правдоподобных догадок и не перескакивая через несколько операторов.

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

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

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

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

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

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

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

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

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

В процессе доказательства пытаются выяснить, все ли проявления ошибки объясняет данная гипотеза, если не все, то либо гипотеза не верна, либо ошибок несколько.

Рис. Схема процесса отладки методом индукции

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

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

Рис. Схема процесса отладки методом дедукции

Помощь в ✍️ написании работы

Поиск по сайту:

©2015-2020 mykonspekts.ru Все права принадлежат авторам размещенных материалов.

Отладка и тестирование программ.

1. Отладка программы

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

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

2. Локализация ошибок

Локализация — это нахождение места ошибки в программе.

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

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

Оба способа по-своему удобны и обычно используются совместно.

3. Принципы отладки

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

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

4. Методы отладки

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

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

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

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

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

var
a, b, c: real;
begin
writeln(‘Программа находит значение максимального из трех введенных чисел’);
write(‘Введите первое число ‘); readln(a);
write(‘Введите второе число ‘); readln(b);
write(‘Введите третье число ‘); readln(c);
if (a>b)and(a>c) then
writeln(‘Наибольшим оказалось первое число ‘,a:8:2)
else if (b>a)and(<strong>a</strong>>c) then
writeln(‘Наибольшим оказалось второе число ‘,b:8:2)
else
writeln(‘Наибольшим оказалось третье число ‘,<strong>b</strong>:8:2);
end.

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

Тестовые наборы данных должны учитывать все варианты решения, поэтому выберем следующие наборы чисел:

Данные                    Ожидаемый результат
a=10; b=-4; c=1       max=a=10
a=-2; b=8; c=4         max=b=8
a=90; b=0; c=90.4  max=c=90.4

В результате выполнения программы мы, однако, получим следующие результаты:
Для a=10; b=-4; c=1:

Наибольшим оказалось первое число 10.00

Для a=-2; b=8; c=4: < pre class=list>Наибольшим оказалось третье число 8.00Для a=90; b=0; c=90.4:

Наибольшим оказалось третье число 0.00

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

1. Трассировка и промежуточная печать

Добавляем промежуточную печать:
— вывод a, b, c после ввода (проверяем, правильно ли получили данные)
— вывод значения каждого из условий (проверяем, правильно ли записали условия)

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

var
a, b, c: real;
begin
writeln(‘Программа находит значение максимального из трех введенных чисел’);
write(‘Введите первое число ‘); readln(a);
writeln(‘Вы ввели число ‘,a:8:2); {отл.печать}
write(‘Введите второе число ‘); readln(b);
writeln(‘Вы ввели число ‘,b:8:2); {отл.печать}
write(‘Введите третье число ‘); readln(c);
writeln(‘Вы ввели число ‘,c:8:2); {отл.печать}
writeln(‘a>b=’,a>b,’, a>c=’,a>c,’, (a>b)and(a>c)=’,(a>b)and(a>c)); {отл.печать}
if (a>b)and(a>c) then
writeln(‘Наибольшим оказалось первое число ‘,a:8:2)
else begin
writeln(‘b>a=’,b>a,’, b>c=’,b>c,’, (b>a)and(b>c)=’,(b>a)and(b>c)); {отл.печать}
if (b>a)and(a>c) then
writeln(‘Наибольшим оказалось второе число ‘,b:8:2)
else
writeln(‘Наибольшим оказалось третье число ‘,b:8:2);
end;
end.

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

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

Вывод для второго случая получается следующим:

Программа находит значение максимального из трех введенных чисел
Введите первое число -2
Вы ввели число -2.00
Введите второе число 8
Вы ввели число 8.00
Введите третье число 4
Вы ввели число 4.00
a>b=FALSE, a>c=FALSE, (a>b)and(a>c)=FALSE
b>a=TRUE, b>c=TRUE, (b>a)and(b>c)=TRUE
Наибольшим оказалось третье число 8.00

Со вводом все в порядке. Впрочем, в этом сомнений и так было немного. А вот что касается второй группы операторов печати, то картина вышла интересная: в результате выводится верное число (8.00), но неправильное слово («третье», а не «второе»).

Вероятно, проблемы в выводе результатов. Тщательно проверяем текст и обнаруживаем, что действительно в последнем случае выводится не c, а b. Однако к решению текущей проблемы это не относится: исправив ошибку, мы получаем для чисел -2.0, 8.0, 4.0 следующий результат.

Наибольшим оказалось третье число 4.00

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

2. Метод индукции

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

Просматриваем все, относящееся к переменным b и с. Со вводом никаких проблем не замечено, а что касается вывода — то мы быстро натыкаемся на замену b на с. Исправляем.

Как видно, невыявленные ошибки в программе остаются. Просматриваем расчетный блок: все, что относится к максимальному b (максимум с получается «в противном случае»), и обнаруживаем пресловутую проблему «a>c» вместо «b>c». Программа отлажена.

3. Метод дедукции

Неверные результаты в нашем случае могут получиться из-за ошибки в:
— вводе данных;
— расчетном блоке;
— собственно выводе.

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

4. Обратное движение по алгоритму

Зная, что ошибка возникает при выводе результатов, рассматриваем код, начиная с операторов вывода. Сразу же находим лишнюю b в операторе writeln.

Далее, смотрим по конкретной ветке условного оператора, откуда взялся результат. Для значений -2.0, 8.0, 4.0 расчет идет по ветке с условием if (b>a)and(a>c) then… где мы тут же обнаруживаем искомую ошибку.

5. Тестирование

В нашей задаче для самого полного набора данных нужно выбрать такие переменные, что
a > b > c
a > c > b
b > a > c
b > c > a
c > a > b
c > b > a

Анализируя получившиеся в каждом из этих случаев результаты, мы приходим к тому, что проблемы возникают при b>c>a и с — максимальном. Зная эти подробности, мы можем заострить внимание на конкретных участках программы.

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

5. Средства отладки

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

1) Аварийная печать — вывод сообщений о ненормальном завершении отдельных блоков и всей программы в целом.

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

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

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

6. Классификация ошибок

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

7. Советы отладчику

1) Проверяйте тщательнее: ошибка скорее всего находится не в том месте, в котором кажется.

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

3) Тщательнее следить за объявлениями констант, типов и переменных, входными данными.

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

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

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

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

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

8) Убедитесь, что исходный текст программы соответствует скомпилированному объектному коду (текст может быть изменен, а запускаемый модуль, который вы тестируете — скомпилирован еще из старого варианта).

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

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

11) Если вы уже знаете симптомы ошибки, иногда полезно не исправлять ее сразу, а на фоне известного поведения программы поискать другие ляпы.

12) Самые труднообнаруживаемые ошибки — наведенные, то есть те, что были внесены в код при исправлении других.

8. Тестирование

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

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

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

2) При прогоне программы по тестовым начальным данным, полученные результаты нужно сверить с эталонными и проанализировать разницу, если она есть.

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

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

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

6) Чем больше ошибок в коде мы уже нашли, тем больше вероятность, что мы обнаружим еще не найденные.
Хорошим называют тест, который с большой вероятностью должен обнаруживать ошибки, а удачным — тот, который их обнаружил.

9. Проектирование тестов

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

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

program Example;
(******************************************************
* Задача: проверить, попадает ли введенное число в *
* заданный пользователем диапазон *
******************************************************)

var
min, max, A, tmp: real;
begin
writeln(‘Программа проверяет, попадают ли введенные пользователем’);
writeln(‘значения в заданный диапазон’);
writeln;
writeln(‘Введите нижнюю границу диапазона ‘); readln(min);
writeln(‘Введите верхнюю границу диапазона ‘); readln(max);
if min>max then begin
writeln(‘Вы перепутали диапазоны, и я их поменяю’);
tmp:=min;
min:=max;
max:=tmp;
end;
repeat
writeln(‘Введите число для проверки (0 — конец работы) ‘); readln(A);
if (A>=min)and(A<=max) then
writeln(‘Число ‘,A,’ попадает в диапазон [‘,min,’..’,max,’]’)
else
writeln(‘Число ‘,A,’ не попадает в диапазон [‘,min,’..’,max,’]’);
until A=0;
writeln;
end.

Если исходить из алгоритма программы, мы должны составить следующие тесты:
ввод границ диапазона
— min< max
— min>max
ввод числа
— A < min (A<>0)
— A > max (A<>0)
— min <= A <= max (A<>0)
— A=0

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

10. Стратегии тестирования

1) Тестирование программы как «черного ящика».

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

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

«Черным ящиком» удобно тестировать небольшие подпрограммы.
2) Тестирование программы как «белого ящика».

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

На практике мы, как всегда, совместно используем оба принципа.
3) Тестирование программ модульной структуры.

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

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

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

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

Hosted by uCoz

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

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

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

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

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

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

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

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

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

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

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

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

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

Для включения или отключения части кода в программу можно воспользоваться директивой «#ifdef символ код #endif». Если определен символ «символ», то «код» будет скомпилирован и включен в программу, иначе «код» будет просто пропущен.

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

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

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

Задание к работе

Разработать набор функций для работы с числами в n-ичной системе (n = = (номер варианта %15) + 10):

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

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

3) напишите функции инициализации числа из целой переменной и сохранения числа в целую переменную;

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

Особое внимание следует уделить не просто написанию программы, а следованию принципам структурного программирования, изложенным в теоретической части. Структура программы данной лабораторной работы дается в задании. Для каждой функции из этой структуры должны быть разработаны тесты, проверяющие ее работу, при необходимости должны быть включены отладочные сообщения. При выполнении работы должны строго выполняться требования по оформлению и комментариям к программе. Число представляется в виде массива int[10] (число может содержать не более 10 n-ичных цифр). Цифры больше девяти записываются буквами латинского алфавита (A – 10, B – 11 и т. д.).

Содержание отчета

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

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

1) Как в общем виде записывается функция на языке С?

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

3) Какая конструкция выбора используется в языке С?

4) Что такое отладка программы?

5) Что такое тестирование программы?

6) Какая директива определяет символ для компилятора?

Лабораторная работа 2
ЦИКЛЫ

Цель работы: овладение навыками построения простых и вложенных циклов, повторение основных форм записи циклов на языке С.

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

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

Отладка программы – это устранения неисправностей и процесс поиска (неточностей) в программе, создаваемый по итогам её прогона на компьютере.

Тестирование (англ. test – опробование) – это опробование, проверка правильности работы программы в целом или её составных частей.

тестирование и Отладка – это два четко различимых и непохожих друг на друга этапа:

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

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

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

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

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

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

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

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

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

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

Отладка программ сейчас производится по большей части с применением специальных программных пакетов на ЭВМ, но перед тем как «нагружать» ее данной работой возможно диагностику программы осуществить и в «ручном режиме», что неизменно полезно как первый этап отладки программы перед предстоящей ее отладкой на ЭВМ. В этом случае необходимо представить, что Вы – машина, и, начав с первого оператора программы, делать оператор за оператором до обнаружения неточности. Эту работу необходимо вести методично и терпеливо, стремясь не делать правдоподобных предположений и не перескакивая через пара операторов.

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

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

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

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

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

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

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

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

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

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

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

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

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

Рис. Схема процесса отладки способом дедукции

Typ

Похожие статьи:

  • Методы тестирования. требования и рекомендации по тестированию программ
  • Как внести порядок в повседневную трудовую жизнь
  • Способы и методы норм-я труда

Содержание:

ВВЕДЕНИЕ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ЗАКЛЮЧЕНИЕ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Автор статьи

Дмитрий Михайлович Беляев

Эксперт по предмету «Информатика»

Задать вопрос автору статьи

Определение 1

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

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

Термин debugging (с англ – отладка) дословно обозначает «вылавливание жучков». Он появился в 1945 г. после случая, когда компьютер «Марк-1» прекратил работу вследствие попадания в его электрические цепи мотылька, который заблокировал одно из реле вычислительной машины.

Логотип baranka

Сдай на права пока
учишься в ВУЗе

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

Получить скидку 4 500 ₽

Отладка программы

В современных системах программирования (например, Turbo C, Turbo Pascal, Turbo Basic и др.) отладку осуществляет зачастую специальное программное средство – отладчик, который позволяет исследовать внутреннее поведение программы.

Возможности отладчика:

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

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

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

«Отладка и тестирование программы» 👇

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

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

Отладка и тестирование программы. Автор24 — интернет-биржа студенческих работ

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

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

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

Тестовые данные

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

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

Рассмотрим на примере систему тестовых данных для задачи нахождения корней квадратного уравнения ax^2+bx+c=0:

Отладка и тестирование программы. Автор24 — интернет-биржа студенческих работ

Этапы процесса тестирования

Процесс тестирования зачастую делится на 3 этапа:

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

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

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

Замечание 1

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

Находи статьи и создавай свой список литературы по ГОСТу

Поиск по теме

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

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

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

В задачи функционального тестирования входят:

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

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

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

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

  • корректное оформление требований и ограничений к качеству ПО;
  • корректное описание модели функционирования ПО в среде эксплуатации у заказчика;
  • адекватность модели ПО заданному классу.

7.3. Инфраструктура процесса тестирования ПС

Под инфраструктурой процесса тестирования понимается:

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

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

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

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

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

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

Международный стандарт ANSI/IEEE-729-83 разделяет все ошибки в разработке программ на следующие типы.

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

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

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

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

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

Ошибки на этапах процесса тестирования.Приведенные типы ошибок распределяются по этапам ЖЦ и им соответствуют такие источники их возникновения [7.12]:

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

Рассмотрим процесс тестирования, исходя из рекомендаций стандарта ISO/IEC 12207, и приведем типы ошибок, которые обнаруживаются на каждом процессе ЖЦ.

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

Характерными ошибками этого процесса являются:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Приведем следующую классификацию типов отказов:

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

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

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

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

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

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

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

Тестирование программного обеспечения — процесс исследования программного обеспечения (ПО) с целью получения
информации о качестве продукта.

Введение

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

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

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

С точки зрения ISO 9126, Качество (программных средств) можно определить как совокупную характеристику исследуемого ПО с учётом следующих составляющих:

·        
Надёжность

·        
Сопровождаемость

·        
Практичность

·        
Эффективность

·        
Мобильность

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

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

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

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

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

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

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

·        
Нагрузочное тестирование

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

·        
Тестирование стабильности (stability/load testing)

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

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

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

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

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

По знанию системы:

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

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

·        
Тестирование серого ящика (gray box)

По степени автоматизированности:

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

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

·        
Полуавтоматизированное тестирование (semiautomated testing)

По степени изолированности компонентов:

·        
Компонентное (модульное) тестирование (component/unit testing)

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

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

По времени проведения тестирования:

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

·        
Тестирование при приёмке (smoke testing)

·        
Тестирование новых функциональностей (new feature testing)

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

·        
Тестирование при сдаче (acceptance testing)

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

По признаку позитивности сценариев:

·        
Позитивное тестирование (positive testing)

·        
Негативное тестирование (negative testing)

По степени подготовленности к тестированию:

·        
Тестирование по документации (formal testing)

·        
Эд Хок (интуитивное) тестирование (ad hoc testing)

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

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

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

Системное тестирование — тестируется интегрированная система на её соответствие требованиям.

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

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

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

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

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

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

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

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

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

Статическое и динамическое тестирование

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

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

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

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

Регрессио́нное тести́рование (англ. regression testing, от лат. regressio — движение назад) — собирательное название для всех видов тестирования программного обеспечения,
направленных на обнаружение ошибок в уже протестированных участках исходного кода. Такие ошибки — когда после внесения изменений в программу перестает работать то, что должно было продолжать работать, — называют регрессионными ошибками (англ. regression
bugs).

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

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

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

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

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

Цитата

«Фундаментальная проблема при сопровождении программ состоит в том, что исправление одной ошибки с большой вероятностью (20-50%) влечет появление новой. Поэтому весь процесс
идет по принципу «два шага вперед, шаг назад».

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

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

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

Тестовые скрипты

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

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

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

Критерии

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

·        
Покрытие операторов — каждая ли строка исходного кода была выполнена и протестирована?

·        
Покрытие условий — каждая ли точка решения (вычисления истинно ли или ложно выражение) была выполнена и протестирована?

·        
Покрытие путей — все ли возможные пути через заданную часть кода были выполнены и протестированы?

·        
Покрытие функций — каждая ли функция программы была выполнена

·        
Покрытие вход/выход — все ли вызовы функций и возвраты из них были выполнены

Для программ с особыми требованиями к безопасности часто требуется продемонстрировать, что тестами достигается 100 % покрытие для одного из критериев. Некоторые из приведённых критериев
покрытия связаны между собой; например, покрытие путей включает в себя и покрытие условий и покрытие операторов. Покрытие операторов не включает покрытие условий, как показывает этот код на Си:

printf(«this is «);

if (bar < 1)

{

   
printf(«not «);

}

printfa
positive
integer«);

Если здесь bar = −1, то покрытие операторов будет полным, а покрытие условий — нет, так как случай несоблюдения условия в операторе if — не покрыт. Полное покрытие
путей обычно невозможно. Фрагмент кода, имеющий n условий содержит 2n путей; конструкция цикла порождает бесконечное количество путей. Некоторые пути в программе могут быть не достигнуты из-за того, что в тестовых данных отсутствовали такие, которые могли
привести к выполнению этих путей. Не существует универсального алгоритма, который решал бы проблему недостижимых путей (этот алгоритм можно было бы использовать для решения проблемы останова). На практике для достижения покрытия путей используется следующий
подход: выделяются классы путей (например, к одному классу можно отнести пути отличающиеся только количеством итераций в одном и том же цикле), 100 % покрытие достигнуто, если покрыты все классы путей (класс считается покрытым, если покрыт хотя бы один путь
из него).

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

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

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

Степень покрытия кода обычно выражают в виде процента. Например, «мы протестировали 67 % кода». Смысл этой фразы зависит от того какой критерий был использован. Например,
67 % покрытия путей — это лучший результат чем 67 % покрытия операторов. Вопрос о связи значения покрытия кода и качеством тестового набора ещё до конца не решён.

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

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


E-mail: Svatoslav.Pankratov@gmail.com

Понравилась статья? Поделить с друзьями:
  • Тестирование памяти ddr4 на ошибки
  • Тестирование ошибок нива шевроле
  • Тестирование ошибок ваз 2115
  • Тестирование ошибка 403
  • Тестирование оперативной памяти на наличие ошибок