Главная страница
Навигация по странице:

  • 9.2. Ручной контроль программного обеспечения

  • Инспекции исходного текста.

  • 9.3. Структурное тестирование

  • Покрытие решений (переходов).

  • Покрытие решений/условий.

  • Комбинаторное покрытие условий.

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

  • Учебник Технология программирования. Технология программирования


    Скачать 7.85 Mb.
    НазваниеТехнология программирования
    АнкорУчебник Технология программирования.pdf
    Дата04.05.2017
    Размер7.85 Mb.
    Формат файлаpdf
    Имя файлаУчебник Технология программирования.pdf
    ТипДокументы
    #6946
    КатегорияИнформатика. Вычислительная техника
    страница23 из 27
    1   ...   19   20   21   22   23   24   25   26   27
    Формирование тестовых наборов. В соответствии с определением тестирования в начале данного параграфа, удачным следует считать тест, который обнаруживает хотя бы одну ошибку. С этой точки зрения хотелось бы использовать такие наборы тестов, каждый из которых с максимальной вероятностью может обнаружить ошибку.
    Формирование набора тестов имеет большое значение, поскольку тестирование является одним из наиболее трудоемких этапов (от 30 до 60 % общей трудоемкости) создания программного продукта. Причем доля стоимости тестирования в общей стоимости разработки имеет тенденцию возрастать при увеличении сложности программного обеспечения и повышении требований к их качеству.
    Существуют два принципиально различных подхода к формированию тестовых наборов: структурный и функциональный.
    Структурный подход базируется на том, что известна структура тестируемого программного обеспечения, в том числе его алгоритмы («стеклянный ящик»). В этом случае тесты строят так, чтобы проверить правильность реализации заданной логики в коде программы.
    Функциональный подход основывается на том, что структура программного обеспечения не известна («черный ящик»), В этом случае тесты строят, опираясь на функциональные спецификации. Этот подход называют также подходом, управляемым данными, так как при его использовании тесты строят на базе различных способов декомпозиции множества данных.
    Наборы тестов, полученные в соответствии с методами этих подходов, обычно объединяют, обеспечивая всестороннее тестирование программного обеспечения.
    Более подробное рассмотрение перечисленных вопросов начнем с обсуждения методов ручного контроля.
    9.2. Ручной контроль программного обеспечения
    Ручной контроль, как указано выше, обычно используют на ранних этапах разработки.
    Все проектные решения, принятые на том или ином этапе, должны анализироваться с точки зрения их правильности и целесообразнос-

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

    инспекции исходного текста,

    сквозные просмотры,

    проверка за столом,

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

    участникам группы заранее выдается листинг программы и спецификация на нее;

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

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

    267 1. Контроль обращений к данным

    Все ли переменные инициализированы?

    Не превышены ли максимальные (или реальные) размеры массивов и строк?

    Не перепутаны ли строки со столбцами при работе с матрицами?

    Присутствуют ли переменные со сходными именами?

    Используются ли файлы? Если да, то при вводе из файла проверяется ли завершение файла?

    Соответствуют ли типы записываемых и читаемых значении?

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

    Правильно ли записаны выражения (порядок следования операторов)?

    Корректно ли выполнены вычисления над неарифметическими переменными?

    Корректно ли выполнены вычисления с переменными различных типов (в том числе с использованием целочисленной арифметики)?

    Возможно ли переполнение разрядной сетки или ситуация машинного нуля?

    Соответствуют ли вычисления заданным требованиям точности?

    Присутствуют ли сравнения переменных различных типов?
    3. Контроль передачи управления

    Будут ли корректно завершены циклы?

    Будет ли завершена программа?

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

    Существуют ли поисковые циклы? Корректно ли отрабатываются ситуации
    «элемент найден» и «элемент не найден»?
    4. Контроль межмодульных интерфейсов

    Соответствуют ли списки параметров и аргументов по порядку, типу, единицам измерения?

    Не изменяет ли подпрограмма аргументов, которые не должны изменяться?

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

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

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

    участникам заседания предлагают несколько тестов;

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

    при необходимости программисту задают вопросы о логике проектирования и принятых допущениях.
    В большинстве сквозных просмотров при выполнении самих тестов находят меньше ошибок, чем при опросе программиста.
    Проверка за столом. Исторически данный метод ручного тестирования появился первым, так как он не требует наличия группы специалистов. Это -проверка исходного текста или сквозные просмотры, выполняемые одним человеком, который читает текст программы, проверяет его на наличие возможных ошибок по специальному списку часто встречающихся ошибок и «пропускает» через программу тестовые данные. Исходя из принципов тестирования, проверку за столом должен проводить человек, не являющийся автором программы. Метод наименее результативен, так как проверка представляет собой полностью неупорядоченный процесс, при ней отсутствует обмен мнениями и здоровая конкуренция.
    Оценка программ. Этот метод непосредственно не связан с тестированием, но его использование также улучшает качество программирования. Его используют для анонимной оценки программы в терминах ее общего качества, простоты эксплуатации и ясности. Цель метода — обеспечить сравнительно объективную оценку и самооценку программистов.
    Такая оценка выполняется следующим образом. Выбирается программист, который должен выполнять обязанности администратора процесса. Администратор набирает группу от шести до 20-ти участников, которые должны заниматься разработкой сходных программ.
    Каждому участнику предлагается представить для рассмотрения две программы, с его точки зрения - наилучшую и наихудшую. Отобранные программы случайным образом распределяются между участниками. Им дают по четыре программы -две наилучшие и две наихудшие, но не говорят, какие программы плохие, а какие - хорошие. Программист просматривает эти программы и заполняет анкету, в которой оценивает качество программ по семибалльной шкале.

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

    не обнаруживают пропущенных маршрутов;

    не обнаруживают ошибок, зависящих от обрабатываемых данных, например, в операторе if (a - b) < eps - пропуск функции абсолютного значения abs проявится только, если a < b;

    не дают гарантии, что программа правильна, например, если вместо сортировки по убыванию реализована сортировка по возрастанию.
    Для формирования тестов программу представляют в виде графа, вершины которого соответствуют операторам программы, а дуги представляют возможные варианты передачи управления. Ниже приведен текст программы, которая определяет значение х в зависимости от значений параметров процедуры. Алгоритм этой программы представлен на рис. 9.2, а, а соответствующий граф передач управления - на рис. 9.2, б.
    Procedure m (a, b:real; var x:real) begin if (a>1) and (b=0) then x:=x/a; if (a=2) or (x>1) then x:=x+1; end;

    270
    Формирование тестовых наборов для тестирования маршрутов может осуществляться по нескольким критериям:

    покрытие операторов;

    покрытие решений (переходов);

    покрытие условий;

    покрытие решений/условий;

    комбинаторное покрытие условий.
    Покрытие операторов. Критерий покрытия операторов подразумевает такой подбор тестов, чтобы каждый оператор программы выполнялся, по крайней мере, один раз. Это необходимое, но недостаточное условие для приемлемого тестирования. Поясним сказанное примером.
    Для фрагмента, алгоритм и граф которого представлены на рис. 9.2, можно было бы выполнить каждый оператор один раз, задав в качестве входных данных а = 2, b = 0, х = 3. Но при этом из второго условия следует, что переменная х может принимать любое значение, и в некоторых версиях языка Pascal это значение проверяться не будет (!).
    Кроме того:

    если при написании программы в первом условии указано: (а > 1) ог (b = 0), то ошибка обнаружена не будет;

    271

    если во втором условии вместо х > 1 записано х > 0, то эта ошибка тоже не будет обнаружена;

    существует путь 1-2-4-6 (см. рис. 9.2, б), в котором х вообще не меняется и, если здесь есть ошибка, она не будет обнаружена.
    Таким образом, хотя при тестировании действительно необходимо задавать исходные данные так, чтобы все операторы программы были выполнены хотя бы один раз, для проверки программы этого явно недостаточно.
    Покрытие решений (переходов). Для реализации этого критерия необходимо такое количество и состав тестов, чтобы результат проверки каждого условия (т.е. решение) принимал значения «истина» или «ложь», по крайней мере, один раз.
    Нетрудно видеть, что критерий покрытия решений удовлетворяет критерию покрытия операторов, но является более «сильным».
    Программу, алгоритм которой представлен на рис. 9.2, а, можно протестировать по методу покрытия решений двумя тестами, покрывающими либо пути: 1-2-4-6, 1-2-3-4-5-6, либо пути: 1-2-3-4-6, 1-2-4-5-6, например: а = 3, b = 0, х = 3 — путь 1-2-3-4-5-6; а = 2, b = 1, х = 1 — путь 1-2-4-6.
    Однако путь, где х не меняется, будет проверен с вероятностью 50 %: если во втором условии вместо условия х > 1 записано х < 1, то этими двумя тестами ошибка обнаружена не будет.
    Покрытие условий. Критерий покрытия условий является еще более «сильным» по сравнению с предыдущими. В этом случае формируют некоторое количество тестов, достаточное для того, чтобы все возможные результаты каждого условия в решении были выполнены, по крайней мере, один раз.
    Однако, как и в случае покрытия решений, этот критерий не всегда приводит к выполнению каждого оператора, по крайней мере, один раз. К критерию требуется дополнение, заключающееся в том, что каждой точке входа управление должно быть передано, по крайней мере, один раз.
    Программа, алгоритм которой представлен на рис. 9.2, а, проверяет четыре условия:
    1) а>1; 2) b = 0; 3) а = 2; 4)х> 1.
    Необходимо реализовать все возможные ситуации: а>1,а≤1, b=0, b≠0, а = 2, а≠2, х>1, x ≤1.
    Тесты, удовлетворяющие этому условию:

    272
    а = 2, b = 0, х = 4 — путь 1-2-3-4-5-6, условия: 1 - да, 2 - да, 3 - да, 4 - да; а = 1, b= 1, х = 1 — путь 1-2-4-6, условия: 1 - нет, 2 - нет, 3 - нет, 4 - нет.
    Критерий покрытия условий часто удовлетворяет критерию покрытия решений, но не всегда. Тесты критерия покрытия условий для ранее рассмотренных примеров покрывают результаты всех решений, но это случайное совпадение. Например, тесты: а = 1, b = 0, х = 3 — путь 1-2-3-6, условия: 1 - нет, 2 - да, 3 - нет, 4 - да; а = 2, b = 1, х = 1 — путь 1-2-3-4-5-6, условия: 1 - да, 2 - нет, 3 - да, 4 – нет покрывают результаты всех условий, но только два из четырех результатов решений: не выполняется результат «истина» первого решения и результат «ложь» второго.
    Основной недостаток метода - недостаточная чувствительность к ошибкам в логических выражениях.
    Покрытие решений/условий. Согласно этому методу тесты должны составляться так, чтобы, по крайней мере, один раз выполнились все возможные результаты каждого условия и все результаты каждого решения, и каждому оператору управление передавалось, по крайней мере, один раз.
    Анализ, проведенный выше, показывает, что этому критерию удовлетворяют тесты: а = 2, b = 0, х = 4 — путь 1-2-3-4-5-6, условия: 1 - да, 2 - да, 3 - да, 4 - да; а = 1, b = 1, х = 1 — путь 1-2-4-6, условия; 1 - нет, 2 - нет, 3 - нет. 4 - нет.
    Комбинаторное покрытие условий. Этот критерий требует создания такого множества тестов, чтобы все возможные комбинации результатов условий в каждом решении и все операторы выполнялись, по крайней мере, один раз.
    Для программы, алгоритм которой представлен на рис. 9.1, необходимо покрыть тестами восемь комбинаций:
    1) a > 1, b =0;
    2) a > 1, b ≠ 0;
    3) a ≤ 1, b = 0;
    4) a ≤ 1; b ≠ 0;
    5) a = 2, x > 1;
    6) a = 2, x ≤ 1;
    7) a ≠ 2, x > 1 8) a ≠ 2, x ≤ 1
    Эти комбинации можно проверить четырьмя тестами: а = 2, b = 0, х = 4 — проверяет комбинации (1), (5); а = 2, b = 1, х = 1 — проверяет комбинации (2), (6); а = 1, b = 0, х = 2 — проверяет комбинации (3), (7); а = 1, b = 1, х = 1 — проверяет комбинации (4), (8).

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

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

    передавать управление каждому оператору, по крайней мере, один раз.
    Термин «возможных» употреблен здесь потому, что некоторые комбинации условий могут быть нереализуемы. Например, для комбинации к < 0 и к > 40 задать к невозможно.
    9.4. Функциональное тестирование
    Одним из способов проверки программ является тестирование с управлением по данным или по принципу «черного ящика». В этом случае программа рассматривается как
    «черный ящик», и целью тестирования является выяснение обстоятельств, в которых поведение программы не соответствует спецификации.
    Для обнаружения всех ошибок в программе, используя управление по данным, необходимо выполнить исчерпывающее тестирование, т. е. тестирование на всех возможных наборах данных. Для тех же программ, где исполнение команды зависит от предшествующих ей событий, необходимо проверить и все возможные последовательности. Очевидно, что проведение исчерпывающего тестирования для подавляющего большинства случаев невозможно. Поэтому обычно выполняют «разумное» или «приемлемое» тестирование, которое ограничивается прогонами программы на небольшом подмножестве всех возможных входных данных. Этот вариант не дает гарантии отсутствия отклонений от спецификаций.
    Правильно выбранный тест должен уменьшать, причем более чем на единицу, число других тестов, которые должны быть разработаны для обеспечения требуемого качества программного обеспечения.
    При функциональном тестировании различают следующие методы формирования тестовых наборов:

    эквивалентное разбиение;

    анализ граничных значений;

    анализ причинно-следственных связей;

    предположение об ошибке.

    274
    1   ...   19   20   21   22   23   24   25   26   27


    написать администратору сайта