Четыре фрейма тестирования, часть 5: Намерение, Дисциплина, Тестируемость, Реализация |
08.10.2025 00:00 |
Автор: Майкл Болтон (Michael Bolton) В прошлой статье я описал четыре фрейма тестирования, каждый из которых может дать нам набор идей для покрытия продукта на разных этапах его разработки. По ходу работы над пакетом, системой или сервисом люди генерируют множество разных идей и артефактов, каждый из которых можно протестировать. Более того, люди с разными интересами, темпераментами и ролями в процессе разработки воспринимают тестирование по-разному. Хотя фреймы расположены так, что кажутся идущими по часовой стрелке, они необязательно последовательны — об этом будет сказано позже. Фреймы обозначены как Намерение, Дисциплина, Тестируемость и Реализация.
Давайте рассмотрим их по очереди. НамерениеДизайн — это проработка идей и намерений. По мере их развития мы можем их тестировать. Тестирование в рамках Намерения фокусируется на том, чтобы оспаривать идеи о том, каким продукт может и должен быть, с целью выявить и устранить проблемы с дизайном до начала создания продукта. Нам может быть сложно чётко понять, чего мы хотим, пока мы ещё ничего не создали. Разные люди имеют разные продуктовые цели и видят ценность в различных аспектах продукта. Большая часть программного обеспечения создаётся для большего числа клиентов, чем мы когда-либо сможем встретить лично, поэтому нам нужно моделировать клиентское пространство. Чтобы сделать это хорошо, необходимо взаимодействовать с ними и учитывать разнообразие клиентов и их ролей, оценивая размах их потребностей и желаний. Разумеется, клиенты — не единственные, кого стоит учитывать при разработке. Программное обеспечение нужно тестировать, поддерживать, сопровождать, документировать, продвигать, продавать и управлять им. Каждый человек, вовлечённый в эти процессы, может иметь свои специфические потребности и ожидания от продукта, и некоторые из них могут конфликтовать друг с другом. Урегулирование противоречивых потребностей и желаний часто требует компромиссов в дизайне и реализации. В рамках процесса проектирования также полезно проработать идеи о том, что можно считать завершённым продуктом. Таким образом, когда мы с оптимизмом воображаем успех и приступаем к созданию продукта, мы прорабатываем дизайн. В ходе этого процесса мы проводим тестирование и ревью, ориентированные на наши представления о требованиях, критериях приёмки, архитектуре, спецификациях, макетах, каркасах, планах — а также на документы и другие артефакты, отражающие наши идеи. То есть мы проводим тестирование, связанное с развитием и уточнением наших намерений, чтобы эффективнее создавать продукт. Тестирование в рамках этой модели может включать обсуждения, мысленные эксперименты и анализ идей, прототипов или черновиков. Такие подходы, как Behavior Driven Development (BDD) и Acceptance Test Driven Development (ATDD), направлены на уточнение намерений. Подход «Knowledge crunching» (обработка знаний), описанный Эриком Эвансом в Domain-Driven Design, — ещё один пример работы по развитию и уточнению намерений. Когда эта деятельность ведется на высоком уровне, она включает проактивное тестирование — по крайней мере один человек сознательно берет на себя роль критика и задает вопросы:
Вопросы «Что может пойти не так?» и «Как мы это узнаем?» особенно полезны, поскольку стимулируют команду задуматься о внутренней и проектной тестируемости (я к этому еще вернусь) ещё на этапе дизайна. В рамках модели Намерения мы, в частности:
Обратите внимание, что этот вид работы по своей природе является исследовательским! Он может дополняться чек-листами, но не имеет жёсткого сценария. Многие специалисты по качеству, похоже, особенно увлечены разработкой и уточнением намерений, помогая нам создавать правильный продукт, избежать создания неправильного и предотвратить появление ошибок в продукте. Это отличная практика — четко, полно и точно формулировать намерения. Как сказал Кем Кейнер ещё в 1993 году: программа, идеально построенная по плохому техническому заданию, — это плохая программа, а не идеальная. Мотивация тестирования, ориентированного на намерения, — сэкономить время и усилия, выявляя проблемы как можно раньше, то есть «сдвигая тестирование влево» по шкале разработки. ДисциплинаПосле того как дизайн разработан, мы приступаем к созданию продукта. Создавая его, мы хотим сохранить высокую ценность работы и снизить стоимость изменений, действуя добросовестно и дисциплинированно. Даже когда намерения ясны, есть риск ошибок. Люди, как поодиночке, так и в командах, не всегда реализуют именно то, что задумали. Даже самые опытные разработчики подвержены случайным ошибкам, недоразумениям и упущениям при написании нового кода. Изменения тоже несут риск промахов. Эти проблемы часто обходятся дорого и отнимают время. Мы не можем избежать всех проблем, но можем предотвратить множество очевидных, если будем работать тщательно, аккуратно и просто. Быстро реагировать на ошибки можно при регулярном проведении ревью и тестирования по ходу разработки. Таким образом, дисциплинированные и усердные разработчики во время написания и доработки кода выполняют тестирование, направленное на быстрое и полезное получение обратной связи, чтобы исправлять относительно легко обнаруживаемые ошибки, которых можно избежать. Часть тестирования может быть неформальной: написать небольшой кусок кода, запустить его и посмотреть, что получится. Разработчики часто проводят эксперименты с отдельными модулями или компонентами, используя заглушки, симуляторы или «тестовые двойники», а не взаимодействуют с продуктом в целом. Некоторая часть разработки и тестирования может быть более формализованной. Методология разработки через тестирование (TDD) предполагает, что перед написанием нового кода разработчик сначала пишет unit-тесты. Изначально каждый тест должен завершаться неудачей, поскольку код, который должен сделать тест успешным, ещё не написан. Когда код написан, разработчик запускает тесты — и если какой-то тест не проходит, он сразу получает обратную связь о проблеме и может успешно исправить ошибку. Некоторые виды работы по дисциплине могут быть совместными: формальные обзоры кода, парное программирование (одна голова – хорошо, а две - лучше) или «командное» программирование (звучит лучше, чем «mob programming»). Автоматизированная проверка выходных данных в юнит-тестах, низкоуровневой интеграции и с целью избежать регресса – важная часть дисциплины. Тестирование в этом контексте может включать контрактное тестирование или его более исследовательского родственника — тестирование свойств (property-based testing). Проверки вывода можно автоматизировать. То тестирование, которое их окружает – анализ рисков, проектирование проверок перед прогоном, интерпретацию и оценку результатов — нет. Тестирование в рамках Дисциплины требует опытных разработчиков с хорошими социальными навыками. Тестирование в рамках дисциплины обычно неглубокое и не фокусируется на всей системе — это сделано намеренно, и это хорошо. Оно быстрое, не слишком интенсивное и не сильно отвлекает разработчиков от работы. Цель — не найти все в мире ошибки, а убедиться, что мы делаем то, что задумали, и сразу получить сигнал, если что-то идёт не так. Во фрейме Дисциплины, среди прочего, мы:
Тестирование в рамках Дисциплины — и обсуждение этой темы — обычно сконцентрировано на программистах/разработчиках, то есть тех, кто работает непосредственно с кодом. Для участников движения экстремального программирования (XP), сторонников TDD и многих из сообщества Agile, именно это и есть тестирование: получение немедленной обратной связи о проблемах на уровне кода, чтобы их можно было оперативно устранить и не дать им «затеряться». Всё это — другой аспект концепции «сдвига тестирования влево». ТестируемостьФрейм Тестируемости сосредоточен на подготовке продукта к эффективному и глубокому тестированию, а также на отстаивании и улучшении его практической тестируемости. Продукт становится более тестируемым — и проблемы в нём легче обнаруживаются, — когда в нем есть функции, обеспечивающие его прозрачность (логирование, мониторинг, возможность запросов к продукту и его данным) и управляемость (интерфейсы для управления или перенастройки продукта). В Rapid Software Testing это называется внутренней тестируемостью. Другие аспекты тестируемости — это простота, модульность и чистота кода. Оформление багов в забагованном продукте отнимает у тестирования время. Однако практическая тестируемость — это не только внутренняя тестируемость. Существуют и другие измерения тестируемости, которые влияют друг на друга и не менее важны. Когда мы хорошо знаем продукт, технологии, которые в нем применяются, и предметную область, которую он представляет, разрыв между тем, что мы знаем, и тем, что нам нужно знать, чтобы руководство могло принимать обоснованные решения, становится меньше. Сужение этого разрыва — это повышение эпистемической тестируемости. Тестировать легче, когда контекст этому способствует — когда вся команда тесно сотрудничает, информация по проекту аккуратно собирается и легко доступна, а также есть свободный доступ к оборудованию и инструментам, поддерживающим разработку и тестирование; это называется тестируемостью, связанной с проектом. Непрерывная интеграция и непрерывное развертывание представляют ещё один аспект тестируемости, связанной с проектом. Тестировать продукт намного проще, когда его можно быстро и надёжно собрать. Тут стоит обратиться к пайплайнам сборки и развертывания, включая автоматические проверки, которые алгоритмически выявляют ошибки и упущения. Также продукт легче тестировать, когда команда проекта имеет доступ к разным заинтересованным лицам и знает, что именно им нужно. Это не только заказчики продукта, но и все, кого продукт касается или кто на него влияет: разработчики, дизайнеры, менеджеры, службы поддержки, операционные специалисты и другие лица. Часто у них есть информация, знания или опыт, которые помогают тестировать эффективнее и результативнее — на этом основана тестируемость, связанная с ценностью продукта. Тестирование становится быстрее и проще, когда у участников есть необходимые знания и навыки для предвидения, поиска, распознавания и сообщения о проблемах и рисках. Это включает обучение, инструменты, ресурсы и поддержку персонала, что мы называем субъективной тестируемостью. Обратите внимание, что фрейм Тестируемости не обязательно следует за фреймами Намерения или Дисциплины; он тесно переплетен с ними, влияя на выбор и действия людей в обеих сферах. Основная цель фрейма Тестируемости — сосредоточить внимание на подготовке к глубокому тестированию, которое может потребоваться после того, как продукт будет создан. Итак, в рамке Тестируемости, помимо прочего, мы:
Энтузиасты DevOps и специалисты, участвующие в настройке непрерывной интеграции и непрерывной доставки (CI/CD), особенно заинтересованы в тех типах тестирования и проверок, которые стимулирует фрейм Тестируемости — ещё один пример концепции «сдвига тестирования влево». РеализацияПока у нас нет готового продукта, мы работаем либо с его компонентами, либо с нашим представлением о конечном продукте. Фрейм Реализации — это момент, когда всё становится реальным. «Реализация» тут — игра слов. Наконец мы достигли цели создания продукта, и теперь у нас есть реальный продукт для тестирования. При тестировании мы можем также обнаружить проблемы, которые до этого никто не заметил. Несмотря на все старания, некоторые ошибки могут быть глубоко спрятанными, неявными, редкими, плавающими, зависящими от определенных условий. Тестирование в рамках Реализации направлено именно на их обнаружение. То, что проблемы ранее ускользнули, не обязательно связано с недостатком усердия. В любом сложном проекте проблемы не всегда очевидны сразу. Программное обеспечение часто зависит от точного совпадения многих факторов в нужное время. Продукты могут работать нормально в одних условиях и не работать в других. Функция может давать сбой при встрече с патологическими данными. Незначительные отличия в аппаратных платформах и операционных системах могут оказаться критическими и приводить к серьёзным последствиям. Прежде всего, проблемы могут возникать внезапно. Иногда ошибки не заложены в отдельных компонентах, а возникают из-за взаимодействия между ними. Проблемы могут появиться при взаимодействии хорошо протестированных компонентов или между компонентом и конкретными данными. Насколько бы ни был «грязным» тестовый стенд, реальный мир намного сложнее. Проблемы могут возникать, когда реальные пользователи применяют продукт неожиданным образом. Всё это позволяет определенным проблемам от нас ускользнуть. Даже если мы работали дисциплинированно и тщательно, некоторые проблемы могли остаться незамеченными и не исправленными. Это отчасти связано с тем, что создатели продукта мыслят как строители — смотрят на него изнутри, а не извне. Кроме того, тестирование в рамках дисциплины по своей природе направлено на быстрые и простые проверки, что зачастую исключает сложные и реалистичные сценарии. Поэтому, когда у нас есть реальный продукт и риск для бизнеса, имеет смысл тщательно искать глубинные проблемы, прежде чем подвергать им пользователей. Тестирование в рамке Реализации — это процесс опытного исследования и экспериментов с созданным продуктом в целом, проведение сложных, насыщенных и непростых тестов, призванных максимизировать шансы обнаружения всех важных и скрытых ошибок, которые могли быть пропущены ранее. Это включает глубокое исследование внутренностей системы, ее проверку на реалистичных сценариях, накопление обширного опыта работы с продуктом, его испытание и переосмысление наших представлений о нём. Наша цель — выявить проблемы, которые могут разочаровать пользователей или привести к затратам для пострадавших от продукта. Некоторые считают, что тестирование в рамке Реализации — это «ручное тестирование, которое проводится после всех автоматизированных проверок». Это крайне вредное заблуждение. Тестирование не делится чётко на ручное или автоматизированное, а термин «ручное» часто объединяет в себе множество разных понятий, что вводит в заблуждение. Давайте разберёмся подробнее. Тестирование в рамке Реализации может быть опытным (экспериментальным), когда тестировщик взаимодействует с продуктом практически так же, как и предполагаемый конечный пользователь. В то же время тестирование может быть инструментальным — с использованием вспомогательных средств или инструментов, которые изменяют естественное взаимодействие с продуктом, чтобы выявить проблемы, которые трудно заметить при обычном использовании. Тестирование в рамке Реализации может быть интерактивным, когда тестировщик непосредственно работает с продуктом в реальном времени, наблюдая его поведение. Другие виды активности могут быть непрямыми, например, когда тест или эксперимент запускается и работает без присутствия человека, а данные собираются и анализируются позже с помощью автоматизированных процессов или инструментов. Тестирование в рамках Реализации носит исследовательский характер — тестировщик самостоятельно принимает решения по ходу работы, реагирует на новую информацию и действует без жёстких ограничений. Тем не менее, в некоторых случаях тестирование может быть строго регламентированным и скриптованным, особенно если клиенту важна отчетность и структурированность определенных аспектов процесса тестирования. Таким образом, в рамках Реализации тестирование может быть опытным или инструментальным, интерактивным или автоматизированным, исследовательским или формализованным. Главное тут в том, что мы имеем дело с продуктом, который готов к развертыванию или находится на завершающей стадии разработки, и который подлежит всестороннему тестированию как полноценное, реальное решение. В рамках Реализации, помимо прочего, мы:
Реализация — это тестирование, расположенное ближе к концу жизненного цикла продукта. Мы подчеркиваем, что идея «сдвига влево» (shift left) — отличная практика, поскольку она поддерживает и ускоряет тестирование именно в рамках Реализации. Однако «сдвиг влево» не может заменить тестирование фрейма Реализации, потому что до этого этапа успехи «сдвига влево» и отсутствие проблем в продукте — лишь надежды и предположения, а не факты. В некоторых случаях тестирование, проведённое до этапа Реализации, может быть достаточным, и для ряда рисков может не понадобиться глубокое тестирование. В целом, особенно во фрейме Реализации, наша задача — сделать тестирование ответственным и достаточно глубоким — достаточно тщательным, чтобы находить скрытые и важные проблемы, но не чрезмерно глубоким. Можно сказать, что цель тут — по крайней мере, для Rapid Software Testing — сделать поверхностное тестирование глубже, а глубокое — дешевле. Кто выполняет тестирование во фрейме Реализации? В методологии Rapid Software Testing выделяют роль ответственного тестировщика — человека, который «несёт личную ответственность за тестирование конкретного объекта определённым способом в конкретном проекте». Когда в команде есть специализированные тестировщики, они, скорее всего, и отвечают за тестирование в рамках Реализации. Если таких людей нет, то существует риск, что тестирование в этом фрейме выполняется лишь частично и по совместительству поддерживающими тестировщиками — или вообще не выполняется. Всё, что было изложено в этой серии, сводится к набору эвристик для тестирования на стыке Agile-разработки и методологии Rapid Software Testing. Четыре фрейма – это своеобразная линза, через которую мы можем рассматривать и обсуждать тестирование. Множество споров ведется вокруг выводов, тогда как на самом деле они касаются исходных предпосылок. Когда мы говорим о тестировании и кажется, что мы не согласны друг с другом, полезно уточнить, о каком именно виде тестирования идёт речь — через какую часть линзы мы смотрим, или в каком фрейме находится тестирование. Однако эта линза не статична — она работает как зум-объектив. Об этом мы поговорим в следующем выпуске этой серии. |