Глава 18. Стратегия тестирования
Глава 18.
Стратегия тестирования
Мы будем писать тесты перед тем, как приступить к кодированию. Это будет происходить каждый раз, когда мы будем садиться за решение очередной задачи. Мы сохраним эти тесты навечно и будем запускать их все вместе очень часто. Мы также будем писать тесты с точки зрения заказчика.
Какая жалость! Никто не хочет разговаривать о тестировании. Тестирование – это гадкий утенок индустрии разработки программного обеспечения. Проблема состоит в том, что каждый знает о важности тестирования. Каждый знает о том, что делает тестирование недостаточно хорошо. И мы видим это – наши проекты не реализуются так, как нам хотелось бы, и мы чувствуем, что тестирование в большем объеме может помочь решению проблемы. Но после этого мы беремся за чтение книги, посвященной тестированию, и увязаем в огромном количестве методик и разновидностей тестирования. Ни за что на свете нам не удастся выполнить все эти предписания и при этом завершить работу в срок.
В ХР тестирование выглядит следующим образом. Каждый раз, когда программист пишет некоторый код, он думает, что этот код будет работать. Каждый раз, когда программист думает, что некоторый код будет работать, он берет свою уверенность из вселенского эфира и воплощает ее в артефакт, который становится частью программы. Теперь уверенность внутри, и программист может ею пользоваться. А так как уверенность теперь внутри программы, остальные люди могут также воспользоваться этой уверенностью.
То же самое можно сказать и о заказчике. Каждый раз, когда заказчик думает о чем-то конкретном, что должна делать программа, он превращает это в еще один кусок уверенности и размещает его внутри программы. Теперь уверенность заказчика тоже находится внутри программы рядом с уверенностью программиста. Общая уверенность в работоспособности программы со временем все увеличивается и увеличивается.
Теперь вы можете взглянуть на тестирование в ХР и хихикнуть: ведь это не работа для тех, кто любит тестирование, наоборот, это работа для тех, кто любит заставлять программы работать. Вы пишете тесты, которые помогают вам добиться работоспособности создаваемых вами программ, а также обеспечить работоспособность программ, которые вы модифицируете. И ничего больше.
Вспомните принцип: Работать совместно с человеческой природой, а не вопреки ей. С этим связана фундаментальная ошибка, которая присутствует во всех книгах по тестированию, которые я прочитал. Все подобные книги начинаются с предположения, что тестирование – это центр разработки. Вы должны сделать этот тест и тот тест и, о да, конечно, вон тот тест тоже. Если мы хотим, чтобы программисты и заказчики писали тесты, мы должны сделать процесс разработки настолько безболезненным, насколько это возможно. Мы должны рассматривать тесты как инструмент разработки. Тесты – это инструмент, помогающий понять поведение системы, а поведение системы формируется разработчиками, а не самими тестами. Если бы было возможно осуществлять разработку без тестов, мы могли бы выбросить все тесты в одну минуту.
Массимо Арнольди (Massimo Arnoldi) пишет:
К сожалению, по крайней мере для меня (и не только), тестирование – это нечто противоречащее человеческой природе. Где-то очень глубоко в каждом из нас сидит грязная неряшливая свинья, и если ее выпустить на свободу, мы будем писать программы совсем без тестов. Спустя некоторое время после этого у нас внутри победу одерживает рациональная сторона, мы останавливаемся и начинаем писать тесты. Следует обратить внимание, что программирование в паре снижает риск пробуждения свиньи, так как маловероятно, что в одно и то же время свиньи проснутся в обоих партнерах одновременно.
Массимо Арнольди (Massimo Arnoldi). Источник: электронная почта.
Тесты, которые необходимо писать в рамках ХР, являются изолированными и автоматическими. Во-первых, каждый тест никак не взаимодействует с остальными тестами, которые вы пишете. Таким способом вы избегаете ситуации, когда сбой в одном из тестов является причиной несрабатывания сотен других тестов. Ничто не разочаровывает нас так сильно, как ложные негативные результаты. Утром вы приходите на работу, обнаруживаете огромное количество дефектов, и у вас в кровь выделяется огромное количество адреналина. А потом обнаруживается, что весь этот ворох проблем решается при помощи коррекции одного из тестов. Будете ли вы относиться к тестам с должным вниманием после того, как описанное произойдет с вами пять или десять раз? Нет.
Во-вторых, тесты автоматические. Тесты наиболее полезны тогда, когда уровень стресса повышается, когда люди работают слишком много, когда человеческий здравый смысл начинает ослабевать. В подобных ситуациях было бы неплохо обладать быстрым и простым способом проверки работоспособности системы. Именно поэтому тесты работают автоматически – вы запускаете их и фактически сразу же получаете короткий односложный ответ: система работает корректно или система работает некорректно.
Протестировать абсолютно все невозможно – для этого тесты должны быть столь же сложными и столь же беззащитными перед ошибками, как и сам код приложения. Ничего не тестировать (в смысле изолированных автоматических тестов) – это самоубийство. Но тогда из всех вещей, которые можно протестировать, что именно вы должны тестировать?
Вы должны тестировать вещи, которые могут не сработать. Если код настолько прост, что он просто не может работать некорректно, и вы видите, что на практике данный код всегда срабатывает, тогда вы можете не писать для него код. Если бы я сказал вам, что надо тестировать абсолютно все, в скором времени вы пришли бы к выводу, что большая часть тестов, которые вы пишете, на самом деле бесполезна, и, если в этом отношении вы схожи со мной, вы перестали бы их писать. Эти тесты предназначены для идиотов!
Тестирование – это ставка. Ставка, которая оправдывает себя в случае, если оказывается, что ваши ожидания не соответствуют действительности. Тест может оправдать свое создание в ситуации, когда он срабатывает при том, что вы не ожидали, что он будет срабатывать. В этом случае вы должны выяснить, почему он срабатывает, так как код умнее, чем вы. Еще одна ситуация, в которой тест оправдывает свое создание, это когда тест не срабатывает, а вы ожидали, что он должен сработать. Очевидно, что в этом случае вы также должны разобраться, в чем дело. В обоих случаях вы узнаете кое-что новое о разрабатываемой вами программе. Разработка программного обеспечения – это получение новых знаний. Чем больше вы знаете, тем лучше вы разрабатываете код.
Таким образом, если у вас есть такая возможность, вы должны писать только те тесты, которые оправдывают затраты на свою разработку. Однако вы не можете заранее знать, какие из тестов оправданы, а какие – нет (если бы вы знали, это означало бы, что все необходимые знания у вас уже есть и вам не нужно узнавать ничего нового), поэтому вы должны разрабатывать тесты, которые могут оказаться оправданными. По мере того, как вы пишете тесты и выполняете тестирование, вы анализируете, какие разновидности тестов чаще оказываются оправданными, а какие – нет, и с течением времени вы начинаете писать все больше оправданных тестов и все меньше неоправданных.
Кто пишет тесты?
Как я уже говорил в самом начале главы, тесты возникают из двух источников:
• программисты
• заказчики
Программисты пишут тесты для каждого из методов. Тесты, разрабатываемые программистами, называются тестами модулей (unit test). Программист создает тест при следующих условиях:
• если интерфейс метода совершенно неясен, вы пишете сначала тест, а затем метод;
• если интерфейс ясен, однако вы полагаете, что при реализации могут возникнуть хотя бы и незначительные проблемы, вы пишете сначала тест, а затем метод;
• если вы обдумываете необычные условия, в которых код должен работать так, как это предполагается, вы должны написать тест для того, чтобы описать эти условия;
• если позже вы обнаруживаете проблему, вы должны написать тест, который изолирует эту проблему;
• если вы занимаетесь переработкой кода и вы не уверены в том, корректно ли он будет вести себя после переработки, и еще не существует теста, позволяющего проверить интересующий вас аспект поведения кода, вы должны вначале написать тест.
Написанные программистами тесты всегда срабатывают на 100%. Если один из тестов модулей не срабатывает, ни для одного члена команды не может быть другой более важной работы, чем исправление теста. На это может уйти минута. Но, может быть, для этого вам потребуется месяц. Вы не знаете заранее. И потому, что программисты контролируют написание и исполнение тестов модулей, они могут поддерживать все тесты в состоянии полной синхронизации с кодом системы.
Заказчики пишут тесты для каждой из историй. При этом они должны задавать себе вопрос: Что еще должно быть проверено, прежде чем я буду уверен в том, что реализация этой истории полностью завершена? Каждый создаваемый ими сценарий должен быть превращен в тест. В данном случае тесты называются функциональными.
Функциональные тесты не обязательно должны в любой момент времени срабатывать на все 100%. Дело в том, что эти тесты появляются из источника, который не является источником кода системы. По этой причине я не могу представить себе универсального способа синхронизации функциональных тестов и кода системы в такой степени, в какой синхронизированы с кодом системы тесты модулей. В то время как для тестов модулей может быть только две оценки – 100% или ноль, работоспособность функциональных тестов, как правило, оценивается в процентном отношении. Ожидается, что спустя некоторое время все функциональные тесты должны срабатывать на все 100%. По мере приближения сроков выпуска очередной версии продукта, заказчик должен категоризировать не срабатывающие функциональные тесты. Некоторые из них являются для него более важными, чем другие. Исправление более важных функциональных тестов необходимо выполнять в первую очередь.
Как правило, заказчики не могут писать функциональные тесты самостоятельно. Они нуждаются в помощи того, кто сможет транслировать предоставляемые ими тестовые данные в собственно тесты, а также с течением времени разработать инструменты, при помощи которых заказчики могли бы писать, запускать и поддерживать свои собственные тесты самостоятельно. Именно поэтому команда ХР любого размера должна включать в себя, по меньшей мере, одного программиста, основной обязанностью которого будет функциональное тестирование системы в тесном сотрудничестве с заказчиком. Его называют тестером (tester). Этот человек должен превращать временами весьма туманные идеи заказчика о функционировании системы в реальные, автоматические, изолированные тесты. Программист, занимающийся тестированием, также должен использовать разработанные с помощью заказчика тесты в качестве основы при создании разнообразных вариаций, которые могли бы указать на некорректное функционирование системы.
Даже если роль такого специалиста по функциональному тестированию играет человек, который получает удовольствие от взламывания программ, которые по идее должны быть готовы к использованию, этот человек должен работать в тех же экономических рамках, в которых работают и остальные программисты, занимающиеся разработкой тестов модулей.
Иными словами, этот программист должен рассматривать каждый тест, как ставку в игре, надеясь на то, что тест сработает там, где ожидается его сбой, и на то, что тест не сработает там, где ожидается, что он должен сработать. Другими словами, этот программист должен писать только те тесты, разработка которых оправданна. Благодаря этому с течением времени он начинает производить все лучшие и лучшие тесты, тесты, которые с большей вероятностью оправдываются. Программист, занимающийся тестированием, существует вовсе не для того, чтобы создать как можно больше тестов. Его задача – создать тесты, которые лучше всего подчеркивают функциональность или, наоборот, недееспособность системы.
Другие тесты
Функциональные тесты и тесты модулей являются сердцем используемой в рамках ХР стратегии тестирования, однако помимо них существуют также и другие тесты, использование которых может быть оправданно в определенных ситуациях. Команда ХР должна проанализировать, в какой момент работы над проектом можно сбиться с пути, при этом необходимо определить, какие новые тесты могут оказаться полезными. Возможно, потребуется использовать следующие разновидности тестов (или любые другие тесты, описания которых можно найти в любой посвященной этому вопросу книге):
• Параллельный тест (parallel test) – этот тест предназначен для того, чтобы доказать, что новая система работает в точности, как старая система. На самом деле тест демонстрирует, насколько новая система отличается от старой. При этом заказчик может принять решение о том, насколько удовлетворительным для него является различие и допустима ли эксплуатация новой системы в промышленных условиях.
• Стресс-тест (stress test) – этот тест разрабатывается для того, чтобы сымитировать наиболее высокую нагрузку на систему. Стресс-тесты применяются для тестирования сложных систем, для которых сложно делать предположения о характеристиках, связанных с производительностью.
• Тест обезьяны (monkey test) – этот тест предназначен для того, чтобы продемонстрировать, что система корректно реагирует на бессмысленный, неподдерживаемый или запрещенный ввод.
Данный текст является ознакомительным фрагментом.