Реферат: Программа сложной структуры с использованием меню

ВИДЫ КОНТРОЛЯ ПРОГРАММ

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

решения одной задачи исоставляющих одно целое.

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

статический и динамический.

Визуальный контроль — это проверка программ “ за столом “, без использования

компьютера. На первомэтапе визуального контроляосуществляется  чтение

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

комментариям и их соответствию тексту программы ;

условиям в операторах условного выбора ( IF, CASE ) ицикла;

сложным логическим выражениям; 

возможности незавершения итерационных циклов   ( WHILE,REPEAT, LOOP ).

Второй этап визуального контроля — сквозной контрольпрограммы

( ее ручная прокрутка на нескольких заранее подобранныхпростых тестах).

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

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

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

совершенствуются навыки в использовании клавиатуры, в товремя как

программистская квалификация преобретается прежде всегозастолом.

Статический контроль- это проверка программы по еетексту   (без

выполнения) спомощью инструментальных средств. Наиболееизвестной формой

статического контроля является синтаксический контрольпрограммы с помощью

компилятора, прикотором проверяется соответствие текстапрограммы

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

Сообщения компилятора обычно делятся на несколько групп взависимости от уровня

тяжести нарушения синтаксиса языкапрограммирования:

— информационные сообщения и предупреждения, приобнаружении

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

работа с программой (компоновка, выполнение) возможна(тем не менее сообщения

этойгруппы также должны тщательно анализироваться, таккак их появление также

может свидетельствовать об ошибке в программе — например,из-за неверного

пониманиясинтаксиса языка);

— сообщения об ошибках, при обнаружении которыхкомпилятор

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

дальнейшая работа с ним скорее всего не возможна;

     

    3

-  сообщения о серьезных ошибках, при наличии которых 

построенный компилятором объектный код заведомонекорректени его дальнейшее

использование невозможно;

— сообщения об ошибках, обнаружение которых привело к

прекращениюсинтаксического контроля и построенияобъектного кода .

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

ошибок. Место обнаружения ошибки может находитьсядалекопо тексту программы от

места истинной ошибки, а текст сообщения компилятораможет не указывать на

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

генерацию компилятором нескольких сообщений об ошибках(например, ошибка в

описании переменной приводит к появлению сообщенияобошибке в каждом операторе

программы, использующем эту переменную).

Второй формой синтаксического контроля может бытьконтроль структурированности

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

программирования. Примером подобной проверки может бытьвыявление в тексте

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

перехода (использования оператора GOTO для перехода вверхпо тексту программы ).

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

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

может совмещаться свизуальным контролем .

Третья форма статического контроля — контрольправдоподобия программы, то есть

выявление в ее тексте конструкций, которые хотяисинтаксически корректны, но

скорее всего содержат ошибку или свидетельствуют о ней.Основные

неправдоподобные ситуации:

— использование в программе неинициализированныхпеременных (то

естьпеременных, не получивших начального значения);

— наличие в программе описаний элементов, переменных,процедур,

меток, файлов,  в дальнейшем не используемых в ее тексте;

— наличие в тексте программы фрагментов, никогда не

выполняющихся;

— наличие в тексте программы переменных, ни разу неиспользуемых

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

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

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

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

эффективность программы, т. е. благотворно скажется наеекачестве.

Для возможности проведения контроля правдоподобия вполном объеме также должны

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

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

   4

Следует отметить, что создание инструментальных средствконтроля

структурированности и правдоподобия программ можетбытьсущественно

упрощено при применении следующих принципов:

  1) проведение этих дополнительных форм статическогоконтроля

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

 2) максимальное использование результатов компиляциипрограммы

и, вчастности, информации, включаемой в листингкомпилятора;

  

3) вместо полного синтаксического разбора текстапроверяемой

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

указанием всех их необходимых признаков.

При отсутствии инструментальных средств контроляправдоподобия эта фаза

статического контроля также может объединяться свизуальнымконтролем.

Четвертой формой статического контроля программ являетсяих верификация, то есть

аналитическое доказательство их корректности.

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

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

различных этапах проектирования ( спецификации,проектирование алгоритма и

структур данных, кодирование ). Корректность самойпрограммы поотношению к

целям, поставленным перед ее разработкой ( то есть этоотносительное свойство ).

Отличие понятия корректности и надежности программ вследующем  :

надежность характеризует как программу, так и ее“окружение” (

качествоаппаратуры, квалификацию пользователя и т.п. );

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

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

 Надежность можно представить совокупностью следующиххарактеристик :

1) целостность программного средства (способность его кзащите

ототказов);

2) живучесть (способность к входному контролю данных и их

проверки входе работы) ;

3) завершенность (бездеффектность готового программного

средства, характеристика качества его тестирования);

4) работоспособность (способность программного средства к

восстановлению своих возможностей полесбоев).

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

указанном выше смысле, т. е. корректностьхарактеризуетсемантические свойства

программ.

 5

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

понятиякорректности :

1) корректность как точное соответствие целям разработки

программы(которые отражены в спецификации) при условии еезавершения или

частичная корректность ;

2) завершение программы, то есть достижение программой в

процессе еевыполнения своей конечной точки.  

В зависимости от выполнения или невыполнения каждого издвух названных свойств

программы различают шесть задач анализакорректности :

1) доказательство частичной корректности ;

2) доказательство частичной некорректности ;

3) доказательство  завершения программы;

4) доказательство  незавершения программы;

     5) доказательство  тотальной (полной ) корректности(то есть

одновременное решение первой и третьей задач);

6) доказательство  некорректности (решение второй иличетвертой задачи).

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

нааксиоматический подход к формализации семантики языковпрограммирования. В

настоящее время известны аксиоматические семантикиПаскаля, подмножества ПЛ/1

инекоторых других языков.

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

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

языка (присваивания, ввода — вывода, вызовапроцедур). Спомощью правил вывода

описывается семантика составных операторов илиуправляющих структур

(последовательности, условного выбора, циклов). Средиэтихправил вывода  надо

отметить правило вывода для операторов цикла так как онотребует знания

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

цикла).

Построение инварианта для оператора цикла по его текстуявляется алгоритмически

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

”подсказка” от разработчика программы.

Наиболее известным из методов доказательства частичнойкорректности программ

является метод индуктивных утвержденийпредложенныйФлойдом и усовершенствованный

Хоаром. Метод состоит из трех этапов.

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

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

предикатов первого порядка :

 6

входной предикат ;

выходной предикат ;

по одному утверждению для каждого цикла (эти утверждения

задаются для входной точки цикла и должныхарактеризоватьсемантику вычислений в

цикле).

Доказательство неистинности условий корректностисвидетельствует о

неправильности программы, или ее спецификации, илипрограммыи спецификации.

Несмотря на достаточную сложность процесса верификациипрограммы и на то, что

даже успешно завершенная верификация не даетгарантийкачества программы ( т.к.

ошибка может содержаться и в верификации ), применениеметодов аналитического

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

программы, а знание этих методов благотворно сказываетсяна квалификации

программиста.

Наконец, динамический контроль программы — это проверкаправильности программы

при ее выполнении на компьютере, т.е.тестирование.

   ЦЕЛИ, ПРИНЦИПЫ  И  ЭТАПЫ  ТЕСТИРОВАНИЯ .

Каждому программисту известно, сколько времени и силуходит на отладку и

тестирование программ. Наэтот этап приходится около 50%общей стоимости

разработки программного обеспечения.

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

тестирования.Нередко можно услышать, что тестирование — это процесс выполнения

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

самоетщательное тестирование не дает гарантии, чтопрограмма не содержит ошибок.

Другое определение тестирования ( у Г. Майерса )  тестирование — это процесс

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

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

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

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

Определение  Г. Майерса указывает на объективнуютрудность тестирования: это

деструктивный ( т.е. обратный созидательному )процесс.Поскольку

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

программных средств сложно  “переключиться” притестировании созданной ими

продукции.

 

 7

