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

  • Применения и ограничения

  • Резюме ● Тестирование потока управления

  • Литература Beizer, Boris ​(1990). ​ Software Testing Techniques ​(Second Edition). Van Nostrand Reinhold. Myers, Glenford

  • Определена и повторно определена

  • Определена и затем уничтожена

  • Использована и повторно использована

  • Уничтожена и использована

  • Статическое тестирование потока данных

  • Динамическое тестирование потока данных

  • Литература Beizer, Boris ​(1990). ​ Software Testing Techniques ​. Van Nostrand Reinhold. Binder, Robert V.

  • Rapps, Sandra and Elaine J. Weyuker.

  • Учебник по тестированию. Guide to Software Test Design


    Скачать 2.51 Mb.
    НазваниеGuide to Software Test Design
    АнкорУчебник по тестированию
    Дата24.02.2022
    Размер2.51 Mb.
    Формат файлаpdf
    Имя файлаKopland_A-Practitioner-s-Guide-to-Software-Test-Design_RuLit_Me_.pdf
    ТипGuide
    #372562
    страница11 из 11
    1   2   3   4   5   6   7   8   9   10   11

    Тест-кейс
    C1
    C2
    C3
    C4
    C5
    1
    Fals e
    Fals e
    Не определено
    Не определено
    Не определено
    2
    True Fals e
    Не определено
    Не определено
    Не определено
    3
    Fals e
    True A
    Не определено
    False
    4
    Fals e
    True B
    False
    False
    5
    Fals e
    True C
    Не определено
    False
    6
    Fals e
    True D
    Не определено
    False
    7
    Fals e
    True B
    True
    False
    8
    Fals e
    True C
    Не определено
    True
    Таблица 10-1: Значения данных для различных маршрутов потока управления.
    Применения и ограничения
    Тестирование потока управления является краеугольным камнем модульного тестирования. Оно должно использоваться для всех модулей кода, которые нельзя протестировать в достаточной степени с помощью просмотров и инспекций кода. Его ограничения состоят в том, что тестировщик должен обладать достаточными навыками программирования для того, чтобы понимать код и его поток управления. Кроме того, из-за всех модулей и основных маршрутов, которые составляют систему, на тестирование потока управления может потребоваться очень много времени.
    Резюме
    Тестирование потока управления
    ​ определяет пути выполнения кода программного модуля, после чего создаются и исполняются тест-кейсы для покрытия этих путей.
    126


    ● Основой тестирования потока управления являются
    графы потока управления​. Модули кода преобразуются в графы, пути через эти графы анализируются, после чего на основе этого анализа создаются тест-кейсы.
    Цикломатическая сложность
    ​ - это конечное минимальное количество независимых, нецикличных маршрутов (называемых основными маршрутами), которые могут образовывать все возможные линейные пути в программном модуле.
    ● Поскольку набор основных маршрутов покрывает все ребра и узлы графа потока управления, то
    структурное тестирование
    ​, удовлетворяющее этому критерию, автоматически гарантирует покрытие как всех ветвей, так и всех операторов.
    Практика
    1. Ниже представлен небольшой листинг программы. Создайте диаграмму потока управления, определите ее цикломатическую сложность, выберите набор основных маршрутов, и определите значения для состояний, которые помогут пройти через каждый путь. if (c1) { while (c2) { if (c3) { s1; s2; if (c5) s5; else s6; break; // Переход в конец оператора while else if (c4) {} else { s3; s4; break;}
    } // Конец оператора while
    } // Конец оператора if s7; if (c6) s8; s9; s10;
    Литература
    Beizer, Boris
    ​(1990). ​Software Testing Techniques

    (Second Edition). Van Nostrand Reinhold.
    Myers, Glenford
    ​(1979). ​The Art of Software Testing

    . John Wiley & Sons.
    Pressman, Roger S.
    ​(1982). ​Software Engineering: A Practitioner's Approach

    (Fourth Edition). McGraw-Hill.
    Watson, Arthur H. and Thomas J. McCabe.
    Structured Testing: A Testing Methodology Using the Cyclomatic
    Complexity Metric

    . NIST Special Publication 500-235, доступно по ссылке http://www.mccabe.com/nist/nist_pub.php
    127

    Глава 11. Тестирование потока данных
    "Холли стала достаточно взрослой и зрелой, чтобы понять
    эмоциональный окрас утверждения Томаса Вульфа "невозможно
    снова вернуться домой", но для неё это оказалось даже ещё более
    острым, ведь не было дома, в который она могла бы вернуться: её
    родители развелись, продали дом, усыпили Боузера и отреклись от
    Холли за то, что она бросила старшую школу, чтобы выйти замуж
    за 43-х летнего управляющего Трейлер Таун в Айдахо - и даже их
    трейлер не был местом, которое она могла бы назвать домом,
    потому что его только арендовали на лето."
    Эйлин Остроу Фельдман
    Введение
    Почти каждый программист делал такую ошибку: main() { int x; if (x==42){...}
    }
    Ошибка состоит в том, что мы ссылаемся на значение переменной прежде, чем присвоили ей значение.
    Наивные разработчики бессознательно полагают, что компилятор языка или среда выполнения инициализирует все переменные нулями, пробелами, TRUE, 42-мя, или чем-угодно, что понадобится далее в программе. Простая программа на языке Си иллюстрирует это заблуждение:
    #include main() { int x; printf ("%d",x);
    }
    Выведенное значение переменной будет равно любому значению, "оставленному" в том месте памяти, где теперь располагается x, но не обязательно тому, что программист хотел или ожидал.
    Тестирование потока данных - это мощный инструмент для обнаружения такого рода ошибок. Рапс и
    Вьюкер, популяризаторы данного метода, писали: "Мы уверены, что, как нельзя чувствовать себя уверенным в программе без выполнения каждого ее оператора в рамках какого-то тестирования, так же не следует быть уверенным в программе без видения результатов использования значений, полученных от любого и каждого из вычислений".
    Ключевой момент
    Тестирование потока данных - это мощный инструмент для обнаружения неправильного использования значений данных, возникшего из-за ошибок в коде.
    128

    Методика
    Переменные, которые содержат значения, имеют определённый жизненный цикл. Они создаются, они используются и они удаляются (уничтожаются). В некоторых языках программирования (например,
    FORTRAN и BASIC) создание и уничтожение происходит автоматически. Переменная создается при первом присвоении ей значения и уничтожается при завершении программы.
    В других языках (таких как C, C++, и Java) создание переменных носит формальный характер. Переменные объявляются выражениями, такими как: int x; // x - создана как целочисленная переменная string y; // y создана как строковая переменная
    Объявления переменных как правило происходят в блоках кода, начинающихся с открытой фигурной скобки { и заканчивающихся закрытой }. Переменные, объявленные внутри блока, создаются в момент их объявления и автоматически уничтожаются в конце блока. Это называется "область видимости" переменной. Например:
    {
    // начало внешнего блока int x; // x определена как целочисленная внутри этого внешнего блока
    ...;
    // x здесь доступен
    {
    // начало внутреннего блока int y; // y определена внутри этого внутреннего блока
    ...; // здесь доступны обе переменные x и y
    }
    // y автоматически уничтожается в конце этого блока
    ...; // x до сих пор доступна, а y - уже нет
    }
    // x автоматически уничтожается
    Переменные могут быть использованы в вычислении (a=b+1). Они также могут быть использованы в условиях (if (a>42)). В обоих случаях одинаково важно, чтобы значение было присвоено переменной до её использования.
    Существует три случая первого появления переменной в ходе выполнения программы:
    1. d переменная не существует (указывается с помощью ), затем её определили ("d" - defined)
    2. u переменная не существует, затем её использовали ("u" - used)
    3. k переменная не существует, затем её удалили или уничтожили ("k" - killed)
    Первый случай - верный. Переменная не существует, и потом её определили. Второй - не верный.
    Переменная не может быть использована прежде, чем её объявили. Третий случай возможно не корректен.
    Уничтожение переменной до её создания указывает на программную ошибку.
    Теперь рассмотрим следующие последовательные пары, состоящие из определения (d), использования
    (u), и удаления (k):
    ● dd
    Определена и повторно определена​ - не является неправильным, но подозрительно.
    Возможна программная ошибка.
    ● du
    Определена и использована​ - совершенно правильно. Обычный случай.
    ● dk
    Определена и затем уничтожена​ - не является неправильным, но возможна программная ошибка.
    ● ud
    Использована и определена​ - приемлемо.
    129

    ● uu
    Использована и повторно использована​ - приемлемо.
    ● uk
    Использована и уничтожена​ - приемлемо.
    ● kd
    Уничтожена и определена​ - приемлемо. Переменная удаляется и затем переопределяется.
    ● ku
    Уничтожена и использована​ - серьёзный дефект. Использование переменной, которая не существует или не определена - это всегда ошибка.
    ● kk
    Уничтожена и уничтожена​ - возможна программная ошибка.
    Ключевой момент
    Исследуйте последовательные пары объявленных, используемых и уничтоженных ссылок на переменные.
    Граф потока данных похож на граф потока управления тем, что показывает поток обработки через модуль.
    Дополнительно к этому, он детализирует определение, использование и уничтожение каждой из переменных модуля. Мы построим эти диаграммы и убедимся, что шаблоны определение-использование-уничтожение являются подходящими. Сначала мы проведем статический тест этой диаграммы. Под "статическим" мы имеем ввиду, что мы исследуем диаграмму (формально через проверки или неформально беглыми просмотрами). Потом мы проведем динамические тесты модуля. Под "динамическими" мы понимаем, что мы создаем и исполняем тестовые сценарии. Начнем со статического тестирования.
    Статическое тестирование потока данных
    Следующая диаграмма потока управления отображает информацию об определении-использовании-удалении для каждой из переменных, использованных в модуле.
    Рис. 11-1: Диаграмма потока управления, отображающая информацию об определении-использовании-удалении для каждой из переменных модуля.
    130

    Рассмотрим для каждой переменной модуля паттерн "определение-использование-удаление" по маршрутам потока управления. Рассмотрим переменную x сначала по левому маршруту, а затем по правому.
    Рис. 11-2: Диаграмма потока управления, отображающая информацию об определении-использовании-удалении для переменной x.
    Паттерны "определение-использование-удаление" для x (образуют пары, если мы следуем по маршруту):
    ● определение - правильно, обычный случай
    ● определение-определение - подозрительно, возможно ошибка программирования
    ● определение-использование - правильно, обычный случай
    Теперь переменная y. Заметим, что первое разветвление в модуле не оказывает никакого влияния на переменную y.
    131

    Рис. 11-3: Диаграмма потока управления, отображающая информацию об определении-использовании-удалении для переменной y.
    Паттерны "определение-использование-удаление" для y (образуют пары, если мы следуем по маршруту):
    ● использование - критическая ошибка
    ● использование-определение - приемлемо
    ● определение-использование - верно, нормальный случай
    ● использование-удаление - приемлемо
    ● определение-удаление - возможно ошибка программирования
    Теперь переменная z.
    132

    Рис. 11-4: Диаграмма потока управления, отображающая информацию об определении-использовании-удалении для переменной z.
    Паттерны "определение-использование-удаление" (образуют пары, если мы следуем по маршруту) следующие:
    ● удаление - ошибка программирования
    ● удаление-использование - критическая ошибка
    ● использование-использование - правильно, обычный случай
    ● использование-определение - приемлемо
    ● удаление-удаление - возможно ошибка программирования
    ● удаление-определение - приемлемо
    ● определение-использование - правильно, обычный случай
    При статистическом анализе в этой модели потока данных возникают известные проблемы:
    ● х: определение - определение
    ● y: использование
    ● y: определение - уничтожение
    ● z: уничтожение
    ● z: уничтожение - использование
    ● z: уничтожение - уничтожение
    При статическом тестировании можно найти много дефектов в потоке данных, но, к сожалению, не возможно найти все проблемы. Рассмотрим следующие ситуации:
    133

    1. Массивы - это коллекции элементов данных, у которых одинаковое имя и тип. Например int stuff[100]; обозначает массив с именем stuff, состоящий из 100 элементов типа "integer" (целое число). В С,
    С++ и Java отдельные элементы именуются как stuff[0], stuff[1], stuff[2] и т.д. Массивы объявляются и уничтожаются целиком, но при этом отдельные элементы массива используются индивидуально.
    Часто программисты ссылаются на stuff[j], где j динамически изменяется во время выполнения программы. В общем случае статический анализ не может определить, были ли правильно соблюдены правила "определение-использование-удаление", если каждый элемент не рассматривается в индивидуальном порядке.
    2. В сложных потоках вполне возможно, что определенная ветвь никогда не будет выполнена. В таком случае неправильная комбинация "определение-использование-удаление" может существовать, но она никогда не выполнится и по сути не будет действительно неподходящей.
    3. В системах, использующих прерывания, некоторые из процедур определение-использование-уничтожение могут выполняться на уровне прерываний, в то время как другие процедуры выполняются на уровне основного процесса. Кроме того, если в системе применяется несколько уровней приоритетов выполнения, то статический анализ такого множества возможных взаимодействий становится слишком трудоемким для выполнения вручную.
    По этой причине, мы рассмотрим динамическое тестирование потока данных.
    Динамическое тестирование потока данных
    Так как тестирование потока данных основано на потоке управления модуля, то, предположительно, поток управления в основном верный. Процесс тестирования потока данных сводится к выбору достаточного количества тестов, таких как:
    ● каждое "определение" прослеживается для каждого его "использования"
    ● каждое "использование" прослеживается из соответствующего ему "определения"
    Чтобы сделать это, перечислим маршруты в модуле. Порядок выполнения такой же, как и в случае с тестированием потока управления: начинаем с точки входа в модуль, строим самый левый маршрут через весь модуль и заканчиваем на выходе из него. Возвращаемся в начало и идём по другому направлению в первом разветвлении. Прокладываем этот путь до конца. Возвращаемся в начало и идём по другому направлению во втором разветвлении, потом в третьем и т.д., пока не пройдём все возможные пути. Затем создадим хотя бы один тест для каждой переменной, чтобы покрыть каждую пару определение-использование.
    Применения и ограничения
    Тестирование потока данных построено на технике тестирования потока управления и расширяет её. Как и при тестировании потока управления, тестирование потока данных должно использоваться для всех модулей кода, которые нельзя проверить в достаточной степени только поверхностными осмотрами
    (ревью) и инспекциями. Недостатком является то, что тестировщик должен владеть достаточными навыками в программировании для правильного понимания кода, потока управления и переменных.
    Подобно тестированию потока управления, тестирование потока данных может быть весьма времязатратным из-за большого количества модулей, путей и переменных, которые входят в состав системы.
    134

    Резюме
    ● Распространенная ошибка программирования - ссылаться на значение переменной без предварительного присвоения этого значения.
    ● Граф потока данных подобен графу потока управления в том, что он отображает обработку проходящего через модуль потока. В дополнение, он детализирует объявление, использование и уничтожение каждой из переменных модуля. Мы будем использовать эти диаграммы для проверки того, что схемы "определение-использование-удаление" являются подходящими.
    ● Подсчитайте пути через модуль. Затем для каждой переменной создайте хотя бы один тест-кейс для того, чтобы покрыть каждую пару "определение-использование".
    Практика
    1. Следующий фрагмент кода вычисляет факториал числа n! для заданного числа n. Создайте тест-кейсы для потока данных, покрывающие все переменные в этом участке кода. Помните, что единичный тест может включать в себя только часть переменных. int factorial (int n) { int answer, counter; answer = 1; counter = 1; loop: if (counter > n) return answer; answer = answer * counter; counter = counter + 1; goto loop;
    }
    2. Составьте диаграмму контроля потока путей и получите тест-кейсы потока данных для следующего фрагмента кода: int module( int selector) { int foo, bar; switch selector { case SELECT-1: foo = calc_foo_method_1(); break; case SELECT-2: foo = calc_foo_method_2(); break; case SELECT-3: foo = calc_foo_method_3(); break;
    }
    135
    switch foo { case FOO-1: bar = calc_bar_method_1(); break; case FOO-2: bar = calc_bar_method_2(); break;
    } return foo/bar;
    }
    У вас есть затруднения в понимании этого кода? Как бы вы справились с ними?
    Литература
    Beizer, Boris
    ​(1990). ​Software Testing Techniques

    . Van Nostrand Reinhold.
    Binder, Robert V.
    ​(2000). ​Testing Object-Oriented Systems: Models, Patterns, and Tools

    . Addison-Wesley.
    Marick, Brian
    ​(1995). ​The Craft of Software Testing: Subsystem Testing Including Object-Based and
    Object-Oriented Testing

    . Prentice-Hall.
    Rapps, Sandra and Elaine J. Weyuker.
    ​"Data Flow Analysis Techniques for Test Data Selection." Sixth
    International Conference on Software Engineering, Tokyo, Japan, September 13–16, 1982.
    136
    1   2   3   4   5   6   7   8   9   10   11


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