Тестирование программного обеспечения
Рефераты >> Программирование и компьютеры >> Тестирование программного обеспечения

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

3. ВОСХОДЯЩЕЕ ТЕСТИРОВАНИЕ.

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

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

4. НИСХОДЯЩЕЕ ТЕСТИРОВАНИЕ.

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

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

Интересен и второй вопрос: в какой форме готовятся тестовые данные и как они передаются программе? Если бы головной модуль содержал все нужные операции ввода и вывода, ответ был бы прост:

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

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

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

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

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

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


Страница: