Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Отладка и тестирование программ: основные подходы и ограничения (Методы тестирования)

Содержание:

ВВЕДЕНИЕ

При разработке учебных планов программистских факультетов большинства вузов подразумевается, что студенты-первокурсники уже умеют программировать. Однако, в школах, зачастую, не делается акцент на таких важных вопросах, как тестирование и отладка. Специалисты-профессионалы знают, что затраты на тестирование и отладку оцениваются в 50–60% всех затрат на разработку программы[1]. В общем смысле выражение «написать программу» означает написать программный код без ошибок трансляции. Зачастую вопрос проверки соответствия программы поставленной задаче, поиска и исправления смысловых ошибок не поднимается в принципе. По большему счету это может происходить в силу отсутствия понятной и однозначной методики тестирования и отладки программ. [1]

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

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

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

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

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

  • определить суть понятий «тестирование» и «отладка»;
  • изучить методики выявления ошибок;
  • изучить методики исправления ошибок;
  • провести практическое исследование на предмет отладки приложений в среде Delphi.

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

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

ГЛАВА 1 СУЩНОСТЬ ТЕСТИРОВАНИЯ И ОТЛАДКИ. МЕТОДИКА ВЫЯВЛЕНИЯ ОШИБОК

«Единственная ошибка - не исправлять своих прошлых ошибок».

Конфуций

1.1 Определение понятий «тестирование» и «отладка»

Большая часть работы программистов связана с написанием исходного кода, тестированием и отладкой программ на одном из языков программирования. [1][2].

Программа – это последовательность команд компьютера, приводящая к решению задачи. Программа является результатом интеллектуального труда, для которого характерно творчество. Хотя программирование в значительной степени искусство, тем не менее, можно систематизировать и обобщить накопленный профессиональный опыт. [2] Проектирование и разработку программ целесообразно разбить на ряд последовательных этапов: 1) постановка задачи; 2) проектирование программы; 3) построение модели; 4) разработка алгоритма; 5) написание программы; 6) отладка программы; 7) тестирование программы; 8) документирование[3].

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

Тестирование — это выполнение программы с целью обнаружения факта наличия в программе ошибки. [3]

Отладка — это определение места ошибки и внесение исправлений в программу[5]. Исходя из определений данных терминов, между ними существует прямая взаимосвязь, а, следовательно, и необходимость их выполнения на завершающих этапах разработки программы. [1]

Тестирование и отладка тесно связаны с понятием «жизненный цикл программного обеспечения». Это весь период времени существования системы программного обеспечения, начиная от выработки первоначальной концепции этой системы и кончая ее моральным устареванием. [2]

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

Рисунок 1. Жизненный цикл программного обеспечения

Упрощённо место тестирования и отладки в структуре жизненного цикла программного обеспечения можно представить следующим образом[7]:

разработка = анализ + проектирование + программирование
(кодирование) + тестирование + отладка [3]

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

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

Согласно статистическим данным, около 50% стоимости начальной разработки составляет тестирование[8]. Сколько бы сил, времени и денег не было потрачено на тестирование, один из главных законов программирования действует с неотвратимостью рока: «Тесты могут доказать наличие ошибок в программе, но они не могут доказать их отсутствия» (Э. Дейкстра «Заметки по структурному программированию»). [4]

Существуют различные способы тестирования программ. Тестирование программы как «черного ящика» (стратегия «черного ящика» определяет тестирование с анализом входных данных и результатов работы программы). Критерием исчерпывающего входного тестирования является использование всех возможных наборов входных данных.

Тестирование программы как «белого ящика» заключается в стратегии управления логикой программы, позволяет использовать ее внутреннюю структуру. Критерием выступает исчерпывающее тестирование всех маршрутов и управляющих структур программы. Разумная и реальная стратегия тестирования – сочетание моделей «черного» и «белого ящиков»[9].

Программные ошибки можно разделить на два класса: синтаксические (синтаксис языка программирования) и алгоритмические (логические).

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

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

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

  • правильные входные данные;
  • неправильные (ошибочные входные значения).

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

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

Определённое представление о фактических причинах ошибок в работе программы может дать процентное соотношение источников сбоев (рис. 2).

Рисунок 2. Соотношение источников программных сбоев (в %)

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

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

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

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

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

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

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

1.2 Методы тестирования

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

Цикл должен выполняться один раз, ни разу, максимальное число раз. Такое тестирование всех путей извне также недостижимо. В программе из двух последовательных циклов, внутри каждого из которых включено ветвление на десять путей имеется 1018 путей расчета. Чтобы построить разумную стратегию тестирования надо разумно сочетать оба этих подхода и пользоваться математическими доказательствами. Восходящее тестирование. Сначала автономно тестируются модули нижних уровней, которые не вызывают других модулей. При этом достигается такая же их высокая надежность, как и у встроенных в компилятор функций. Затем тестируются модули более высоких уровней вместе с уже проверенными модулями и так далее по схеме иерархии. [4]

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

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

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

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

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

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

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

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

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