У Майерса сформулированы также основные принципыорганизации тестирования :

    1) необходимой частью каждого теста должно являтьсяописание

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

или отсутствие ошибки в ней ;

    2) следует  по  возможности  избегать  тестированияпрограммы ее

автором, т.к.кроме уже указанной объективной сложноститестирования для

программистов здесь присутствует и тот фактор, чтообнаружение недостатков в

своей деятельностипротиворечит человеческой психологии (однако отладка

программы эффективнее всего выполняется именно авторомпрограммы ) ;

  3) по  тем  же  соображениям  организация — разработчик

программногообеспечения не должна “единолично ” еготестировать ( должны

существовать организации, специализирующиеся натестировании программных средств

) ;

  4) должны являться правилом доскональное изучениерезультатов

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

программе;

   5)  необходимо тщательно подбирать тест не только для

правильных ( предусмотренных ) входных данных, но и для

неправильных(непредусмотренных) ;

   6) при анализе результатов кождого теста необходимо

проверять, не делает ли программа того, что она недолжнаделать ; 

      7) следует сохранять использованные тесты (для повышения

эффективности повторного тестированияпрограммы после еемодификации или

установки у заказчика) ;

    8) тестирования не должно планироваться исходя из

предположения, что в программе не будутобнаружены ошибки(в частности, следует

выделять для тестирования достаточные временные иматериальные ресурсы) ;

9) следует учитывать так называемый “принцип скопления

ошибок”: вероятность наличия не обнаруженныхошибок внекоторой части программы

прямо пропорциональна  числу ошибок, уже обнаруженных вэтой части;

     10) следует всегда помнить, что тестирование —

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

Существует два основных вида тестирования:функциональное и структурное. При

функциональномтестировании программа рассматривается как“черный ящик” (то есть

ее текст не используется). Происходит проверкасоответствия поведения программы

ее внешнейспецификации. Возможно ли при этом полноетестирование программы?

Очевидно, что критерием полнотытестирования в этомслучае являлся бы перебор

всех возможных значений входных данных, что невыполнимо .

8

Поскольку исчерпывающее функциональное тестированиеневозможно, речь может идти

о разработки методов, позволяющих подбирать тесты не“вслепую”, а с большой

вероятностью обнаружения ошибок в программе.

При структурном тестировании программа рассматривается как “белый ящик” (т.е.

ее текст открыт для пользования ).Происходит проверкалогики программы. Полным

тестированием в этом случае будет такое, которое приведетк перебору всех

возможных путей на графе передачуправления программы (ееуправляющем графе).

Даже для средних по сложности программ числом таких путейможет достигать

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

то и в этом случае исчерпывающее структурное тестированиепрактически

невозможно, т. к. неясно, как подбиратьтесты, чтобыобеспечить “покрытие” всех

таких путей. Поэтому при структурном тестированиинеобходимо использовать другие

критерии его полноты, позволяющиедостаточно простоконтролировать их выполнение,

но не дающие гарантии полной проверки логики программы.

Но даже если предположить, что удалось достичь полногоструктурного

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

т.к.

   1) программа может не соответствовать своей внешней

спецификации, что в частности, может привести к тому, чтов ее управляющем графе

окажутся пропущенными некоторые необходимые пути ;

2) не будут обнаружены ошибки, появление которых зависитот

обрабатываемых данных (т.е. на одних исходныхданныхпрограмма работает

правильно, а на других — с ошибкой).

Таким образом, ни структурное, ни функциональноетестирование не может быть

исчерпывающим. Рассмотрим подробнее основные этапытестирования

программныхкомплексов.

В тестирование многомодульных программных комплексовможно выделить четыре

этапа:

1) тестирование отдельных модулей ;

2) совместное тестирование модулей ; 

3) тестирование функций программного комплекса (т.е.поиск

различий между разработанной программой и ее внешнейспецификацией ) ;

4) тестирование всего  комплекса  в целом (т.е. поискнесоответствия

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

отраженным обычно в техническом задании).

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

тестирования, т.к.

