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

Цель работы:

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

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

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

Составленный набор тестов необходимо представить в отчете.

Теоретические сведения.

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

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

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

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

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

Комплект тестов должен быть таким:

Чтобы проверить все варианты внешнего эффекта программы и ва­рианты ее внутренней работы алгоритма;

Чтобы все ветви алгоритма были пройдены, по крайней мере, по од­ному разу.

Чтобы проконтролировать предельные и вырожденные случаи.

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

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

1. Проверка в нормальных условиях.

2. Проверка в экстремальных условиях.

3. Проверка в исключительных ситуациях.

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

Проверка в нормальных условиях

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

Проверка в экстремальных условиях

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

Проверка в исключительных ситуациях.

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

Пример тестов.

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

Стороны

Параллепипеда

Примечание

Хороший нормальный тест d 1,7320508

Введение

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

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

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

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

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

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

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

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

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

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

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

Заключение

Глоссарий

Список использованных источников

Список сокращений

Введение

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

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

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

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

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

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

1. Понятия тестирования и отладки программного обеспечения

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

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

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

Согласно этому определению, тестирование предусматривает "анализ" или "эксплуатацию" программного продукта. Тестовая деятельность, связанная с анализом результатов разработки программного обеспечения, называется статическим тестированием (static testing). Статическое тестирование предусматривает проверку программных кодов, сквозной контроль и проверку программы без запуска па машине, т.е. проверку за столом (desk checks). В отличие от этого, тестовая деятельность, предусматривающая эксплуатацию программного продукта, носит название динамического тестирования (dynamic testing). Статическое и динамическое тестирование дополняют друг друга, и каждый из этих типов тестирования реализует собственный подход к выявлению ошибок.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2. Стратегия тестирования и отладки программного обеспечения

.1 Метод Сандвича

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

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

Модифицированный метод сандвича.

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

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

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

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

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

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

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

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

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

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

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

Методы тестирования на основе стратегии белого ящика:

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

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

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

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

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

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

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

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

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

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

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

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

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

Неверная или пропущенная функциональность

Ошибки интерфейса

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

Методы тестирования на основе Автоматизированные инструменты

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

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

Ошибки загрузки

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

Ошибки инициализации и завершения

Проблемы сохранения резервных копий и способности к восстановлению работы

Проблемы безопасности

Методы тестирования на основе стратегии черного ящика

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Снижения;

Обратная трассировка.

Метод ручного тестирования.

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

Метод пролога.

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

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

Метод снижения.

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

Метод обратной трассировки.

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

Заключение

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

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

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

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

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

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

Глоссарий

№ п/пПонятиеОпределение 1Тестирование программного обеспеченияэто процесс анализа или эксплуатации программного обеспечения с целью выявления дефектов 2Отладкаэто процесс выявления источников отказов, т.е. ошибок, и внесение в программу соответствующих исправлений3Восходящее тестированиетестирование осуществляется снизу вверх4Нисходящее тестированиетестирование осуществляется сверзу вниз5Тестирование «белого ящика»это разработка тестовых случаев где используют любые доступные сведения о внутренней структуре или коде6Тестирование «черного ящика»это разработка тестовых случаев при наличии установленных открытых интерфейсов7Метод сандвичаэто подход к интеграции больших программ, таких, как операционная система или пакет прикладных программ.8Модульное тестированиепроцесс, позволяющий проверить на корректность отдельные модули исходного кода программы9Тестирование безопасностиэто проверка работы механизмов доступа к системе и к данным10Тестирование производительностиэто проверка, удовлетворяет ли системное приложение требованиям по производительности Список использованных источников

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

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

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

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

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

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

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

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

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

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

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

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

Список сокращений

testing - тестирование программного обеспечения- процессtesting - статическое тестирование checks - проверка за столом testing - динамического тестирования - дефектdown - нисходящий- программный интерфейс приложения

еггог returns - возвращение ошибкиbox - прозрачный ящик - прозрачное тестирование

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

1Программирование - внесение в программу новой функциональности, исправление ошибок в имеющейся.

2Тестирование (ручное или автоматизированное; программистом, тестером или пользователем; «дымовое», в режиме чёрного ящика или модульное…) - обнаружение факта ошибки.

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

4Отладка - обнаружение причины ошибки.

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

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

    ошибки времени выполнения;

    алгоритмические.

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

После возникновения такой ошибки необходимо нажать «Ok» в окне сообщения об ошибке, а затем завершить выполнение программы – пункт меню « Run / Program reset » или нажать комбинацию клавиш <Ctrl ><F 2 >. При возникновении такой ошибки курсор в программе будет указывать на строку, вызвавшую ошибку. Наиболее сложно обнаружить алгоритмические ошибки. Программа компилируется без ошибок, не дает ошибок при пробных запусках, но при анализе результатов выясняется, что результат неправильный. Необходимо вручную «прокрутить» алгоритм – требуется отладка программы .

Для трассировки программы (проверка «логики алгоритма»), т. е. выполнения программы по шагам, необходимо выполнить следующие действия. В пункте меню выбрать пункт «Run / Step over » или «Run / Trace in to » (клавиши <F 8 > и <F 7 > соответственно), команда «Run / Trace in to » отличаются более детальной трассировкой. Для прекращения трассировки и продолжения выполнения программы в автоматическом режиме необходимо выбрать пункт «Run / Run » или нажать <F 9 >. Остановить программу можно с помощью команды «Run / Program reset » или нажать комбинацию клавиш <Ctrl ><F 2 >. Иногда необходимо выполнить трассировку с определенной строки программы. Для этого курсор подводят к интересующей строке и выполняют команду «Run / Run to cursor » или нажимают <F 4 >. Часто известно возможное место ошибки в алгоритме – тогда используют точку останова . Программист устанавливает на нужной строке курсор и ставит там точку останова с помощью команды «Run / Add Breakpoint » или нажав <F 5 >. Выбранная строка будет отмечена. Для снятия точки останова необходимо на этой строке снова нажать <F 5 >. При выполнении программа дойдёт до точки останова, затем программист сможет трассировать программу с помощью <F 7 > и <F 8 >. При необходимости можно указать условие остановки на точке останова (эта настройка осуществляется в окне «Breakpoints », пункт меню «Run / Add breakpoints »).

При выполнении программы по шагам часто необходимо не только проверять правильность «логики алгоритма», но и знать значения некоторых переменных. Для этого выполняют команду «View / Watch / Add watch » и вводят имя интересующей переменной либо подводят курсор к переменной, значение которой необходимо просмотреть, и нажимают <Ctrl ><F 5 >. При трассировке программы в этом случае в окне «Watch list » можно наблюдать изменение значений интересующих переменных.

10. Создание и описание новых типов данных.

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

Имя = Описание типа;

Имя – имя нового типа;

Описание типа описание возможных значений переменных созданного типа.

Замечание. При описании нового типа после имени типа ставится знак «равно», затем следует описание типа.

Примеры

DayOfWeek = (Monday, Wednesday, Friday);

Day =1..31;

Тип подобного вида называется перечисляемым, переменные данного типа могут принимать только перечисленные значения. В примере это одно из названий дня недели (тип DayOfWeek ) или одно из чисел от 1 до 31 (тип Day ). С переменными перечисляемого типа можно использовать функции Pred (переменная)и Succ (переменная), возвращающие предыдущее (Pred ) и последующее (Succ ) из допустимых значений.

Примеры

Пусть объявлены переменные W: DayOfWeek и D: Day. Тогда:

Succ (W); {Оператор вернет значение ‘Monday’}

Pred (D); {Оператор вернет значение ‘4’}

Замечания:

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

    Обращение с помощью оператора Succ или Pred к последнему (для оператора Succ ) или первому (для оператора Pred ) элементу приведет к ошибке.

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

Тестирование и отладка программы

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

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

  1. Синтаксические
  2. Времени выполнения (run-time errors)
  3. Алгоритмические

Синтаксические ошибки

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


Рис. 27.1.

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

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

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

Ошибки времени выполнения (run-time errors) тоже, как правило, легко устранимы. Они обычно проявляются уже при первых запусках программы, или во время тестирования . Если такую программу запустить из среды Lazarus, то она скомпилируется, но при попытке загрузки, или в момент совершения ошибки, приостановит свою работу, выведя на экран соответствующее сообщение. Например, такое:


Рис. 27.2.

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

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

Если программу запустить из самой Windows , при возникновении этой ошибки появится такое же сообщение. При этом если нажать "OK ", программа даже может запуститься, но корректно работать все равно не будет.

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

begin MySL:= TStringList.Create; MySL.Add("Новая строка"); end;

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

begin MySL:= TStringList.Create; MySL.Add("Новая строка"); ...; //работа с объектом MySL.Free; //освободили объект end;

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

begin try MySL:= TStringList.Create; MySL.Add("Новая строка"); ...; //работа с объектом finally MySL.Free; //освободили объект, даже если была ошибка end; end;

Итак, во избежание ошибок времени выполнения программист должен не забывать делать проверку на правильность ввода пользователем допустимых значений, заключать опасный код в блоки try…finally…end или try…except…end , делать проверку на существование открываемого файла функцией FileExists и вообще соблюдать предусмотрительность во всех слабых местах программы. Не полагайтесь на пользователя, ведь недаром говорят, что если в программе можно допустить ошибку, пользователь эту возможность непременно найдет.