• Верификация программы - попытка найти ошибки, выполняя программу в тестовой или моделируемой среде.

• Испытание – попытка найти ошибки, выполняя программу в заданной программной среде.

• Приемо-сдаточные испытания – проверка пригодности программы для эксплуатации; такие испытания обычно проводят под контролем поставщика системы. По назначению тесты классифицируются:

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

• тестирование сопряжений - контроль сопряжений между частями программной системы, как между компонентами в комплексе, так и между модулями отдельного компонента (например, у заглушки);

• комплексное тестирование — контроль и испытание системы по отношению к исходным целям. Осуществляется с целью проверки правильной совместной работы составных частей программы. При комплексном тестировании особое внимание обычно уделяется взаимодействию компонентов. Комплексное тестирование является процессом контроля, если оно выполняется в условиях моделируемой среды, и процессом испытания при выполнении в реальной среде; [4]

• системное тестирование - при системном тестировании вся система в целом обычно рассматривается как некоторый «черный ящик»; поведение этой системы исследуют, не вникая в подробности отдельных ее компонентов и взаимодействий между ними;

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

1.3 Сущность и методика отладки программ. Виды ошибок

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

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

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

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

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

Выражение: Total := Summa + Summa + Summa; эффективнее выражения: Total := 3 * Summa; а операцию деления Summa := Summa/2; лучше заменить на более быстрое умножение, которое приведет к тому же самому результату Summa := Summa * 0.5;

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

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

2)Изменение области существования переменной.

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

4)Экономия стека: при передаче массива в качестве параметра подпрограммы, следует использовать ссылку на массив. Помимо экономии памяти это приводит также и к экономии времени за счет того, что система не создает копии передаваемого массива в стеке.

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

Отладка программного обеспечения[12]

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

Отладка не является разновидностью тестирования, хотя слова «отладка» и «тестирование» часто используют как синонимы. Под ними подразумеваются разные виды деятельности:

- тестирование — деятельность, направленная на обнаружение ошибок;

- отладка направлена на установление точной природы известной ошибки, а затем - на исправление этой ошибки;

- результаты тестирования являются исходными данными для отладки.

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

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

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

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

Отладку можно разделить на синтаксическую и семантическую.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2.2 Применение точек остановки и модификация локальных переменных

В коде любого созданного приложения обязательно будут ошибки. Если говорить о синтаксических ошибках, которые вызваны неверным вводом команд в редакторе, либо неверной записью идентификаторов и иными неверными действиями программиста, то они почти всегда фиксируются самим компилятором Delphi. Следует постоянно обращать внимание на различные сообщения и предупреждения, выдаваемые при прогоне программы, это может помочь обнаружить найти ошибку в тексте кода. Но многие ошибки связаны с тем, что неточно реализована логика самого алгоритма. Такие дефекты обнаруживаются только во время выполнения контрольных примеров. Так бывает например, когда вместо символа "<" ошибочно введен символ "<=". Если вдруг исходный алгоритм реализуется неправильно, то работоспособность приложения может быть даже, и не нарушено, но результаты будут выдаваться неверные или программой будут выполняться неверные действия. Поэтому и обнаруживаются подобные ошибки лишь на этапе отладки.

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

Из всех инструментов встроенного отладчика наиболее часто используются точки остановки - BreakPoint. После установки точки, приложение будет работать до тех пор, пока не достигнет ее, после чего работа программы будет остановлена и управление переходит к отладчику Delphi. Точки остановки удобнее всего снимать и ставить нажатием горячей клавиши «F5», либо зайти в меню «Debug->Toggle breakpoint», либо другими способами.

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

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

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

var

Form1: TForm1;

A: Integer;

B: Integer = 123;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin

Inc(A);

Inc(A);

Inc(A, B);

Inc(A);

Inc(A);

ShowMessage(IntToStr(A));

ShowMessage(IntToHex(A, 8));

end; [4]

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

Получается следующая картина: точка установки стоит на строчке Inc(A). В специальном окне «Local Variables», можно видеть значения всех используемых локальных переменных процедуры создания формы, а также переменной Self, передающейся неявно и всегда присутствующей в методах класса и параметра Sender.

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

Для просмотра и изменения значения переменной в отладчике Delphi существуют два инструмента. Можно вызвать специальное окно «Evaluate/Modify» через меню или с помощью горячей клавиши «Ctrl+F7». Этот инструмент очень простой и используется в большинстве чаще всего. Выглядит он примерно так:

Чтобы изменить значение переменной A, необходимое нам значение вводится в поле «New value». Далее жмем «Enter» или кнопку «Modify».

Другой инструмент «Inspect» вызывается из диалога «Evaluate/Modify». Он является уже более продвинутым редактором значений переменных. Вызвать его можно и через меню «Run».

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

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

Изменив значение переменной A на правильное, можно продолжить выполнение нашей программы нажав «F9» или «Run». После произведенных действий при помощи отладчика, процедура возвратит нужные значения. Теперь можно спокойно исправлять код процедуры, т.е. присвоить переменной A значение 1 – «A:= 1».

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

Он предоставит доступ ко всем свойствам объекта, которые нуждаются в изменении. [2]

2.3 Пошаговая трассировка приложения

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

Наименование команды

Горячая клавиша

Действие отладчика

«Trace Into»

«F7»

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

«Step Over»

«F8»

аналогично «Trace Into», но вход в тело вызываемой процедуры не происходит.

продолжение таблицы

Наименование команды

Горячая клавиша

Действие отладчика

«Trace to Next Source Line»

«Shift+F7»

полный аналог первой команды, но используется в окне «CPU-View»

«Run to Cursor»

«F4»

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

«Run Until Return»

«Shift+F8»

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

«Set Next Statement»

«Shift+F4»

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

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

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

Опция «Record field alignment» устанавливает выравнивание неупакованных записей. Эту опцию можно изменять в процессе кодирования модуля при помощи директив «{$A x}», либо «{$Align x}».

А вот в группе «Syntax options» все опции лучше оставить по умолчанию, чтобы компилятор работал нормально.

В группе параметров «Runtime errors» есть параметр «Range checking», который очень важен для отладки проектов. Этот параметр проверяет границы во время доступа к массивам данных.

Это один из наиболее востребованных параметров при отладке приложения. Он отвечает за проверку границ при доступе к массиву данных. В случае ошибки в границах блока при попытке записи в него – возможно даже разрушение памяти программы. Кроме этого данная опция контролирует возможность выхода за границы допустимого диапазона значений для локальных переменных. Поэтому производить отладку проекта всегда необходимо при включенной опции «Range checking». Параметр «Overflow cheking» работает аналогично, но только там, где используются арифметические операции с переменными (также желательно включить).

Если необходимо в отдельных модулях отключать проверку переполнения, как например, в алгоритмах шифрования, то в данных (отдельных) модулях используется директива «{$OVERFLOWCHECKS OFF}».

Группа параметров «Debugging» включает параметры, влияющие лишь на полноту отладочной информации в DCU-файлах. Исключение составляет лишь параметр «Assertions», включающий в работу процедуру Assert().

В целом рекомендуется во время отладки приложений устанавливать все параметры из групп «Runtime errors» и «Debugging» включенными, а отключать их уже при заключительной компиляции готового приложения. В Delphi 7 и ниже это приходится делать вручную, а более новых студиях есть хорошая поддержка билдов проекта, где персонально для отдельных видов сборок можно выставлять все необходимые опции.

Вторым по важности инструментом при отладке приложений является окно «Call Stack» второй по значимости. Оно содержит описание всех вызовов до возникновения исключения, ошибки или прерывания в точке остановки.

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

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

Помимо кода программы приходится работать также с данными различных типов и областями памяти. В отладчике, при помощи «Data breakpoint», предусмотрена возможность устанавливать точки остановки на адреса, указывающие ячейки памяти. Это делается через «Watch List» или в окне «Breakpoint List» при помощи «Add Breakpoint->Data Breakpoint», где, в диалоге, следует указать адрес области памяти, ее размер, либо или имя нужной переменной. Если мы указываем имя переменной, то отладчик будет пытаться отыскать ее в памяти и установить точку остановки. Адрес памяти где содержится значение переменной меняется при каждом новом запуске программы, поэтому получить значение довольно сложно. [4]

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

Нужно отметить, что отладчик Delphi не является профессиональным средством отладки сторонних приложений. Столь важный и удобный инструмент как «Memory Breakpoint» имеет урезанный вариант. Там сохранена лишь возможность контролировать адрес памяти на запись. [6] Но, тем не менее, даже в очень урезанном варианте он является хорошим инструментом для контроля изменений в памяти приложения, конкретно для поиска ошибок при адресной арифметике.

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

ЗАКЛЮЧЕНИЕ

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

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

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

В заключении себе и другим будущим программистам хочу дать следующие рекомендации:

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

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

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

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

Модули должны подключаться к приложению только один раз; замена модулей существенно усложняет тестирование.

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

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

