Тестирование - Модульное программирование

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

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

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

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

 

Рис. 12.6. Блок-схема программы учета запасов.

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

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

Подпрограмма

Модули

Ввод с карт

1. Ввод с карт

2. Преобразование данных

 

Печать

1. Преобразование данных

2. Вывод на печать

 

Корректировка записей

1. Изменение общего количества

2. Изменение учетного номера

3. Изменение цены

4. Другие

 

Работа с дисками

1. Считывание текущей информации в память

2. Обновление информации

3. Запись на диск новых данных

 

Центральная часть блок-схемы представляет собой управляющую

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

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

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

2. Считывание карты модулем ввода.

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

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

5. Считывание информации с диска модулем ввода подпрограммы работы с дисками.

6. Вызов подпрограммы корректировки.

7. Работа модуля изменения общего количества подпрограммы обработки записей.

8. Вызов управляющей программой подпрограммы обмена с дисками.

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

10. Вызов подпрограммы печати, производящей преобразование формы представления данных и вывод этих данных на печать.

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

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

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

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

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

 



 
Статьи раздела