Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Давыдов В.Г. - Программирование и основы алгоритмизации - 2003

.pdf
Скачиваний:
839
Добавлен:
13.08.2013
Размер:
9.55 Mб
Скачать

П.4.3. Тестирование программного проекта

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

Одним из путей проверки или тестирования программы явля­ ется ее выполнение по одному разу с каждой из возможных комби­ наций входных данных — т.е. тестирование с использованием зара­ нее подготовленного набора контрольных примеров.

Требования к контрольным примерам. Какие же требования следует предъявить к контрольным примерам?

Таких требований всего два.

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

иобеспечить полную проверку программного проекта — протестиро­ вать все ветви, имеющиеся в программе.

Контрольные примеры должны быть простыми в том смыс­ ле, чтобы анализ ожидаемых результатов был несложным (примеры должны быть небольшой размерности со значениями исходных дан­ ных, удобными для анализа).

Отметим, что создание достаточного и простого набора кон­

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

Структура контрольного примера. Структура контрольного примера может быть, например, следующей:

цель примера;

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

анализ ожидаемых результатов (для примеров с нормальным за­

 

вершением - анализ ожидаемых результатов в точках останова);

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

 

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

 

Выбор точек

останова.

При выборе точек останова

можно

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

 

точки останова

следует

выбирать после выполнения

каждой

420

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

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

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

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

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

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

Программа запускается до первой точки останова так, как это указывалось выше. Если полученные машинные результаты сов­ падают с результатами анализа, приведенного в контрольном при­ мере, то аналогично программа запускается до следующей точки ос­ танова и т.д.

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

манды Debug I Stop Debugging (IDE MS Visual Studio C++ 6.0) или Run I Program Reset (IDE Borland C++ 3.1) прекращается. Програм­ ма повторно запускается до последней точки останова с хорошими результатами и с этого места выполняется по шагам с проверкой по­ лученных результатов (выполняется трассировка ошибочного участ­ ка). По результатам пошаговой проверки обнаруживается ошибка и текущий сеанс отладки также прекращается. Затем в исходный текст программы вносятся необходимые исправления и трассировка оши­ бочного участка повторяется. Этот процесс заканчивается после ис­ правления ошибок, о чем будет свидетельствовать получение в оче­ редной точке останова ожидаемых результатов.

Приложение П.5. Рекомендации по созданию

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

исходного текста.

П.5.1. Спецификация программного проекта

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

421

его спецификации. Спецификация

программного

проекта

включает

требования к обработке ошибок

и предупрелсдений,

а такэюе све­

дения о файловом и функциональном составе

программного

проек­

та и о взаимодействии функций проекта

друг с другом.

 

Прежде всего рассмотрим, что же понимается под предупреж­

дениями и ошибками. Предупреэюдение

необходимо

выдавать при

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

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

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

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

422

Файл Main.cpp

main() Главная функция

Proglnfo() Информация о прог­ рамме и командной строке

ReadMatrix() Чтение матрицы

WriteMatrix() Печать матрицы с заголовком

SwapUnits()

Перестановка элементов строк

Файл ErWarnW.cpp

ErrorWarningWork() Обработка ошибок и предупреждений

OpenFile() Открытие файла

CloseFile() Закрытие файла

Файл FileOC.cpp

Файл CheckCS.cpp

CheckComString() Контроль командной строки

1, 2, ..., 6 - порядок вы­ зова функций

Функция OpenFile() вызывается из функций ErrorWarningWork(), ReadMatrix() и WriteMatrix()

Функция CloseFile() вызывается из функций ErrorWarningWork(), ReadMatrix() и WriteMatrix()

Файл Matrix.срр

Функция ErrorWarningWork() вызывается из функ­

ций ReadMatrix() и WriteMatrix()

^Вызов функции Возврат из функции

Рис. 107. Файловая и функциональная структура программного проекта

Желаемый состав и интерфейс функций. Чтобы функции ввода и печати массива стали универсальными, надо их снабдить следующим интерфейсом:

// Прототипы

функций

 

 

 

void

ReadArray(

 

 

 

 

±nt

Arr[

N ],

//

Вводимый

массив

//

Файл

ввода

 

 

 

 

СЪАГ

Filelnp[

]

) ;

 

void.

PrlntArray

(

 

 

 

 

int

Arr [

N ] r

//

Выводимый

массив

//Файл вывода

char

FileOutf

7,

 

cha.r

Mode [ ] r

//

Режим открытия файла вывода

423

/ / Заголовок

для

печати

char

Header[

] ) ;

Перечисленные функции целесообразно разместить в отдель­ ном файле как универсальные и взаимосвязанные.

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

FILE * OpenFile (

//

Возвращает указатель

на структуру

 

//

со сведениями

об

открытом файле

//Открываемый файл

сЬлг

FileName[

],

Режим открытия

файла

 

сЬа.г

Mode [ ] ,

//

 

хпЬ

CloseFile(

ErrCode

) ; /

/ Код ошибки

 

 

void

 

 

 

 

 

 

//

За крыв аемый

файл

],

 

 

 

char

FileName [

со сведениями

о

закрываемом

//

Указатель

на

структуру

//файле

FILE

*pStrInfoFlle,

int

ErrCode

) ; / / Код ошибки

Об использовании командной строки при запуске программного проекта. С этой целью можно использовать, например, командную строку следующего вида:

Task02.еке Task02.1пр Task02,out [Enter]

При этом заголовок главной функции может иметь следующий

вид:

int main (

АгдС,

//

Возвращает

О при

успехе

аргументов

±пЬ

//

ARGument

Count:

число

 

char

*ArgV[

//

командной

строки

примере

3)

] ) /

/ Argument

Value:

массив

 

указателей

 

 

//

на

аргументы

командной

строки

 

 

//

(

в

примере

 

ArgV

[ 1

]

 

 

 

 

//

эквивалентно

 

 

"Task02,1пр"^

 

 

 

//

ArgVf

2

]

 

эквивалентно

 

//"Task02.out")

Для обработки ошибок в формате командной строки можно использовать функцию следующего вида (эта функция универсальна и ее целесообразно поместить в отдельный файл):

лго±<1

WorkCS (

 

 

 

int

ArgC,

// Число аргументов

командной

строки

424

(

±nt

 

ErrCode

) //

Код

ошибки

 

 

 

±f(

ArgC !=

3 )

 

 

 

 

 

 

 

 

 

 

 

 

 

 

{

printf(

 

 

 

 

 

 

 

"\n

 

 

 

 

формат командной

строки.

"

Ошибка

%d. Непредусмотренный

"\л

Для

запуска

программы

используйте

командную

строку

вида:"

"\п

Т4сполняемый_файл

Файл_ввода

Файл_вывода'\

ErrCode

) ;

 

e x i t

(

ErrCode

) ;

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

 

Об обработке ошибок и предупреждений. Чтобы многократно не дублировать аналогичные фрагменты, целесообразно использовать для обработки ошибок и предупреждений универсальную функцию, кото­ рую следует поместить в отдельный файл. Эта функция может иметь, например, такой вид:

// Прототип

сЬат Msg[

] , char

Type^

•vo±(X ErrWarnWork ( xnt ErrWarnCode,

cbar FileOutl

] = "", сЬаг

Mode[ ]

= "" ) ;

//Определение

void

ErrWarnWork(

предупреждения

 

 

 

//

Код

ошибки или

 

 

 

±nt

 

ErrWarnCode,

Строка

сообщения

 

 

char

Msg[ ],

//

 

выдается

char

Type,

//

'е'

-

ошибка,

сообш,ение

 

 

 

//

на

экран,

'w' -

предупреждение,

 

 

 

//

сообш,ение

выдается

в

файл на МД

//Файл вывода

char

 

 

FlleOutf

)

],

Режим открытия

 

файла

вывода

cha.r

 

 

Mode [ ]

//

 

swibch(

 

Туре )

 

 

 

 

 

 

 

 

{

'е'

:

 

 

 

 

 

 

 

 

 

ca.se

 

 

 

 

 

 

 

 

 

printf(

"\п Ошибка

%d. %s ",

ErrWarnCode,

Msg ) ;

exit

( ErrWarnCode

)

;

 

 

 

 

 

case

'w*:

 

 

 

 

 

 

 

 

 

//

 

Здесь

открывается

файл

FileOut

в

режиме Mode

//

 

(получаем

указатель

pFileOut

с

типом

FILE *)

fprintf

( pFileOut,

 

 

"\п Предупреждение

%d. %s ",

//

Здесь

ErrWarnCode,

Msg

) ;

указателем

pFileOut

закрывается

файл

с

break; cLefavLl Ь: printf(

425

"\п

Ошибка

%d.

 

Использован

недопустимый тип

сообщения:"

"\п

используйте

 

\'е\'

или

\'w\'

", ErrWarnCode

) /

 

exit(

ErrWarnCode

) ;

 

 

 

}

 

 

 

 

 

 

 

 

retvLrn;

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

//

Пример

вызова

для

предупреждения

 

//Для сообш,ения

ch&r

 

 

buff

200

];

 

 

 

 

 

 

//

Формируем

текст

предупреждения

с

форматами

. . . ",

sprint

f (

bufr

" . . .

Управляюш,ая

строка

 

 

 

список

аргументов

для

форматов

)

;

 

 

ErrWarnWork(

40,

buf,

'W,

ArgV[

2 ], "a"

) ;

 

 

//

Пример

вызова

для

ошибки

 

ошибке

 

 

 

 

//

Формируем

текст сообщения об

с

форматами

. .

.",

sprint

f (

buf,

" . . .

Управляющая

строка

 

 

 

список

аргументов

для

форматов

)

;

 

 

ErrWarnWork(

50,

buf,

'е'

) ;

не

нужны

и

их не

записываем.

//

!!!

Два последних

аргумента

//

Так

можно делать, так как

2

последних

параметра

имеют

//значения по умолчанию - см. прототип

Обработка ошибок и предупреждений,

1. Ошибка открытия файла.

При возникновении данной ошибки программа прерывает ра­

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

"Ошибка № XX. Ошибка

открытия файла <имя.расширение> для чте­

ния/записи/дозаписи.

"

Код ошибки и код возврата задаются в вызове функции откры­

тия файла,

 

2. Предупреждение о том, что файл не закрыт.

При возникновении данной ситуации программа выдает на эк­

ран следующее сообщение:

 

 

 

 

 

"Предупреждение

№ XX.

Файл

<имя.расширение>

не закрыт.

Выпол­

нение

программы

продолжено."

 

 

 

 

 

Код предупреждения задается в вызове функции закрытия

файла.

 

 

 

 

 

 

 

 

 

 

3. Неверный режим открытия файла.

 

 

 

 

При возникновении данной ошибки программа прерывает ра­

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

режим

<режим> от­

"Ошибка

№ XX.

Использован

непредусмотренный

крытия

файла

<имя.расширение>.

Используйте

режимы

"г",

"rt",

"w",

"wt", "а"

или

"at"

(на любом регистре)

. "

 

 

Код ошибки и КОД возврата задаются в вызове функции закры-

426

тия файла.

3. Неверный тип выдаваемого сообщения.

При возникновении данной ситуации программа выдает на эк­ ран^ следующее сообщение:

"Предупреждение

№ XX.

Использован

непредусмотренный

<тип> вы­

даваемого

 

сообщени

вместо 'е' или 'w'. Применен

режим

'w',

выполнение

программы

продолжено,

"

 

 

 

 

 

 

 

Код предупреждения задается в вызове функции обработки

предупреждений и сообщений об ошибках.

 

 

 

 

 

 

4. Недопустимое значение количества строк матрицы.

 

 

 

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

работу, выдавая в файл результатов следующее сообщение:

 

 

"Предупреждение

№ XX.

Из файла

<имя.расширение>

прочитано

не­

допустимое

значение

количества

строк

матрицы,

равное ...

(коли­

чество

строк

должно

лежать в

диапазоне

от

2 до

...) .

Принимает­

ся

количество

строк

2 ,

выполнение

программы

 

продолжается."

 

Код предупреждения задается в вызове функции обработки

предупреждений и сообщений об ошибках.

 

 

 

 

 

 

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

 

 

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

работу, выдавая в файл результатов следующее сообщение:

 

 

"Предупреждение

1? XX.

Из файла <имя.расширение>

прочитано

не­

допустимое

значение

количества

столбцов

матрицы,

 

равное

(количество

столбцов

 

должно

лежать

в диапазоне

от 2

до

...) .

Принимается

количество

столбцов

2, выполнение

программы

про­

должается.

"

 

 

 

 

 

 

 

 

 

 

 

 

Код предупреждения задается в вызове функции обработки

предупреждений и сообщений об ошибках.

 

 

 

 

 

 

6. Ошибка чтения значения количества строк матрицы.

 

 

 

При возникновении данной ошибки программа прерывает ра­

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

 

 

 

 

 

"Ошибка

I? XX.

Ошибка

чтения

значения

количества

строк

матрицы

из

файла

<имя.расширение>."

 

 

 

 

 

 

 

 

 

Код ошибки и код возврата задаются в вызове функции обра­

ботки предупреждений и сообщений об ошибках.

 

 

 

 

 

7. Ошибка чтения значения количества столбцов матрицы.

 

 

При возникновении данной ошибки программа прерывает ра­

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

 

 

 

 

 

"Ошибка

№ XX.

Ошибка

чтения

значения

количества

столбцов

мат­

рицы из

файла

<имя.расширение>."

 

 

 

 

 

 

Код ошибки и код возврата задаются в вызове функции обра­ ботки предупреждений и сообщений об ошибках.

427

8. Ошибка чтения значения элемента матрицы.

При возникновении данной ошибки программа прерывает ра­ боту, выдавая на экран следующее сообщение:

"Ошибка № XX.

Ошибка

чтения значения

элемента матрицы с

номе­

ром строки ... и

номером

столбца ... из

файла <имя.расширение>.

"

Код ошибки и код возврата задаются в вызове функции обра­ ботки предупреждений и сообщений об ошибках.

9. Преждевременный конец файла исходных данных.

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

"Предупреждение

XX.

Файл

ввода

 

<имя .расширение>

содержит

недостаточное

количество

данных

(преждевременный

конец

фай­

ла) . Непрочитанные

элементы

матрицы

инициализируются

 

нулями.

Выполнение программы

 

продолжается."

 

 

 

Код предупреждения задается в вызове функции обработки предупреждений и сообщений об ошибках.

10. Избыточное количество данных в файле исходных данных. При возникновении данной ситуации программа продолжает

работу, выдавая в файл результатов следующее сообщение:

"Предупреждение

№ XX.

Файл ввода

<имя .расширение

> содержит

лишние данные г

которые

игнорируются

программой.

Выполнение

программы

продолжается."

 

 

Код предупреждения задается в вызове функции обработки предупреждений и сообщений об ошибках.

11. Неверное количество аргументов командной строки.

При возникновении данной ошибки программа прерывает ра­ боту, выдавая на экран следующее сообщение:

"Ошибка

№ XX.

Использован

неверный

формат

командной

в

строки.

Обработка

матрицы,

заключающаяся

в

том,

что

каждой

строке

 

матрицы ищется

максимальный

элемент.

Элементы,

стояш^е

после

максимального

элемента,

заменяются

 

нулями и

помещаются

в начало

строки.

Исходная

и

вновь

полученная

матрицы

печата­

ются.

Запуск

программы

выполняется

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

 

командной

строки

 

вида:

 

 

. ехе

 

файл__ввода

файл_вывода

. "

 

имя_выполняемого_файла

 

 

Код ошибки и код возврата задаются в вызове функции обра­ ботки командной строки.

П5.2. Пример оформления исходного текста программы

/*

Файл TASK02.CPP

Проект

: многофайловый

с

функциями.

428

 

 

 

 

 

 

 

 

 

 

расположенными

 

в

отдельных

 

 

файлах

Назначение

 

 

 

 

 

:

вычисление

 

площади

 

садового

 

 

 

 

 

 

 

 

 

 

 

участка

Square

:=

Length

 

*

Width

Состав

 

проекта

 

(файл

 

 

 

 

 

 

 

 

 

 

 

 

 

проекта

TASK02.PRJ)

 

 

:

файл

TASK02.СРР

(главная

 

функция

 

 

 

 

 

 

 

 

 

 

проекта);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

файл TASK02_1. СРР

 

(ввод

длины

и

 

 

 

 

 

 

 

 

 

 

ширины

 

садового

участка)

;

 

 

 

 

 

 

 

 

 

 

 

 

файл

TASK02_2.СРР

 

(печать

 

длины и

 

 

 

 

 

 

 

 

 

 

ширины

 

садового

участка)

 

;

 

 

 

 

 

 

 

 

 

 

 

 

файл

TASK02_3.СРР

 

(вычисление

 

 

 

 

 

 

 

 

 

 

площади

садового

 

участка)

;

 

 

 

 

 

 

 

 

 

 

 

 

файл

4.

СРР

(печать

площади

 

 

 

 

 

 

 

 

 

 

 

 

садового

 

участка)

 

 

 

ЭВМ

 

 

 

 

 

 

 

 

:

IBM

80386

 

 

 

 

 

 

 

Среда

 

программирования:

 

 

ВС31

(C++)

 

 

 

 

 

 

 

Операционная

система

 

:

DR

DOS

6.О

 

 

 

 

 

 

 

Дата

 

создания

 

 

 

 

:

 

02.11.2002

 

 

 

 

 

 

 

Дата

 

 

 

корректировки

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Иванов

 

И.

И.,

ФТКг

гр.

 

1081/4

 

 

 

 

 

 

 

 

 

 

Санкт-Петербургский

 

 

государственный

 

 

 

политехнический

 

университет

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

_V

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

// Стандартные

включаемые

 

файлы

и прототипы

функций

 

 

iinclude

 

 

 

"task02.h"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

±nt main

(

void

)

 

 

 

//

Возвращает

О при

 

успехе

 

 

{

 

 

 

 

Lenght,•

 

//

Длина

садового

 

участка

 

 

 

float

 

 

 

 

 

 

 

 

 

 

 

 

 

Width,

 

 

//

Ширина

садового

участка

 

 

 

 

 

 

 

 

Square;

 

//

Площадь

садового

 

участка

 

 

//

Ввод

длины

и

ширины

садового

 

участка

 

 

 

 

 

ReadData(

 

Lenght,

 

Width

)

;

 

 

 

 

 

 

 

 

 

 

//

Печать

длины

и

ширины

садового

 

участка

 

 

 

 

WriteDat(

 

Lenght,

 

Width

)

;

 

 

 

 

 

 

 

 

 

 

//

Вычисление

площади

 

садового

 

участка

 

 

 

 

 

Area

(

Lenght,

Width,

Square

) ;

 

 

 

 

 

 

 

 

 

WriteRes

 

(

Square

)

;

//

Печать

площади

садового

 

участка

jcebvLxrn. О;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

//

Конец

файла

 

TASK02.CPP

 

 

 

429