Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Питер_Гудлиф_Ремесло_программиста_Практика_написания_хорошего_кода.pdf
Скачиваний:
16
Добавлен:
19.04.2024
Размер:
9.23 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

200m

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

.

 

 

 

 

 

.c

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-xcha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

Глава 8. Время испытанийClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Метод черного ящика проверяет, не упущено ли что%нибудь (какие%ли% бо функции, предполагавшиеся в программном продукте), тогда как метод белого ящика обнаруживает ошибки в реализации. Полноценное тестирование программного блока требует применения обоих методов.

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

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

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

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

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

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

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Выборm

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

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

201Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

должен делать этот код. Он может очень хорошо работать – делая не то, что нужно.

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

Хорошие входные данные

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

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

Плохие входные данные

Столь же большое значение имеет ряд правильно подобранных пло# хих входных данных. Вы проверяете устойчивость приложения и отсутствие ложных ответов на ввод недопустимых данных.

Нужно рассмотреть все виды нехороших данных, в том числе:

Слишком большие или слишком маленькие числовые значения (часто забывают об отрицательных значениях).

Слишком длинные или короткие входные данные (классиче% ским примером служит длина строки; посмотрите, как код реа% гирует на пустую строку, или проверьте массивы и списки раз% ных размеров).

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

Граничные значения

Проверьте все граничные случаи – они часто служат источником ошибок. Определите наибольшее и наименьшее допустимые значе% ния или естественные границы ввода (например, те, которые изме% няют характер поведения). В каждом из этих случаев проверьте по% ведение кода:

На самом граничном значении

На значениях, превышающих границу

На значениях, несколько меньших границы

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

Граничные тесты обнаруживают частые ошибки, например ввод > вместо >= или неправильный выбор начального значения перемен% ной цикла (отсчитывать с нуля или с единицы?). Для обнаружения такого рода ошибок нужны все три граничных теста.

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

202m

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

.

 

 

 

 

 

.c

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-xcha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

Глава 8. Время испытанийClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Случайные данные

Не думайте долго – генерируйте случайные наборы входных дан% ных. Это очень эффективная стратегия тестирования. Если вы су% меете написать инфраструктуру тестирования, в которой много% кратно автоматически генерируются и применяются случайные входные данные, это усилит ваши возможности выявления скры% тых ошибок, о которых вы не догадались бы иначе.

Нуль

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

Указатели C/C++ часто принимают нулевые значения, когда значе% ние не определено или не задано. Проверьте, корректно ли воспри% нимает ваш код поступающие на вход нулевые значения указателей. В Java можно с той же целью подавать ссылки на нулевой объект.

Архитектура и тестирование

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

Архитектура кода должна облегчать его тестирование.

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

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

Необходимо заранее проектировать код в расчете на тестирование. Не так просто взять старую компоненту и прикрепить к ней «тестируе% мый» интерфейс. Если есть масса прочего кода, зависящего от сущест%

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Рукамиm

не трогать!

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

203Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

Есть ряд простых правил, соблюдение которых приводит к созданию кода, который действительно легко тестировать:

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

Не пользуйтесь глобальными переменными (или объектами single# ton, лишь прикрывающими глобальные переменные). Собирайте такие состояния в общие структуры, передаваемые в качестве аргу% ментов.

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

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

Руками не трогать!

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

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

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

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

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