1. Основы алгоритмизации и программирования: учеб. пособие / Т.А.

Жданова, Ю.С. Бузыкова. – Хабаровск : Изд-во Тихоокеан. гос.ун-та, 2011. –

56 с. Режим доступа:

http://pnu.edu.ru/media/filer_public/2013/02/25/book_basics.pdf.

2. Программирование и основы алгоритмизации: Для инженерных

специальностей технических университетов и вузов. /А.Г. Аузяк, Ю.А.

Богомолов, А.И. Маликов, Б.А. Старостин. Казань: Изд-во Казанского

национального исследовательского технического ун-та - КАИ, 2013, 153 с.

Режим доступа: http://au.kai.ru/documents/Auzyak_Progr_osn_alg_C_2013.pdf.

3. Основы алгоритмизации и программирования : учебное пособие / Г.

Р. Кадырова. – Ульяновск : УлГТУ, 2014. – 95 с. . Режим доступа:

http://venec.ulstu.ru/lib/disk/2014/137.pdf

4. Основы алгоритмизации и программирования. Курс лекций. Режим

доступа:

http://lib.ssga.ru/fulltext/UMK/исходные%20для%20Кацко/заменить%20полно

стью/Информатика/лекции/13%20Основы%20алгоритмизации%20и%20прог

раммирования.pdf

5. Белов П.М. Основы алгоритмизации в информационных системах:

Учебн. Пособие.- Спб.: СЗТУ, 2003. – 85с. Режим доступа:

http://www.ict.edu.ru/ft/005406/nwpi225.pdf

6. Основы алгоритмизации и программирования: Метод. указ. / Сост.:

И.П. Рак, А.В. Терехов, А.В. Селезнев. Тамбов: Изд-во Тамб. гос. техн. ун-та.

Режим доступа: http://www.ict.edu.ru/ft/004758/terehov.pdf.

7. Макаров В.Л. Программирование и основы алгоритмизации.: учебн.

пособие.-Спб., СЗТУ, 2003, - 110с. Режим доступа:

http://window.edu.ru/resource/126/25126/files/nwpi223.pdf

8. Плаксин М. А. Тестирование и отладка программ для профессионалов будущих и настоящих [Электронный ресурс] / М. А. Плаксин. — 3-е изд. (эл.). — Электрон. Текстовые дан. (1 файл pdf : 170 с.). — М. : БИНОМ. Лаборатория знаний, 2015

9. Соловьев С.В. Технология разработки прикладного программного обеспечения: учеб. пособие // С. В. Соловьев, Л. С. Гринкруг, Р. И. Цой; М-во образования и науки Рос. Федерации, Дальневост. гос. социал.-гуманитар. акад., Каф. техн. дисциплин. - М.: Изд. дом Акад. естествознания. - 2011. - 407с.: ил. Режим доступа: https://www.monographies.ru/ru/book/view?id=141

  1. Плаксин М. А. Тестирование и отладка программ для профессионалов будущих и настоящих [Электронный ресурс] / М. А. Плаксин. — 3-е изд. (эл.). — Электрон. Текстовые дан. (1 файл pdf : 170 с.). — М. : БИНОМ. Лаборатория знаний, 2015. Стр. 5

  2. Основы алгоритмизации и программирования : учебное пособие / Г.Р. Кадырова. – Ульяновск : УлГТУ, 2014. – 95 с. Стр. 24.

  3. Там же, стр. 35-36.

  4. Основы алгоритмизации и программирования. Курс лекций. Стр. 2.

  5. Плаксин М. А. Тестирование и отладка программ для профессионалов будущих и настоящих [Электронный ресурс] / М. А. Плаксин. — 3-е изд. (эл.). — Электрон. Текстовые дан. (1 файл pdf : 170 с.). — М. : БИНОМ. Лаборатория знаний, 2015. Стр. 10.

  6. Основы алгоритмизации и программирования. Курс лекций. Стр. 3.

  7. Технология разработки программного обеспечения: конспект лекции / сост. И.И. Савенко; Томский политехнический университет. – Томск: Изд-во Томского политехнического университета, 2014. – 67 с. Стр. 7.

  8. Основы алгоритмизации и программирования. Курс лекций. Стр. 36.

  9. Основы алгоритмизации и программирования : учебное пособие / Г.Р. Кадырова. – Ульяновск : УлГТУ, 2014. – 95 с. Стр. 36.

  10. Основы алгоритмизации и программирования. Курс лекций. Стр. 35-42.

  11. Белов П.М. Основы алгоритмизации в информационных системах: Учебн. Пособие.- Спб.: СЗТУ, 2003. – 85с. Стр. 42.

  12. http://www.tehprog.ru/index.php_page=lecture0111.html