на  последующих  этапах  тестирования   эти   методы

использоватьсложнее из-за больших размеров проверяемогопрограммного обеспечения

;

    последующие этапы тестирования ориентированы наобнаружение

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

При тестировании как отдельных модулей, так и ихкомплексов должны быть решены

двезадачи :

     1) построение эффективного множества тестов ;

     2) выбор способа комбинирования (сборки) модулей при

создании трестируемого варианта программы .

  СТРУКТУРНОЕ  ТЕСТИРОВАНИЕ .

Поскольку исчерпывающее структурное тестированиеневозможно, необходимо выбрать

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

бы целенаправленный подбор тестов.

Наиболее слабым из критериев полноты структурноготестирования является

требование хотябы однократного выполнения (покрытия)каждого оператора

программы.

Более сильным критерием является так называемый критерий С1: каждая ветвь

алгоритма(каждый переход) должна быть пройдена(выполнена) хотя бы один раз. Для

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

покрытиеоператоров, но, например, для программ на языкеПЛ/1 дополнительно к

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

(задаваемыхоператорами ENTRY) и всех ON — единиц.

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

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

критерия С1 (например, в программе на языке Паскаль,использующей конструкцию

цикла WHILE  х AND  y  DO…, применение критерияпокрытия условий требует

проверки обоих вариантов выхода из цикла: NOT x  и NOT y ).

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

переходов. Например, конструкция IF A AND BTHEN... требует по критерию покрытия

условий двух тестов (например, A=true, B=false и A=false,B=true ), при

которыхможет не выполняться оператор, расположенный в then- ветви оператора 

if.

Практически единственным средством, предоставляемымсовременными системами

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

различныхоператоров программы (ее профилизации). Но спомощью этого инструмента

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

критериевполноты — покрытие всех операторов.

Правда, с помощью этого же инструмента можно проверить ивыполнение критерия С1.

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

образом, чтобы все конструкции условного выбора (IF иCASE

10

или SWITCH ) содержали ветви ELSE или DEFAULT, хотя бы ипустые. В этом случае

всеветви алгоритма, не выполнявшиеся на данном тестебудут “видимы” из таблицы

частоты выполнения операторов преобразованной программы. 

Актуальной остается задача создания инструментальныхсредств, позволяющих:

  1) накапливать информации о покрытых и непокрытыхветвях для

всех использованных тестов ;

 2) выделять разработчику еще не покрытые притестировании

участки программы, облегчая выбор следующих тестов;

      3) поддерживать более мощные критерии полнотыструктурного

тестирования.

 

 

 

 

 

 

 

      Совместное тестирование модулей.

  

Известны два подхода к совместному тестированию модулей:пошаговое и монолитное

тестирование.

При монолитном тестировании сначала по отдельноститестируются все модули

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

комплексного тестирования.

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

набору ужепроверенных модулей.

В первом случае для автономного тестирования каждогомодуля требуется модуль —

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

и один или несколько модулей — заглушек ( то естьвспомогательных модулей,

имитирующихработу модулей, вызываемых из тестируемого).При пошаговом

тестировании модули проверяются не изолированно друг отдруга, поэтому требуются

либо толькодрайверы, либо только заглушки.

А  

     BC  D

     E    F

   рис. 1

12

При сравнении пошагового и монолитного тестирования можноотметить следующие

преимущества первогоподхода : 

    1) меньшая трудоемкость (для примера на рис.1 примонолитном

тестировании требуются 5 драйверов и 5 заглушек; припошаговом тестировании

требуются или только 5 драйверов — если модулиподключаются “снизу вверх ”, —

или только 5 заглушек — если модули подключаются“сверхувниз”) ; 

    2) более раннее обнаружение ошибок в интерфейсахмежду

модулями (их сборка начинается раньше, чем при монолитномтестировании ) ;

    3) легче отладка, то есть локализация ошибок (они восновном

связаны с последним из подключенных модулей) ;

    4) более совершенны результаты тестирования (более

тщательная проверка совместного использованиямодулей).

