Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
4. Текстовые файлы и циклическое выполнение.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
64.07 Кб
Скачать

4.2.2. Структурное тестирование

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

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

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

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

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

Для примера рассмотрим тест для DP 3A с входными данными XBZA. Очевидно, что все выражения будут выполнены, единственные части которые могут быть пропущены – операторы внутри выражений WHILE, для которых условие на входе равно FALSE.

Тестовый запуск программы 3B со входными данными CEDAR# проанализировать несколько более сложно. Для всех выражений WHILE выполняются части DO, но не понятно выполняются ли части THEN и ELSE внутри DP 3.2.1.1 В любом случае символ записан в F2, но это не дает нам информации, каким путем шло выполнение внутри оператора IF.

Часть THEN выполняется когда меняется текущий минимум, это происходит при первом проходе для CEDAR#, когда С заменяется на A при четвертой итерации для 3.2.1.1. С другой стороны, часть ELSE выполняется когда текущий минимум не меняется и это случается на второй итерации, когда C меньше чем E. Таким образом, CEDAR является адекватным структурным тестом. Анализ также показывает, что XHB# не может быть адекватным структурным тестом, поскольку часть ELSE для 3.2.1.1 не может быть достигнута.

4.2.3. Анализ SelectSort

В противоположность семейству IFSort и MinSort, размеры которых существенно растут с ростом размеров сортируемых строк, SelectSort может сортировать строки любого размера. Будучи по размеру не более, чем IFSort4 или MinSort6, SelectSort может сортировать строки в сотни и тысячи символов. Однако, время выполнения для SelectSort будет зависеть от длины входной строки. Количество шагов в данном случае может быть точно определено. Первое, сосредоточимся на выражениях WHILE, которые появляются в DP 3.1, 3.2, 3.2.1, 3.2.2. Исключая другие детали программы, выражения WHILE в SelectSort могут быть пронумерованы.

Номер WHILE

Структура и решаемые задачи

1

2

3

4

BEGIN

WHILE {Копировать INPUT в F1}

WHILE {Продолжать, пока F1 не пустой}

BEGIN

WHILE {Копировать все кроме мин. из F1 в F2}

WHILE {Копировать F2 в F1}

END

END

Предположим, что имеется N входных символов. Выражение WHILE номер 1 требует N итераций. Второе выражение WHILE также потребует N итераций, потому что F1 укорачивается на 1 символ при каждой итерации. Количество итерации для третьего и четвертого выражений WHILE зависит от номера итерации для выражения WHILE номер 2.

На первой итерации WHILE номер 2, WHILE номер 3 требует N итераций, а WHILE номер 4 – N-1 итераций. На второй итерации для WHILE номер 2, WHILE номер 3 требует N-1 итераций, а WHILE номер 4 – N-2 итераций и т.д. Таким образом, количество итераций будет следующим:

Выражение WHILE

Количество итераций

1

2

3

4

N

N

N + N-1+ … + 1

N-1 + N-2 + … + 1 + 0

Далее, посчитаем выражения READ и WRITE для каждого блока WHILE

Выражение WHILE

Операций READ/WRITE

1

2

3

4

2

1

2

2

Следовательно, количество выражений READ/WRITE выполняемых SelectSort, будет следующим:

Nrw = 2N + N + 2(N + (N-1) + … + 1) + 2((N-1) + (N-2) + … + 0)

= 5N + 4((N-1) + …+ 1)

= 5N + 4N(N-1)/2

= 5N + 2N2 – 2N

= 2N2+3N

Количество выражений READ/WRITE для входных последовательностей различной длины

N

Nrw

2N2

5

10

20

100

1000

65

230

860

20 300

2 003 000

50

200

800

20 000

2 000 000

Очевидно, что количество итераций Nrw в основном определяется составляющей 2N2. Мы можем сказать, что количество операций ввода-вывода для данной программы порядка 2N2. Т.е. 1000-строка будет сортироваться примерно в 100 раз дольше, чем 100-строка, и т.д. Время работы программы может быть довольно большим для еще более длинных строк.

Реверсирование строк с помощью выбора.

Программа SelectSort требует небольшой переделки чтобы стать программой для обращения строк. Единственная модификация, которая требуется – заменит DP 3.2.1 (которая выбирает минимальный из 1) на раздел, который может быть обозначен следующим комментарием:

{Выбрать последний символ в F1,

копировать остаток в F2}

Также в данном случае имеет смысл переименовать переменную Min в Last, чтобы название переменной соответствовало ее использованию в программе.

Повышение быстродействия SelectSort и SelectReverce

Скорость SelectSort и SelectReverce может быть увеличена примерно вдвое, если использовать F1 и F2 симметрично. Выбирать символ из F1 и копировать остаток в F2, затем выбирать символ из F2 и копировать остаток в F1 и т.д. Для того, чтобы определить, из какого файла читать и в какой копировать потребуется переключатель even/odd (четное/нечетное).

На самом деле, существует еще один способ ускорения SelectSort. Мы можем использовать внутренние переменные для того, чтобы хранить не один текущий минимум, а несколько на один проход. Например, с переменными Min1, Min2, Min3, Min4, Min5 пять минимальных хначений может быть найдено и выведено за один проход. Таким образом мы можем ускорить SelectSort примерно в 5 раз.

Используя оба приведенных приема, например с 10 переменными для хранения локальных минимумов и симметричного использования файлов, мы можем увеличить скорость работы программы в 20 раз, т.е. сократить время работы программы, например с 3 часов до 10 минут.