Отладка программы в любом случае предполагает обдумывание и логическое осмысление всей имеющейся информации об ошибке. Большинство ошибок можно обнаружить по косвенным признакам посредством тщательного анализа текстов программ и результатов тестирования без получения дополнительной информации. При этом используют различные методы:
Метод ручного тестирования. Это — самый простой и естественный способ данной группы. При обнаружении ошибки необходимо выполнить тестируемую программу вручную, используя тестовый набор, при работе с которым была обнаружена ошибка.
Метод очень эффективен, но не применим для больших программ, программ со сложными вычислениями и в тех случаях, когда ошибка связана с неверным представлением программиста о выполнении некоторых операций.
Лекция № 16. Тестирование и отладка программных продуктов
Содержание лекции: виды контроля качества разрабатываемого ПО; ручной контроль; структурное, функциональное и оценочное тестирование; классификация ошибок; методы и средства отладки ПО.
Assert для повышения надежности, отладки и тестирования программ. [программирование] #ityoutubersru
Цель лекции: ознакомиться с видами и способами контроля и тестирования ПО, методами и средствами отладки программ.
Недостаточно выполнить проектирование и кодирование программного продукта, также необходимо обеспечить его соответствие требованиям и спецификациям. Многократно проводимые исследования показали, что чем раньше обнаруживаются те или иные несоответствия или ошибки, тем больше вероятность их исправления и ниже его стоимость [4]. Современные технологии разработки ПО предусматривают раннее обнаружение ошибок за счет выполнения контроля результатов всех этапов и стадий разработки. На начальных этапах контроль осуществляют вручную или с использованием CASE -средств, на последних — он принимает форму тестирования.
Тестирование — это процесс выполнения программы, целью которого является выявление ошибок. Никакое тестирование не может доказать отсутствие ошибок в сложном ПО, поскольку выполнение полного тестирования становится невозможным и имеется вероятность, что остались невыявленные ошибки. Соблюдение основных правил тестирования и научно обоснованный подбор тестов может уменьшить их количество. Процесс разработки согласно современной модели жизненного цикла ПО предполагает три стадии тестирования: автономное тестирование компонентов ПО; комплексное тестирование разрабатываемого ПО; системное или оценочное тестирование на соответствие основным критериям качества. Для повышения качества тестирования рекомендуется соблюдать следующие основные принципы:
предполагаемые результаты должны быть известны до тестирования;
следует избегать тестирования программы автором;
необходимо досконально изучать результаты каждого теста;
необходимо проверять действия программы на неверных данных;
необходимо проверять программу на неожиданные побочные эффекты на неверных данных.
Вероятность наличия необнаруженных ошибок в части программы пропорциональна количеству ошибок уже найденных в этой части. Удачным считают тест, который обнаруживает хотя бы одну ошибку. Формирование набора тестов имеет большое значение, поскольку тестирование является одним из наиболее трудоемких этапов создания ПО. Доля стоимости тестирования в общей стоимости разработки возрастает при увеличении сложности ПО и повышении требований к их качеству.
Существуют два принципиально различных подхода к формированию тестовых наборов: структурный и функциональный. Структурный подход базируется на том, что известна структура тестируемого ПО, в том числе его алгоритмы («стеклянный ящик»). Тесты строятся для проверки правильности реализации заданной логики в коде программы.
Функциональный подход основывается на том, что структура ПО не известна («черный ящик»). В этом случае тесты строят, опираясь на функциональные спецификации. Этот подход называют также подходом, управляемым данными, так как при его использовании тесты строят на базе различных способов декомпозиции множества данных. Наборы тестов, полученные в соответствии с методами этих подходов, объединяют, обеспечивая всестороннее тестирование ПО.
Ручной контроль используют на ранних этапах разработки. Все проектные решения анализируются с точки зрения их правильности и целесообразности как можно раньше, пока их можно легко пересмотреть. Различают статический и динамический подходы к ручному контролю.
При статическом подходе анализируют структуру, управляющие и информационные связи программы, ее входные и выходные данные. При динамическом — выполняют ручное тестирование (вручную моделируют процесс выполнения программы на заданных исходных данных). Исходными данными для таких проверок являются: техническое задание, спецификации, структурная и функциональная схемы программного продукта, схемы отдельных компонентов, а для более поздних этапов — алгоритмы и тексты программ, а также тестовые наборы. Доказано, что ручной контроль способствует существенному увеличению производительности и повышению надежности программ и с его помощью можно находить от 30 до 70 % ошибок логического проектирования и кодирования. Основными методами ручного контроля являются: инспекции исходного текста, сквозные просмотры, проверка за столом, оценки программ.
В основе структурного тестирования лежит концепция максимально полного тестирования всех маршрутов, предусмотренных алгоритмом (последовательности операторов программы, выполняемых при конкретном варианте исходных данных). Недостатки: построенные тестовые наборы не обнаруживают пропущенных маршрутов и ошибок, зависящих от заложенных данных; не дают гарантии, что программа правильна.
Другим способом проверки программ является функциональное тестирование: программа рассматривается как «черный ящик», целью тестирования является выяснение обстоятельств, когда поведение программы не соответствует спецификации. Для обнаружения всех ошибок необходимо выполнить исчерпывающее тестирование (при всех возможных наборах данных), что для большинства случаев невозможно. Поэтому обычно выполняют «разумное» или «приемлемое» тестирование, ограничивающееся прогонами программы на небольшом подмножестве всех возможных входных данных. При функциональном тестировании различают следующие методы формирования тестовых наборов: эквивалентное разбиение; анализ граничных значений; анализ причинно-следственных связей; предположение об ошибке.
При комплексном тестировании используют тесты, построенные по методам эквивалентных классов, граничных условий и предположении об ошибках, поскольку структурное тестирование для него не применимо. Одним из самых сложных является вопрос о завершении тестирования, так как невозможно гарантировать, что в программе не осталось ошибок. Часто тестирование завершают потому, что закончилось время, отведенное на его выполнение. Его сворачивают, обходясь минимальным тестированием [15], которое предполагает: тестирование граничных значений, тщательную проверку руководства, тестирование минимальных конфигураций технических средств, возможности редактирования команд и повторения их в любой последовательности, устойчивости к ошибкам пользователя.
После завершения комплексного тестирования приступают к оценочному тестированию, целью которого является поиск несоответствий техническому заданию. Оценочное тестирование включает тестирование: удобства использования, на предельных объемах, на предельных нагрузках, удобства эксплуатации, защиты, производительности, требований к памяти, конфигурации оборудования, совместимости, удобства установки, удобства обслуживания, надежности, восстановления, документации, процедуры.
Отладка — это процесс локализации (определения оператора программы, выполнение которого вызвало нарушение вычислительного процесса) и исправления ошибок, обнаруженных при тестировании ПО. Для исправления ошибки необходимо определить ее причину. Отладка требует от программиста глубоких знаний специфики управления используемыми техническими средствами, операционной системы, среды и языка программирования, реализуемых процессов, природы и специфики ошибок, методик отладки и соответствующих программных средств; психологически дискомфортна (нужно искать собственные ошибки в условиях ограниченного времени); оставляет возможность взаимовлияния ошибок в разных частях программы. Четко сформулированные методики отладки отсутствуют. Различают:
синтаксические ошибки – сопровождаются комментарием с указанием их местоположения, фиксируются компилятором (транслятором) при выполнении синтаксического и частично семантического анализа;
ошибки компоновки — обнаруживаются компоновщиком (редактором связей) при объединении модулей программы;
ошибки выполнения — обнаруживаются аппаратными средствами, операционной системой или пользователем при выполнении программы, проявляются разными способами и в свою очередь делятся на группы:
ошибки определения исходных данных (ошибки передачи, ошибки преобразования, ошибки перезаписи и ошибки данных);
логические ошибки проектирования (неприменимый метод, неверный алгоритм, неверная структура данных, другие) и кодирования (ошибки некорректного использования переменных, вычислений, межмодульного интерфейса, реализации алгоритма, другие);
ошибки накопления погрешностей результатов вычислений (игнорирование ограничений разрядной сетки и способов уменьшения погрешности).
Отладка программы в любом случае предполагает обдумывание и логическое осмысление всей имеющейся информации об ошибке. Большинство ошибок можно обнаружить по косвенным признакам посредством тщательного анализа текстов программ и результатов тестирования без получения дополнительной информации с помощью следующих методов:
ручного тестирования (при обнаружении ошибки нужно выполнить тестируемую программу вручную, используя тестовый набор, при работе с которым была обнаружена ошибка);
индукции (основан на тщательном анализе симптомов ошибки, которые могут проявляться как неверные результаты вычислений или как сообщение об ошибке);
дедукции (вначале формируют множество причин, которые могли бы вызвать данное проявление ошибки, а затем анализируя причины, исключают те, которые противоречат имеющимся данным);
обратного прослеживания (для точки вывода неверного результата строится гипотеза о значениях основных переменных, которые могли бы привести к получению данного результата, а затем, исходя из этой гипотезы, делают предположения о значениях переменных в предыдущей точке).
Для получения дополнительной информации об ошибке выполняют добавочные тесты и используют специальные методы и средства: отладочный вывод; интегрированные средства отладки; независимые отладчики.
Общая методика отладки программных продуктов, написанных для выполнения в операционных системах MS DOS и Win32:
1 этап — изучение проявления ошибки;
2 этап – определение локализации ошибки;
3 этап — определение причины ошибки;
4 этап — исправление ошибки;
5 этап — повторное тестирование.
Процесс отладки можно существенно упростить, если следовать основным рекомендациям структурного подхода к программированию:
программу наращивать «сверху-вниз», от интерфейса к обрабатывающим подпрограммам, тестируя ее по ходу добавления подпрограмм;
выводить пользователю вводимые им данные для контроля и проверять их на допустимость сразу после ввода;
предусматривать вывод основных данных во всех узловых точках алгоритма (ветвлениях, вызовах подпрограмм).
Дополнительную информацию по теме можно получить в [1, 2, 4, 7, 9, 14, 15].
Воспользуйтесь поиском по сайту:
studopedia.org — Студопедия.Орг — 2014-2023 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.006 с) .
Источник: studopedia.org
Тестирование, отладка и оптимизация
(В литературе часто этот этап просто называют тестированием). На этом этапе производится всесторонняя проверка программ. По поводу того как должно выполняться тестирование, среди разных программистов нет еденного мнения, но они единодушны в том, как тестирование не должно выполняться. Тестирование программы (или ее отдельных модулей) не должен выполнять программист (или группа программистов), создавший эту программу (модуль).
Рассмотрим этот этап более подробно. Существуют три аспекта проверки программы на:
Проверка правильности (верификация программы) удостоверяет, что программа делает в точности то, для чего она была предназначена. Качественная программа – это программа, выполняющая заранее объявленные действия известным способом и не выполняющая никаких необъявленных действий.
Статистика свидетельствует, что стоимость такого тестирования программного продукта составляет не менее 50 процентов стоимости начальной разработки и 70 процентов всей стоимости поддержки программного продукта. Но сколько бы сил и денег не было потрачено на тестирование необходимо понимать, что тесты могут доказать наличие ошибок в программе, но они не могут доказать их отсутствия.Один из общих законов программирования гласит, что ни одна программа не дает желаемых результатов при первой попытке ее трансляции и выполнения.
На рисунке изображена диаграмма процентного соотношения причин появления тех или иных ошибок при обработке данных.
Из диаграммы видно, что большинство ошибок совершаются именно на этапе кодирования.
Существуют два типа программных ошибок: синтаксические и семантические. Синтаксические ошибки возникают из-за нарушений правил (лексики) языка программирования и выявляются во время компиляции. Такие ошибки могут быть исключены сравнительно легко. Большинство из них можно выявить путем простого просмотра текста программы.
Чаще всего программисты оставляют этот этап компилятору, однако сквозной просмотр текста иногда бывает полезен. Скорость исправления ошибок, выявленных компилятора зависит от степени знакомства программиста с данным языком. Семантические или логические ошибки приводят к некорректным вычислениям или ошибкам во время выполнения программы (run-time error).
Математическая безупречность алгоритма не гарантирует правильности его перевода в программу. Аналогично разумный вид получаемых результатов не дает достаточной гарантии правильности программы. В общем случае нельзя дать общего решения для проведения проверки на правильность программы.
Конечно, самым лучшим способом тестирования программы является поставка ее пользователю сразу же после завершения программирования. Единственное слабое место такого метода – этот пользователь больше никогда не купит у вас не одной программы. Выявление и устранение ошибок часто имеет циклический характер. Устранение одной ошибки может породить другую ошибку.Особенно это касается работы с глобальными переменными.
Как правило, устранение таких ошибок заключается в разработке и проведении наборов тестов, то есть выполнении программы с тщательно подобранными проверочными данными для которых известен правильный ответ. При подготовке к тестированию следует придерживаться следующих правил:
1.Чем раньше спроектирован тест, тем вероятнее выявление ошибок. Поэтому лучше готовить тесты еще на этапе проектирования системы.
2.Недопустима хаотичность процесса тестирования. Он должен быть документирован и полностью управляем.
3.Необходимы повторяемость и завершенность тестов.
4.Следует избегать добавления новых тестов в процессе тестирования.
Первым шагом семантической проверки является ручной прогон, то есть программист моделирует прохождение данных через его программу с помощью карандаша и листа бумаги. Это скучная и утомительная работа, однако большинство ошибок может быть выявлено именно на этой стадии.
Разумеется, таким образом нельзя проверить всевозможные комбинации данных. Однако можно проверить всевозможные типы или наиболее вероятные комбинации данных. Если они дают правильные результаты, предполагается, что непроверенные комбинации также дали бы правильные результаты. Отдельно тестируется каждый модуль программы. Если программа хорошо спроектирована, то после этого остается проверить только интерфейс между модулями.
Следует особо подчеркнуть, что первоначальное тестирование процедур модуля выполняется программистом путем написание коротких «программок», которые вызывают процедуры в различными наборами параметров. Начинающему программисту такой подход может показаться очень расточительным с точки зрения расходования рабочего времени, но это единственный способ более или менее эффективной борьбы с ошибками в программе.
Очень часто тесты (файлы с тестовыми данными) создаются вручную. Следовательно, их число редко превышает два-три десятка. Иногда применяют генераторы тестовых данных – специальные программы, формирующие данные в соответствии со спецификациями задаваемыми программистами. Данные могут группироваться в записи, имеющие установленные форматы. Тестовые данные могут также систематически или случайно выбираться из другого заданного набора данных для уменьшения их общего количества, над которыми выполняется тест.
Кроме того, необходимо на завершающем этапе тестирования следует прогнать программу на реальном объеме данных и посмотреть насколько интерфейс программы выдержит такую нагрузку. (Очень часто программа прекрасно работающая для двух десятков записей в базе данных через год, когда база будет насчитывать сотни тысяч записей, будет выполняться несколько минут).
Если прогон программы на тестовых данных дает неверный результат, то необходимо найти и исправить ошибку. При отладкепрограммыиспользуют три основных способа:
-распечатка текущего состояния
Распечатка текущего состояния используется с целью фиксации фактических значений переменных для проверки хода вычислений. Для этого во время отладки программы в местах, которые программист считает критическими, помещают функции вывода на экран текущего состояния переменных. После окончания теста вызовы этих функций удаляются и программа снова перекомпилируется.
Метод «точки останова» обычно применяют при разного рода зацикливаниях. В текст программы включают функции останова программы, например можно вывести на экран сообщение «Достигнута точка n» и вызвать функцию getch(). Этот метод имеет смысл объединять с методом деления пополам. Точка останова ставится в средине программы, если программа выполнилась до этой точки, что точка останова ставиться в средине второй половины программы, если нет, то в средине первой и т.д. Таким образом область поиска ошибки постепенно сужается.
Трассировка – это пошаговое выполнение программы с возможностью просматривать состояние всех переменных. Она может оказаться очень эффективной, но значительно замедляет выполнение программы и не будучи тщательно спланированной, приводит к колоссальным объемам выдаваемой информации.
Проверка вычислительной сложности, как правило, заключается в экспериментальном анализе сложности алгоритма или экспериментальном сравнении двух алгоритмов и более, решающих одну и ту же задачу. (Будет подробнее рассмотрена в последующих темах курса)
Проверка эффективности реализации (оптимизация) направлена на отыскание способа заставить правильную программу работать быстрее или расходовать меньше памяти. Теоретически, оптимизация не является обязательным условием разработки программы. Множество программ может быть поставлено (и поставляется) сразу же после отладки.
Однако существует целый ряд программ, критичных как к скорости выполнения, так и к размеру. К таким программам относятся, например, программы графического вывода в силу большого объема вычислений, связанных с графическими преобразованиями. Очевидно, что оптимизация должна проводиться опытными программистами, хорошо знакомыми с тонкостями языка и компилятора. Поэтому сегодня чаще оптимизируются только фрагменты программы, влияющие на скорость вывода на экран изображений.
При проектировании больших систем оптимизацию производится в два этапа. Сначала оптимизируется текст программы на языке высокого уровня, а затем наиболее критичные ко времени выполнения процедуры переписывают на языке ассемблера.
Чтобы улучшить программу, пересматриваются результаты реализации в процессе построения алгоритма. Не рассматривая все возможные варианты и направления оптимизации программ, приведем здесь некоторые полезные способы, направленные на увеличение скорости выполнения программ.
Первый способ основан на следующем правиле. Сложение и вычитание выполняются быстрее, чем умножение и деление.Целочисленная арифметика быстрее арифметики вещественных чисел. Таким образом, X+X лучше, чем 2*X, а (2i+j)*0,5 хуже, чем (i+i+j)*0,5. Умножение выолняется быстрее чем деление, например sum*=0,5 лучше чем sum/=2;При выполнении операций над целыми числами следует помнить, что благодаря применению двоичной системы счисления умножение числа, кратные двум, можно заменить соответствующим количеством сдвигов влево. Поэтому 10*А выполняется дольше, чем (A
Второй способ заключается вудалении избыточных вычислений.
Пример, вычисление квадратных корней уровнения
Лучшим решением является следующее
Легко увидеть, что в первом случае потребовалось выполнить четыре операции сложения/вычитания, восемь операций умножения, две операции деления, два вызова функции sqrt, во втором — пять операций сложения/вычитания, два умножения, два деления и одно обращение к функции sqrt.
Третий способ проверки эффективности реализации основан на способности некоторых компиляторов строить коды для вычисления логических выражений так, что вычисления прекращаются, если результат становится очевидным. Например, в выражении A||B||C, если A имеет значение «истина», то переменные В и С уже не проверяются. Таким образом, можно сэкономить время, разместив переменные A,B,С так, чтобы первой стояла переменная, которая вероятнее всего будет истинной, а последней та, которая реже всего принимает истинное значение.
Однако следует быть осторожным в следующем примере: ROOL(A)||B||C. ROOL(A) может и чаще принимает значение «истина», но представляет собой вызов функции, возможно выполняющей сложные и длительные вычисления. Тогда может оказаться, что запись В||С||ROOL(A) является более эффективной.
Четвертый прием — исключение циклов.
Пример. Рассмотрим следующий пример: сформировать одномерный массив, каждый элемент которого должен быть равен сумме элементов строки двумерного массива.
можно переписать так
В данном пример выигрыш достигается, во-первых, за счет уменьшения количества циклов (два, а не три), а во-вторых, за счет того, что с введением временной переменной b уменьшено количество операций вычисления адресов элементов массива.
Пятый прием – развертывание циклов.
Пример. Следующий фрагмент
можно переписать так:
Выигрыш в скорости вычислений вполне очевиден.
Шестой прием – разгрузка участков повторяемости, то есть вынос из циклов выражений, которые могут быть вычислены вне циклов.
В данном случае используется так называемая чистка цикла вверх.Однако в следующем примере таким образом нельзя разгрузить цикл:
Действительно, при вычислении значений переменных с и a используется переменная x, значение которой вычисляется в цикле. Однако, значение переменных все равно определяется значением переменной x, вычисленной на последней итерации цикла. Поэтому эффективнее переписать данный фрагмент следующим образом, применяя чистку цикла вниз:
Кроме указанных способов оптимизации полезно производить чистку программы, то есть удаление из нее ненужных объектов и конструкций:
-удаление идентичных операторов;
-удаление несущественных операторов, то есть операторов не влияющих на результат программы;
-удаление бесполезных операторов, вычисляющих вспомогательные переменные, используемые только для постановки в другие выражения;
-удаление функций, к которым нет обращений;
-удаление объявленных, но неиспользуемых переменных, операций и т.д.
Также существует ряд способов экономного расходования памяти:
-совмещение по памяти не существующих одновременно статических переменных, то есть несвязанные переменные следует объявлять в различных модулях, а не в теле главной программы.
-изменение времени жизни переменной
-перемещение оператора объявление переменной ближе к фрагменту, где переменная используется
-экономия стека: при передаче массива в качестве параметра подпрограммы, следует использовать указатель на массив.
Кроме того, следует делать текст программы более компактным (если это не приводит к ухудшению читабельности). Необходимо следить за дублированием в различных ветвях алгоритмов, и сокращать текст программы за счет оформления повторяющихся фрагментов текста в виде функций. Однако не следует слишком злоупотреблять созданием процедур: наличие большого количества процедур, состоящих из 2-3 операторов, вряд ли можно считать приемлемым.
Это далеко не полный перечень способов оптимизации. Здесь приведены лишь самые очевидные из них. Следует, кроме того, заметить, что не всегда стоит увлекаться погоней за быстродействием, так как при этом чаще ухудшается удобочитаемость программы.
Внедрение и сопровождение
Внедрение – это процесс запуска программы в промышленную эксплуатацию. Этот этап характерен для программ, разрабатываемых на заказ. При внедрении разработчик устанавливает продукт на компьютеры заказчика (инсталлирует его) и проверяет весь его рабочий цикл. Это этап эксплуатации системы. Если программа работает устойчиво, начинается этап обучения пользователей. (В договоре необходимо заранее указать объем учебных часов, которые разработчики должны посвятить обучению заказчика.)
Сопровождение – это процесс поддержки внедренной программы. Сопровождение предусматривает оказание консультаций, а также внесение необходимых изменений в программу. Каким бы изощренным ни было тестирование программ, к сожалению, в больших программных комплексах чрезвычайно тяжело устранить абсолютно все ошибки.
Устранение обнаруженных при сопровождении — задача этого этапа. По мере выявления и исправления ошибок в ходе сопровождения их количество постепенно уменьшается. Однако через какое-то время кривая ошибок вновь начинает расти. Можно предположить, что происходить нечто вроде интерференции волн различной частоты – два процесса накладываются друг на друга, приводя систему к краху. Первый процесс – порождение новых ошибок при исправлении предыдущих, второй – повышение квалификации пользователей при работе с программой и как следствие использование ими тех возможностей программы, которые они раньше не использовали.
Выполняемый в ходе сопровождения анализ опыта эксплуатации программы позволяет обнаруживать узкие местам или неудачные проектные решения в тех или иных частях программного комплекса. В результате такого анализа может быть принято решение о проведении работ по совершенствованию разработанной системы. Кроме описанного выше сопровождение может включать в себя проведение консультаций, обучение пользователей системы, оперативное снабжение пользователей информацией о новых версиях системы и т.п. Качественное проведение этапа сопровождения в большой степени определяет коммерческий успех программного продукта.
Все исправления, вносимые на этапе сопровождения приводят к изменю структуры программы в сторону ее ухудшения и в конечном счете к дезорганизации системы. В конце концов, наступает момент, когда дальнейшее исправление ошибок в программе теряет всякий смысл. С этого момента, можно считать, что программа умерла.
На самом деле, незначительное число программ доживают до собственной «смерти». Чаще программа заменяется на новую или новую версию данной. Новая версия программы обычно учитывает ошибки предыдущей, а также дополнительные требования, возникшие в связи с появлением новой техники и более глубоким осмыслением задачи пользователем.
Статьи к прочтению:
- Тестирование приводных механизмов
- Тип_результата id_функции(список параметров)
Оптимизация ПК. Поднятие производительности ПК. Увеличение скорости системы и поднятие FPS ФПС
Похожие статьи:
- Отладка и тестирование программного продукта Решение многих производственных и экономических задач связано с моделированием данных процессов, то есть созданием некой идеальной модели, в той или иной…
- Тестирование и отладка программ Для проверки правильности функционирования программы выполняется тестирование. Тестирование – это исполнение программы с использованием некоторого набора…
Источник: csaa.ru