Есть приемущества и у монолитного тестирования :

   1) меньше расход машинного времени (хотя из-за большей

сложности отладки может потребоватьсядополнительнаяпроверка программы и это

приемущество будет сведено на нет) ; 

     2) предоставляется больше возможностей дляорганизации

параллельной работы на начальном этапетестирования.

В целом более целесообразным является выбор пошаговоготестирования. При его

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

восходящая.

Нисходящее тестирование начинается с главного (иливерхнего) модуля программы, а

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

уже протестированных. Одна из основных проблем, возникающихпри

нисходящемтестировании, — создание заглушек. Этотривиальная задача, т. к. как

правило недостаточно, чтобы в заглушке выполнялся вывод

соответствующегоинформационного сообщенияи и возвратвсегда одних и тех же

значений выходных данных.

Другая прблема, которую необходимо решать при нисходящемтестировании, — форма

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

входные данные не непосредственно, а через специальныемодули ввода, которые при

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

тестов нужно или иметь несколько разных заглушек, илизаписать эти тесты в файл

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

Поскольку после тестирования главного модуля процесс проверкиможет продолжаться

по-разному, следует придерживаться следующих правил :  

      а) модули, содержащие операции ввода-вывода, должныподключаться к

тестированию как можно раньше ;

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

целом модули также должны тестироваться впервую очередь.

12

  Основные достоинства нисходящего тестирования : 

     уже на ранней стадии тестирования есть возможностьполучить

работающий вариант разрабатываемойпрограммы ;

     быстро могут быть выявлены ошибки, связанные сорганизацией

взаимодействие с пользователем.

Недостатки нисходящей стратегии продемонстрируются спомощью рис.2.

Допустим, что на следующем шаге тестирования заглушкамодуля H заменяется его

реальным текстом.Тогда

1) может оказаться трудным или даже невозможным

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

наперед последовательности значений данных на входемодуля Н ;

2) не всегда окажется возможным легко оценить

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

модуля Н;

3) т. к. результаты выполнения прграммы на построенном

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

трудным  восстановлении дейсвительных результатов работымодуля Н.

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

  появляется соблазн совмещения нисходящего

проектирования с тестированием, что, какправило, неразумно, т.к. проектирование

— процесс итеративный и в нем неизбежен возврат наверхние уровни и исправление

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

;

  может возникнуть желание перейти к тестированию модуля

следующего уровня до завершениятестирования предыдущегопо объективным причинам

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

верхнего уровня ресурсовмодулей нижних уровней). 

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

(т.е. тех, которые не вызывают не каких других модулейпрограммы). Эта стратегия

во многом противоположна нисходящему тестированию (вчастности, преимущества

становятсянедостатками и наоборот).

Нет проблемы выбора следующего подключаемого модуля — учитывается лишь то,

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

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

случаев проще (крометого, использование средствавтоматизации и отладки

облегчает создание как раз драйверов, а не заглушек).

Другие достоинства восходящего тестирования :

поскольку нет промежуточных модулей (тестируемый модуль

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

проблем, связанных с возможностью или тружностью заданиятестов;

нет возможности совмещения проектирования с

тестированием ;

нет трудностей, вызывающих желание перейти к

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

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

структурыразрабатываемого программного комплекса возможнатолько на завершающей

стадии тестирования.

Хотя однозначного вывода о преимущества той или инойстратегии пошаговаого

тестирования сделать нельзя(нужно учитывать конкретныехарактеристики

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

восходящеетестирование.    

На третьем этапе тестирования программных комплексов(тестировании функций)

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

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

Обзор методов проектирования тестов при функциональеомтестировании начнем с

методазквивалентного разбиения.

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

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

то тест из этого множества должен :

1) уменьшать (более чем на единицу) число других тестов,которые должны быть

разработанны для достижения заранее поставленной цели

“удовлетворительного”тестирования ;

     2) покрывать собой значительную часть другихвозможных

тестов .

Другими словами :

      1) каждый тест должен заключать в себе проверку