Алгоритмические ошибки

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

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

Если программа работает правильно с одними наборами исходных данных, и неправильно с другими, то это свидетельствует о наличии алгоритмической ошибки. Алгоритмические ошибки иногда называют логическими, обычно они связаны с неверной реализацией алгоритма программы: вместо "+" ошибочно поставили "-", вместо "/" - "*", вместо деления значения на 0,01 разделили на 0,001 и т.п. Такие ошибки обычно не обнаруживаются во время компиляции , программа нормально запускается, работает, а при анализе выводимого результата выясняется, что он неверный. При этом компилятор не укажет программисту на ошибку - чтобы найти и устранить её, приходится анализировать код, пошагово "прокручивать" его выполнение, следя за результатом. Такой процесс называется отладкой .

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

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

В процессе отладки программы выделяются этапы:

1. трансляция исходного текста программы;

2. компоновка программы;

3. выполнение программы с целью определения логических ошибок;

4. тестирование программы.

Трансляция

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

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

Лексический анализ

Выявляются отельные составляющие текста программы, которые называются лексемами, и определяется их тип. К числу лексем относятся названия операторов, например, read или write; имена (переменных или констант), например, NABOR или CHISLO, различные разделители, такие как круглые скобки, знаки препинания и т.д. Одновременно типами указанных лексем являются названия операторов, имена переменных, разделители и т.д. Если программистом допущена ошибка и оператор ввода указан, например, rread, он будет распознан компилятором как имя. На этом этапе выявляется также использование недопустимых языком программирования символов, например, символа @. В результате лексического анализа исходная программа кодируется: каждая лексема заменяется кодом ее типа, что сокращает объем текста программы. Кроме того, из текста программы удаляются пробелы.

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

read (NABOR,CHISLO);

дает цепочку

где 1 – код названия оператора;

2 – код скобки;

3 – код имени;

4 – код знака препинания.

Пример 2. Лексический анализ фрагмента программы на Турбо-Паскале, содержащего только один неправильно записанный оператор ввода:


rread (NABOR,CHISLO); ,

дает цепочку

Синтаксический анализ

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

Рисунок 1

В то же время структура "правильного" оператора ввода определяется схемой:

Рисунок 2

Поскольку представленные структуры идентичны, оператор read (NABOR,CHISLO); при синтаксическом анализе определяется как правильный.

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

Рисунок 3

Поскольку структура этого рисунка не соответствует структуре рисунка 1, оператор rread (NABOR,CHISLO); расценивается как синтаксически некорректный: компилятор не найдет в анализируемом фрагменте требуемого действия, которое задается названием оператора, и сообщит об этом программисту.

Семантический анализ

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

read (NABOR,CHISLO); ,

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

Пример 3. Программа

var NABOR, CHISLO: integer;

read (NABOR, CHISLO);

Пример 4. Программа

var CHISLO: integer;

CHISLO:=CHISLO + 1;

расценивается семантическим анализатором как семантически корректная.

Генерация промежуточного кода

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

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

$1 DD ? ; операторы DD описывают переменные: каждый из них

$2 DD ?; отводит под переменную 2 байта памяти;

$3 DD ?; переменные $1 - $3 вводятся генератором кода как

CHISLO DD ?; вспомогательные переменные;

MOVE 1, $1; в операторах MOVE константы или содержимое

MOVE CHISLO, $2; переменных слева от запятой помещаются в переменные и

MOVE $1, AX; регистры процессора (АХ и СХ), указанные справа;

ADD AX, CX; выполняется сложение содержимого регистров АХ и СХ,

; результат остается в регистре АХ

MOVE AX, $3; выполняются перемещения значений, находящихся в

MOVE $3, CHISLO; регистре и переменной, в соответствующие переменные

Полученный код избыточен: в самом деле, выполняется бессмысленная пересылка константы 1 и значения переменной CHISLO сначала в дополнительные переменные $1 и $2, а затем уже в регистры АХ и СХ, которые и используются при сложении. Аналогичные бессмысленные действия выполняются и с результатом сложения. Однако уменьшение размеров кода осуществляется на следующем этапе.

Оптимизация промежуточного кода

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

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

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

Генерация объектного кода

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

код объем действие

операции

124 1 б сложить содержимое регистров АХ и СХ, результат – в регистре АХ,

125 3 б поместить содержимое регистра АХ по адресу,

126 2 б поместить константу в регистр АХ,

127 3 б поместить содержимое адреса в регистр СХ.



 

Возможно, будет полезно почитать: