Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Питер_Гудлиф_Ремесло_программиста_Практика_написания_хорошего_кода.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

 

 

 

Главаm

8. Время испытаний

 

 

 

 

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

 

 

 

 

 

615Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

Гораздо лучше кодировать в тщательно подобранном вами стиле, чем полагаться на установки редактора по умолчанию. Этого может потре# бовать стиль, принятый в фирме. Я лучше настрою свой редактор, что% бы он автоматически форматировал код так, как мне нужно, чем буду мучиться с перемещением курсора после каждого нажатия ENTER.

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

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

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

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

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

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

Вопросы для размышления

1.Напишите комплект тестовых примеров для кода определения наи большего общего делителя, приведенного в начале главы. Постарай тесь проверить как можно больше случаев. Сколько отдельных конт

рольных примеров у вас получилось?

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

616m

 

 

 

 

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

 

 

 

 

 

Ответы и обсуждениеClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

a.Сколько успешно прошло?

b.Сколько не прошло?

c.С помощью своих тестов найдите ошибки и исправьте код.

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

Затем напишите тесты для комбинаций обычных входных данных (на% пример, 1, 10 и 100 в любом порядке). После этого проверьте числа, у которых нет общих множителей, такие как 733 и 449. Проверьте рабо% ту для каких%нибудь очень больших значений и отрицательных чисел.

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

assert(greatest_common_divisor(10, 100) == 10); assert(greatest_common_divisor(100, 10) == 10); assert(greatest_common_divisor(733, 449) == 0);

... еще тесты ...

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

Нашли ли вы ошибку в greatest_common_divisor? Сейчас будет подсказ% ка. Если не хотите испортить загадку, отвернитесь… Попробуйте по# дать на вход отрицательный аргумент. Вот более надежная (и эф% фективная) версия, написанная на C++:

int greatest_common_divisor(int a, int b)

{

a = std::abs(a); b = std::abs(b);

for (int div = std::min(a,b); div > 0; div)

{

if ((a % div == 0) && (b % div == 0)) return div;

1Это открыло бы дорогу появлению новых ошибок кодирования – пред%

ставьте себе мучения из%за ошибок в тестовом коде!

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

8. Время испытаний

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

}

return 0;

}

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

617Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

2.Какие различия между тестированием приложения электронной таб лицы и системы автоматического пилотирования самолета?

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

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

игораздо тщательнее. Они строго тестируются. Действуют стандарты безопасности.

3. Нужно ли тестировать тестовый код, который вы пишете?

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

Пишите код тестов как можно проще, чтобы избежать в нем ошибок.

4.В чем разница между тестированием, проводимым программистом, и тестированием в отделе QA?

Тестеры чаще проводят тестирование в стиле черного ящика и обычно работают только с продуктом в целом. Они редко работают на уровне кода, потому что продукт обычно является исполняемой программой; библиотеки кода поставляются относительно редко.

Программисты чаще проводят тестирование в стиле «белого ящика», проверяя, что их творения работают в соответствии с замыслом.

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

5.Нужно ли писать набор контрольных примеров для каждой отдельной функции?

1Жаль, но мы вынуждены с этим смириться.

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

618m

 

 

 

 

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

 

 

 

 

 

Ответы и обсуждениеClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

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

6.Существует методика, требующая сначала писать тесты, а потом код. Какого рода тесты вы стали бы писать?

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

7.Следует ли писать тесты для C/C++, чтобы проверить правильность обработки параметров, имеющих значение NULL (нулевых указате лей)? В чем ценность такого теста?

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

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

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

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

Если код предназначен для работы в другой среде (например, на мощ ном сервере или во встроенном устройстве), как обеспечить адекват ность тестирования?

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

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

8. Время испытаний

 

 

 

 

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

 

 

 

 

 

619Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

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

9.Как определить, что проведено достаточно тестов? Когда можно оста новиться?

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

Для простых блоков кода при тестировании методом черного ящика достаточно успешно выполнить все тесты из раздела «Выбор контроль% ных примеров для блочного тестирования» на стр. 200.

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

Тестирование по охвату

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

Тестирование по количеству ошибок

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

Тестирование по типам ошибок

При этом подходе внимание обращается на те места, где чаще всего возникают ошибки. Например, тестируются все граничные значе% ния и выявляются все ошибки смещения на единицу.

Исходя из этого можно установить критерии прекращения тестирова% ния:

Успешно проходит определенный процент регрессивных тестов (при этом неудачные тесты не являются определяющими).

Охват кода, функциональности или требований достигает заданно%

го уровня.