наибольшего числа задаваемых внешней спецификациейвходныхусловии (ограничений

на входные данные) для того, чтобы минимизировать общеечисло необходимых тестов

;

   2) необходимо разбить область значений входных данных

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

эквивалентности), чтобы можно было полагать каждый тест,являющийся

представителем некоторого класса, эквивалентнымлюбомудругрому тесту этого

класса (т.е. обнаруживающим одни и те же ошибки).

В общем случае использование термина “классэквивалентности” является здесь

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

Проектирование тестов по методу эквивалентного разбиенияпроводится в два этапа

:

      выделение по внещней спецификации классовэквивалентности;

построение множества тестов.

Напервом этапе происходит выбор из спецификации каждоговходного условия и

разбиение его на две или более группы, соответствующиетак называемым

“правильным”(ПКЭ) и “неправильным” классомэквивалентности (НКЭ), т.е. облатям

допустых для программы и недопустимых значений входныхданных. Этот процесс

зависит от видавходного условия. Если входное условиеописывает область

(например, х <=0.5) или количеством (например, размермассива А равен 50)

допустимых значенийвходных данных, то определяются одинПКЭ (х <=0.5 или размер

А равен 50) и два НКЭ (х< -0.5; х>0.5 или размер Аменьше 50; размер А больше

50).

Если входное условие описывает дискретное множестводопустимых значений

входныхданных (например, В может равно -1, 0 или 1), тоопределяются ПКЭ для

каждого значения из множества (в данном примере 3) и одинНКЭ (В<>-1 &В<>0 &

В<>1). 

Если входное условие описывает ситуацию “ложно быть ”(например, N>0), то

определяются один ПКЭ (N>0) и один НКЭ (N<=0).

На втором этапе метода эквивалентного разбиениявыделенные классы

эквивалентностииспользуются для построения тестов:

   каждому классу присваивается свой номер ;

   проектируются тесты для ПКЭ таким образом, что кажлыйтест покрывает

как можно больше еще не покрытых ПКЭ, до техпор, пока всеПКЭ не будут покрыты ;

  проектируются тесты для НКЭ таким образом, что каждыйтест

покрывает один и только один НКЭ, до тех пор, пока все НКЭне будут покрыты.

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

недопустимымизначениями входных данных проверяют толькоодну ошибку и скрывают

реакцию программы на другие ошибки.

Метод эквивалентного разбиения значительно лучше случайногоподбора тестов, но

имеетсвои недостатки. Основной из них — пропускопределенных типов

высокоэффективных тестов (т.е. тестов, характеризующихсябольшой вероятностью

обнаруженияошибок). От этого недостатка во многомсвободен метод анализа

граничных условий.

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

границеопределенного в спецификации входного иливыходного условия, выше или

ниже ее. Метод анализа граничных условий отличается отметода эквивалентного

разбиенияследующим :

 выбор любого представителя класса эквивалентности

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

;

  при построении тестов рассматриваются не только

входные условия, но и выходные (т.е.определенные вовнешней спецификации

ограничения на значения входных данных).

Общие правила метода анализа граничных условий :

    1) построить тесты для границ области допустимыхзначений

входных данных и тесты с недопустимымизначениями,соответствующими

незначительному выходу за границы этой области (например,для области [-1.0;

1.0] строим тесты -1.0; 1.0; -1.001; 1.001) ;

  2) построить тесты для минимального и максимильного

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

входных данных, и тесты для значений, больших или меньшихэтих величин

(например, если входной файл может содержатьот 1 до 225записей, то выбираются

тесты для пустого файла, содержащего 1, 255 и 256записей)  ;

   3) использовать правило 1 для каждого выходного

условия (например, программа вычисляетежемесячный расходчастного лица или

небольшого предприятия, минимум которого 0.00 $, амаксимум 1165.50 $; тогда

необходимо постоить тесты, вызывающиеотрицательныйрасход, расходы, равные 0.00

$ и 1165.50 $, и расход, больший 1165.50 $) ;

   4) использовать правило 2 для каждого выходного

условия (например, программа ищет и отображаетна экранедисплея наиболее

подходящие, в зависимости от входного условия, рефератыстатей, но не более

четырех; тогда необходимо построить тесты, приводящие котображению 0, 1, 4

рефератов и попытки ошибочного отображения 5 рефератов) ;

      5) если входные и выходные данные програмыпредставляют

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

то пре тестировании сосредоточить внимание на первом ипоследнем элементе

множества;

  6) попытаться найти и проверить тестами другие

граничные условия.

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

граничнымзначениям входных данных соответствуют граничныезначения результатов

работы программ.

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

пример. Пусть имеется программа, осуществляющая ввод трехчиселинтерпретирующая

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

(“разносторонний”, “равнобедренный” или “равносторонний”).Допустим также, что в

программе содержится ошибка: при проверке условияпостроения треугольника

(сумма длин любых двух сторон должна быть большетретьей)используется операция

отношения >= вместо >. При проектировании тестов пометоду 

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

треугольника (например, 3, 4, 5) и невозможности егопостроения (например, 1, 2,

4), т.е.ошибка в программе не будет обнаружена (навходные данные 1, 2, 3 будет

выведено сообщение “разносторонний треугольник”). Ноподобный тест будетполучен

при  использовании метода анализа граничных условий.

Анализ граничных уловий — один из наиболее полезных методовпроектирования

тестов. Ноон часто оказывается неэффективным из-за того,что граничные условия

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

Общим  недостатком двух рассмотренных выше методовфункционального тестирования

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

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

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

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

образом выбрать высоко эффективныетесты. Полезнымпобочным эффектом этого метода

является обнаружение неполноты и противоречивости вовнешних спецификациях.

Функциональная диаграмма — это текст на некотором формальномязыке, на который

транслируется спецификация, составленная на естественномили

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

и следствием — выходное условие или преобразованиесистемы (т.е. остаточное

действиепрограммы, вызванное определенным входнымусловием или их комбинацией).

Например, для программы обновления файла изменение в немявляетсяпреобразованием

системы, а подтверждающее это изменение сообщение — выходным условием.

Метод функциональных диаграмм состоит из шести основныхэтапов. На первом из них

(необязательном) внешняя спецификация большогоразмераразбивается на отдельные

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

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

На втором этапе в спецификации выделяются причины иследствия, а на третьем —

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

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

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

(каждый узел функциональной диаграммы может находиться всостоянии 1 —

“существует” — или 0 — “не существует”).

а) Тождество: (а=1=>b=1) & (а=0=>b=0)

  а      b    

б) Отрицание: (а=1=>b=0) & (a=0=>b=1)

      ~

  ab

в) Дизъюнкция: (a=1ïb=1=>c=1) &(a=0&b=>0>c=0)

  a

ï     c

  b

г) Конъюнкция: (a=1&b=1=>c=1) &(a=0ïb=0=>c=0)

  a    

&     c

  b   

рис.3

На четвертом этапе функциональная диаграмма снабжаетсякомментариями, которые

задают ограничения на комбинации причин и следствий.Нарис.4 приведены знаки

комментариев, задающих эти ограничения.

   а) Исключение одной из причин :

 

   a 

E((a=1ïb=1)^~(a=1&b=1)) ï(a=0&b=0)

   b

  

   б) Включение хотя бы одной причины :

    a

I(a=1ïb=1)&~(a=0&b=0)   

  

    b

    в) Существуетодна и только одна причина :

     a

O(a=1ïb=1)&~(a=1&b=1)&~(a=0&b=0) 

     b

     г) Одна причина влечет за собой лругую :

     a

  R     ~(a=1&b=0)   

 

     b 

      д) Одно следствие скрывает в себе другое :

      a

 M(a=1&b=0)&(a=1&b=1)

 

      b

 рис.4     

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

    выбирается следствие, которое устанавливается в 1 ;

    находятся все комбинации причин (с учетомограничений),

которые устанавливают выбранное следствие в 1

еще рефераты
Еще работы по информатике, программированию