Меню

Выявление ошибок системных компонентов лекция

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

Меры по обнаружению ошибок можно разбить на две подгруппы:

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

Пассивное обнаружение ошибок

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

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

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

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

3. Избыточность. Все средства обнаружения ошибок основаны на некоторой форме избыточности (явной или неявной).

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

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

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

· Проверяйте, находится ли входное значение в установленных пределах. Например, если входной элемент — адрес в основной памяти, проверяйте его

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

· Проверяйте допустимость всех вариантов значений. Если входное поле — код, обозначающий один из десяти районов, никогда не предполагайте, что если это не код ни одного из районов 1, 2,…, 9, то это обязательно код района 10.

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

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

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

Когда разрабатываются меры по обнаружению ошибок, важно принять согласованную стратегию для всей системы (т.е. применить идею концептуальной целостности). Действия, предпринимаемые после обнаружения ошибки в программном обеспечении (например, возврат кода ошибки), должны быть единообразными для всех компонент системы. Это ставит вопрос о том, какие именно действия следует предпринять, когда ошибка обнаружена. Наилучшее решение — немедленно завершить выполнение программы или (в случае операционной системы) перевести ЦП в состояние ожидания. С точки зрения предоставления человеку, отлаживающему программу, например системному программисту, самых благоприятных условий для диагностики ошибок немедленное завершение представляется наилучшей стратегией. Конечно, во многих системах подобная стратегия бывает нецелесообразной (например, может оказаться, что приостанавливать работу системы нельзя). В таком случае используется метод регистрации ошибок. Описание симптомов ошибки и «моментальный снимок» состояния системы сохраняется во внешнем файле, после чего система может продолжать работу. Этот файл позднее будет изучен обслуживающим персоналом. Такой метод использован в операционной системе OS/VS2MVS фирмы IBM. Каждая компонента содержит программу восстановления, которая перехватывает все случаи ненормального

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

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

Пример: система PRIME

Система PRIME-это мультипроцессорная система с виртуальной памятью, разработанная в Калифорнийском университете в Беркли. Один из процессоров системы выделен в качестве центрального процессора и содержит центральный управляющий монитор (ССМ — central control monitor) — управляющую программу, которая распределяет страницы памяти и пространство на диске, назначает программы другим процессорам (проблемным процессорам) и регулирует пересылки всех межпроцессорных сообщений. Расширенный управляющий монитор (ЕСМ — extended control monitor) — это реализованная микропрограммно-управляющая программа, постоянно присутствующая в каждом процессоре и управляющая диспетчеризацией процессов, операциями ввода-вывода и посылки / получения.

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

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

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

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

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

Активное обнаружение ошибок

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

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

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

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

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

Пример: программа обнаружения разрушений, разработанная фирмой TRW

Система защиты ресурсов фирмы IBM — это экспериментальная модификация операционной системы OS/360 для изучения проблем, связанных с системами защиты. Используя ее, корпорация TRW разработала монитор, действующий в заранее установленные интервалы времени и пытающийся обнаружить признаки того, что программа пользователя нарушила правила защиты.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ПРОВЕРКА
ПРАВИЛЬНОСТИ ПРОГРАММ.

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

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

Все
принципы и методы разработки надежного
программного обеспечения можно разбить
на четыре группы:

1.
Предупреждение ошибок.

2.
Обнаружение ошибок.

3.
Исправление ошибок.

4.
Обеспечение устойчивости к ошибкам.

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

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

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

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

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

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

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

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

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

Аттестация
— авторитетное подтверждение правильности
программы. При тестировании с целью
аттестации выполняется сравнение с
некоторым заранее определенным
стандартом.

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

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

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

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

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

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

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

8.2.
Базовые правила тестирования.

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

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

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

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

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

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

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

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

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

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

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

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

8.3.
Отладка.

Рекомендуемый
подход к методам отладки аналогичен
особенностям проектирования и включает
в себя следующие этапы:

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

2.
Разработайте план. Следующий шаг —
построить одну или несколько гипотез
об ошибке и разработать план проверки
этих гипотез.

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

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

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

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

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

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

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

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

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

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

Изучение
процесса отладки.

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

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

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

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

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

4.
Что следовало сделать при проектировании
или тестировании, чтобы предупредить
появление этой ошибки или обнаружить
ее раньше?

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

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

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

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