Тестирование на основе моделей. Современные технологии тестирования В чем заключается тестирование модели

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

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

Каскадная модель (Линейная последовательная модель жизненного цикла ПО)

Каскадная модель (Waterfall Model) является одной из наиболее старых моделей, которую можно применять не только для разработки или тестирования ПО, но также практически для любого другого проекта. Его базовым принципом является последовательный порядок выполнения задач. Это значит, что мы можем переходить к следующему шагу разработки или тестирования только после того, как предыдущий был успешно завершен. Эта модель подходит для небольших проектов и применима только в том случае, если все требования точно определены. Главными достоинствами этой методологии являются экономическая эффективность, простота использования и управления документацией.

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

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

Узнайте больше о каскадной модели из предыдущей статьи .

V-Model (Модель верификации и валидации)

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

Схема данной модели показывает принцип разделения задач на две части. Те, которые относятся к дизайну и разработке, размещены слева. Задачи, относящиеся к тестированию ПО, размещены справа:

Основные этапы этой методологии могут изменяться, однако обычно они включают следующие:

  • Этап определения требований . Приемочное тестирование относится к этому этапу. Его основная задача состоит в оценке готовности системы к финальному использованию
  • Этап, на котором происходит высокоуровневое проектирование, или High-Level Design (HDL) . Этот этап относится к системному тестированию и включает оценку соблюдения требований к интегрированным системам
  • Фаза детального дизайна (Detailed Design) параллельна фазе интеграционного тестирования, во время которой происходит проверка взаимодействий между различными компонентами системы
  • После этапа написания кода начинается другой важный шаг — юнит-тестирование. Очень важно убедиться в том, что поведение отдельных частей и компонентов ПО корректно и соответствует требованиям

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

Инкрементная модель

Данная методология может быть описана, как мультикаскадная модель тестирования ПО. Рабочий процесс разделяется на некоторое количество циклов, каждый из которых также делится на модули. Каждая итерация добавляет определенный функционал к ПО. Инкремент состоит из трех циклов:

  1. дизайн и разработка
  2. тестирование
  3. реализация.

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

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

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

Спиральная модель

Спиральная модель это методология тестирования ПО, которая основана на инкрементном подходе и прототипировании. Она состоит из четырех этапов:

  1. Планирование
  2. Анализ рисков
  3. Разработка
  4. Оценка

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

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

Читайте подробнее o спиральной модели в предыдущем блог посте .

Agile

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

Узнайте больше об Agile (прим. — статья на английском языке) .

Экстремальное программирование (XP, Extreme Programming)

Экстремальное программирование является одним их примеров гибкой разработки ПО. Отличительной особенностью этой методологии является “парное программирование”, ситуация, когда один разработчик работает над кодом, в то время как его коллега постоянно проводит обзор написанного кода. Процесс тестирования ПО является довольно важным, поскольку начинается даже раньше, чем написана первая строка кода. Каждый модуль приложения должен иметь юнит-тест, чтобы большинство ошибок могло быть исправлено на стадии написания кода. Другим отличительным свойством является то, что тест определяет код, а не наоборот. Это значит, что определенная часть кода может быть признана завершенной только в том случае, если все тесты пройдены успешно. В противном случае, код отклоняется.

Главными достоинствами такой методологии являются постоянное тестирование и короткие релизы, что помогает обеспечить высокое качество кода.

Scrum

Scrum — Часть методологии Agile, итеративный инкрементный фреймворк, созданный для управления процессом разработки ПО. Согласно принципам Scrum, команда тестировщиков должна участвовать в следующих этапах:

  • Участие в Scrum планировании
  • Поддержка в юнит-тестировании
  • Тестирование пользовательских историй
  • Сотрудничество с заказчиком и владельцем продукта для определения критериев приемлемости
  • Предоставление автоматического тестировании

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

В то же время принципы Agile методологии в Scrum к появлению специфических особенностей:

  • Оценка усилий, необходимых для каждой пользовательской истории является обязательной
  • Тестировщик должен быть внимательным к требованиям, поскольку они могут постоянно изменяться
  • Риск регрессии возрастает вместе с частыми изменениями в коде
  • Одновременность планирования и выполнения тестов
  • Недопонимание между членами команды в случае если требования заказчика не до конца ясны

Узнайте больше о методологии Scrum из предыдущей статьи .

Заключение

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

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

18.09.2003 Александр Петренко, Елена Бритвина, Сергей Грошев, Александр Монахов, Ольга Петренко

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

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

Подходы к улучшению качества программ

«Борьба за качество» программ может вестись двумя путями. Первый путь «прост»: собрать команду хороших программистов с опытом участия в аналогичных проектах, дать им хорошо поставленную задачу, хорошие инструменты, создать хорошие условия работы. С большой вероятностью можно ожидать, что удастся разработать программную систему с хорошим качеством.

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

В простейшем варианте набор этапов жизненного цикла таков:

  • анализ требований;
  • проектирование (предварительное и детальное);
  • кодирование и отладка ("программирование");
  • тестирование;
  • эксплуатация и сопровождение.

Стандартизованная схема жизненного цикла с четкой регламентацией необходимых работ и с перечнем соответствующей документации легла в основу так называемой «водопадной» или каскадной модели. Водопадная модель подразумевает жесткое разбиение процесса разработки программного обеспечения на этапы, причем переход с одного этапа на другой осуществляется только после того, как будут полностью завершены работы на предыдущем этапе. Каждый этап завершается выпуском полного комплекта документации, достаточной для того, чтобы разработка могла быть продолжена другой командой. Водопадная модель стала доминирующей в стандартах процессов разработки Министерства обороны США. Многие волей или неволей, даже отклоняясь от этой модели, в целом соглашались с ее разумностью и полезностью.

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

В конце 80-х годов была предложена так называемая спиральная модель, был развит и проверен на практике метод итеративной и инкрементальной разработки (Iterative and Incremental Development, IID). В спиральной модели были учтены проблемы водопадной модели. Главный упор в спиральной модели делается на итеративности процесса. Описаны опыты использования IID с длиной итерации всего в полдня. Каждая итерация завершается выдачей новой версии программного обеспечения. На каждой версии уточняются (и, возможно, меняются) требования к целевой системе и принимаются меры к тому, чтобы удовлетворить и новые требования. В целом Rational Unified Process (RUP) также следует этой модели.

Позволило ли это решить проблему качества? Лишь в некоторой степени.

Проблема повышения качества программного обеспечения в целом и повышения качества тестирования привлекает все большее внимание; в университетах вводят специальные дисциплины по тестированию и обеспечению качества, готовят узких специалистов по тестированию и инженеров по обеспечению качества. Однако по-прежнему ошибки обходятся только в США от 20 до 60 млрд. долл. ежегодно. При этом примерно 60% убытков ложится на плечи конечных пользователей. Складывается ситуация, при которой потребители вынуждены покупать заведомо бракованный товар.

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

Каково же направление главного удара? Что предлагают «наилучшие практики»?

В 80-е и 90-е годы ответ на этот вопрос звучал примерно так. Наиболее дорогие ошибки совершаются на первых фазах жизненного цикла - это ошибки в определении требований, выборе архитектуры, высокоуровневом проектировании. Поэтому надо концентрироваться на поиске ошибок на всех фазах, включая самые ранние, не дожидаясь, пока они обнаружатся при тестировании уже готовой реализации. В целом тезис звучал так: «Сократить время между моментом?внесения? ошибки и моментом ее обнаружения». Тезис в целом хорош, однако не очень конструктивен, поскольку не дает прямых рекомендаций, как сокращать это время.

В последние годы в связи с появлением методов, которые принято обозначать эпитетом agile («шустрый», «проворный») предлагаются и внедряются новые конструктивные методы раннего обнаружения ошибок. Скажем, современные модели, такие как Microsoft Solutions Framework (MSF) и eXtreme Programming (XP), выделяют следующие рекомендации к разработке тестов:

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

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

Не будем останавливаться на справедливости этих положений и их эффективности. Как часто бывает, побочный эффект новшества оказался более значимым, чем собственно реализация этой идеи. В данном случае дискуссии вокруг «шустрых» методов привели к новому пониманию места тестирования в процессе разработки программного обеспечения. Оказалось, тестирование в широком понимании этого слова, т.е. разработка, пропуск тестов и анализ результатов, решают не только задачу поиска уже допущенных в программном коде ошибок. Серьезное отношение к тестированию позволяет предупреждать ошибки: стоит перед тем, как писать код, подумать о том, какие ошибки в нем можно было бы сделать, и написать тест, нацеленный на эти ошибки, как качество кода улучшается.

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

Итак, различные работы в процессе производства программ должны быть хорошо интегрированы с работами по тестированию. Соответственно, инструменты тестирования должны быть хорошо интегрированы со многими другими инструментами разработки. Из крупных производителей инструментов разработки программ, первыми это поняли компании Telelogic (набор инструментов для проектирования, моделирования, реализации и тестирования телекоммуникационного ПО, базирующийся на нотациях SDL/MSC/TTCN) и Rational Software (аналогичный набор, преимущественно базирующийся на нотации UML). Следующий шаг сделала компания IBM, начав интеграцию возможностей инструментов от Rational в среду разработки программ Eclipse.

Тезис XP - «Пиши тест перед реализацией» - хорош как лозунг, но в реальности столь же неконструктивен. Для крупных программных комплексов приходится разрабатывать тесты различного назначения: тесты модулей, интеграционные или компонентные тесты, системные тесты.

Три составляющие тестирования - экскурс в теорию

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

Проверка корректности всех модулей, к сожалению, не гарантирует корректности функционирования системы модулей. В литературе иногда рассматривается «классическая» модель неправильной организации тестирования системы модулей, часто называемая методом «большого скачка». Суть метода состоит в том, чтобы сначала оттестировать каждый модуль в отдельности, потом объединить их в систему и протестировать систему целиком. Для крупных систем это нереально. При таком подходе будет потрачено очень много времени на локализацию ошибок, а качество тестирования останется невысоким. Альтернатива «большому скачку» - интеграционное тестирование , когда система строится поэтапно, группы модулей добавляются постепенно.

Распространение компонентных технологий породило термин «компонентное тестирование» как частный случай интеграционного тестирования.

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

Инструменты тестирования - реальная практика

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

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

Обзор инструментов тестирования будем вести в обратном порядке - от системного тестирования к модульному.

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

В данном виде тестирования широко применяются инструменты записи-воспроизведения (record/playback); из наиболее известных продуктов можно назвать Rational Robot (компания IBM/Rational), WinRunner (Mercury Interactive), QARun (Compuware). Наряду с этим существуют инструменты для текстовых терминальных интерфейсов, например, QAHiperstation компании Compuware.

Для системного нагрузочного тестирования Web-приложений и других распределенных систем широко используется инструментарий LoadRunner от Mercury Interactive; он не нацелен на генерацию изощренных сценариев тестирования, зато дает богатый материал для анализа производительности, поиска узких мест, сказывающихся на производительности распределенной системы.

Примерная общая схема использования инструментов записи-воспроизведения такова:

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

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

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

Впрочем, возможности данного вида тестирования ограничены:

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

Следующий класс инструментов - инструменты тестирования компонентов . Примером является Test Architect (IBM/Rational). Такие инструменты помогают организовать тестирование приложений, построенных по одной из компонентных технологий (например, EJB). Предусматривается набор шаблонов для создания различных компонентов тестовой программы, в частности, тестов для модулей, сценариев, заглушек.

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

Последний из рассматриваемых здесь классов инструментов - инструменты тестирования модулей . Примером может служить Test RealTime (IBM/Rational), предназначенный для тестирования модулей на C++. Важной составляющей этого инструмента является механизм проверочных «утверждений» (assertion). При помощи утверждений можно сформулировать требования к входным и выходным данным функций/методов классов в форме логических условий, в аналогичной форме можно задавать инвариантные требования к данным объектов. Это существенный шаг вперед по сравнению с Test Architect. Аппарат утверждений позволяет систематическим образом представлять функциональные требования и на базе этих требований строить критерии тестового покрытия (правда, Test RealTime автоматизированной поддержки анализа покрытия не предоставляет).

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

Решение перечисленных проблем предлагает новое поколение инструментов, которые следуют подходу тестирования на основе модели (model based testing) или на основе спецификаций (specification based testing).

Чем могут помочь модели

В голове разработчика и тестировщика всегда присутствует та или иная «модель» устройства программы, а также «модель» ее желаемого поведения, исходя из которой, в частности, составляются списки проверяемых свойств и создаются соответствующие тестовые примеры. (Заметим, что это разные модели; первые часто называют архитектурными, а вторые - функциональными или поведенческими.) Они зачастую составляются на основе документов или обсуждений в неформальном виде.

Разработка моделей и спецификаций связана с «математизацией» программирования. Попытки использовать различные математические подходы для конструирования и даже генерации программ предпринимались с первых лет возникновения компьютеров. Относительный успех был достигнут в теории компиляторов, реляционных баз данных и в нескольких узкоспециальных областях; серьезных результатов в большинстве практических областей достичь не удалось. Многие стали относиться к формальным методам в программировании скептически.

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

Преимущества тестирования на основе моделей виделись в том, что:

  • тесты на основе спецификации функциональных требований более эффективны, так как они в большей степени нацелены на проверку функциональности, чем тесты, построенные только на знании реализации;
  • на основе формальных спецификаций можно создавать самопроверяющие (self-checking) тесты, так как из формальных спецификаций часто можно извлечь критерии проверки результатов целевой системы.

Однако не было ясности в отношении качества подобных тестов. Модели обычно проще реализации, поэтому можно было предположить, что тесты, хорошо «покрывающие» модель, слишком бедны для покрытия реальных систем. Требовались широкие эксперименты в реальных проектах.

Модель - некоторое отражение структуры и поведения системы. Модель может описываться в терминах состояния системы, входных воздействий на нее, конечных состояний, потоков данных и потоков управления, возвращаемых системой результатов и т.д. Для отражения разных аспектов системы применяются и различные наборы терминов. Формальная спецификация представляет собой законченное описание модели системы и требований к ее поведению в терминах того или иного формального метода. Для описания характеристик системы можно воспользоваться несколькими моделями в рамках нескольких формализмов. Обычно, чем более общей является нотация моделирования, тем больше трудностей возникает при автоматизации тестирования программы на основе модели/спецификации, описанной в этой нотации. Одни нотации и языки больше ориентированы на доступность и прозрачность описания, другие - на последующий анализ и трансляцию, в частности, трансляцию спецификации в тест. Предпринимались попытки разработки языка формальных спецификаций, удовлетворяющего требованиям промышленного использования (например, методология RAISE), однако широкого применения они не нашли.

Имеется несколько ставших уже классическими нотаций формальных спецификаций: VDM, Z, B, CCS, LOTOS и др. Некоторые из них, например, VDM, используются преимущественно для быстрого прототипирования. Язык B удобен для анализа, в частности для аналитической верификации моделей. Все эти языки активно используются в рамках университетских программ. В реальной практике для описания архитектурных моделей используется UML, а для построения поведенческих моделей - языки SDL/MSC, исполнимые диаграммы UML и близкие к ним нотации.

Перечисленные языки и нотации для поведенческих моделей, к сожалению, не обладают достаточной общностью. Они хорошо себя зарекомендовали в телекоммуникационных приложениях и практически бесполезны для описания функциональности программных систем «общего вида»: операционных систем, компиляторов, СУБД и т.д.

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

Инструменты тестирования на основе моделей

Test Real Time - один из первых представителей этой группы. Более широкие возможности предоставляет Jtest компании Parasoft. Интересен инструментарий компании Comformiq. Семейство инструментов разработки тестов на основе моделей предлагает Институт системного программирования РАН в кооперации с компанией ATS. Поскольку семейство UniTesK авторам знакомо существенно ближе, мы изложим общую схему подхода тестирования на основе моделей на примерах из UniTesK.

Рис. 1. Фазы процесса разработки спецификаций и тестов

Общая схема процесса разработки спецификаций и тестов состоит из четырех фаз (рис. 1).

Первая фаза относительно коротка, но в реальных проектах она важна. Именно здесь закладывается уровень абстрактности модели. Модель должна быть максимально простой: это позволит требовать исчерпывающего набора тестов. В то же время, модель должна быть содержательной, раскрывать специфику тестируемой реализации. Таким образом, задача первой фазы - найти компромисс между абстрактностью и детальностью.

Задача второй фазы - описание требований к поведению системы. Многие подходы (например, SDL) предлагают описывать исполнимые модели, которые можно рассматривать как прототипы будущей реализации. Задание требований в таком случае определяется формулой «реализация должна вести себя так же, как модель». Подход понятен, но, к сожалению, во многих реальных ситуациях он не работает. Допустим, в заголовке некоего сообщения, построенного моделью, указано одно время, а в аналогичном заголовке от реализации - несколько другое. Это ошибка или нет? Еще один пример. Модель системы управления памятью сгенерировала указатель на свободный участок памяти, а реальная система выдала другой указатель: модель и система работают в разных адресных пространствах. Ошибка ли это?

UniTesK - унифицированное решение

UniTesK предлагает использовать так называемые неявные спецификации или спецификации ограничений. Они задаются в виде пред- и постусловий процедур и инвариантных ограничений на типы данных. Этот механизм не позволяет описывать в модели алгоритмы вычисления ожидаемых значений функций, а только их свойства. Скажем, в случае системы управления памятью модель будет задана булевским выражением в постусловии типа «значение указателя принадлежит области свободной памяти». Простой пример постусловия для функции «корень квадратный» приведен на ; одна и та же спецификация представлена в трех разных нотациях: в стиле языков Cи, Java и C#. Использование спецификационных расширений обычных языков программирования вместо классических языков формальных спецификаций - шаг, на который идут почти все разработчики подобных инструментов. Их различает только выразительная мощность нотаций и возможности анализа и трансляции спецификаций.

Третья фаза - разработка тестового сценария. В простейшем случае сценарий можно написать вручную, но в данной группе инструментов - это плохой тон. Тест, т.е. последовательность вызовов операций целевой системы с соответствующими параметрами, можно сгенерировать, отталкиваясь от некоторого описания программы или структуры данных. Будем называть такое описание сценарием . Компания Conformiq предлагает описать конечный автомат. Различные состояния автомата соответствуют различным значениям переменных целевой системы, переходы - вызовам операций этой системы. Определить автомат - это значит для каждого состояния описать, в какое состояние мы перейдем из данного, если обратимся к любой наперед заданной операции с любыми наперед заданными параметрами. Если такое описание получить легко, больше ничего делать не понадобится: инструмент сгенерирует тест автоматически и представит результаты тестирования, например, в виде MSC-диаграмм. Но легко ли это, скажем, для программы с одной целочисленной переменной и двумя-тремя операциями? Скорее всего, да. Однако в общем случае сделать попросту невозможно.

В UniTesK для генерации тестовых последовательностей конечный автомат не описывается, а генерируется по мере исполнения теста. Все, что требуется от разработчика теста, - это задание способа вычисления состояния модели на основании состояния целевой системы и способа перебора применяемых в текущем состоянии тестовых воздействий. Эти вычисления записываются в тестовых сценариях. Очередное тестовое воздействие выбирается на основании спецификации сценария в зависимости от результатов предыдущих воздействий. Такой подход обладает двумя важными преимуществами. Во-первых, это позволяет строить сложные тестовые последовательности в чрезвычайно компактной и легкой для написания и понимания форме. Во-вторых, тесты приобретают высокую гибкость: они легко могут быть параметризованы в зависимости от текущих потребностей тестирования и даже могут автоматически подстраиваться под незначительные изменения модели. На рис. 3 приведен пример сценарного метода.

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

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

В реальных системах количество различимых состояний и количество допустимых в каждом из них тестовых воздействий очень велико, что приводит к комбинаторному «взрыву состояний». Для борьбы с этим эффектом разработан механизм факторизации модели: те состояния целевой системы, различие между которыми несущественно с точки зрения задач данного теста, объединяются в одно обобщенное состояние модели; аналогичным образом объединяются в группы и тестовые воздействия. Процесс факторизации предоставляет разработчику свободу творчества, но, вместе с тем, он поддержан строгими исследованиями, определяющими достаточные условия, при соблюдении которых гарантированы корректность результатов и существенное сокращение времени тестирования при сохранении достигаемого тестового покрытия.

Рис. 4. Архитектура тестовой программ

Создатели UniTesK, полагая, что не должно быть отдельной среды для разработки тестов, не только наделили его возможностью мимикрии под различные языки программирования, но обеспечили интеграцию составляющих его инструментов в популярные средства разработки программ. На рис. 5 представлен сеанс использования UniTesK в среде разработки Forte 4.0 компании Sun Microsystems.

Новое качество, которое обещают новые инструменты

Как отмечалось выше, создатели инструментов тестирования обычно сталкиваются со следующими проблемами:

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

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

Критерии тестового покрытия. Основной критерий - проверка всех утверждений, в частности, утверждений, определяющих постусловия процедур или методов. Он легко проверяется и легко связывается с функциональными требованиями к целевой системе. Так, инструменты UniTesK, инструменты для платформ Java и C# предоставляют четыре уровня вложенных критериев.

Повторное использование тестов. Уровень повторного использования существенно выше, чем у традиционных инструментов. Разработчик тестов пишет не тестовый скрипт, а критерии проверки утверждения и тестовый сценарий. И то, и другое лишено многих реализационных деталей, и поэтому их проще переиспользовать для новой версии целевой системы или для адаптации спецификаций и тестов для сходного проекта. Например, статистика UniTesK показывает, что уровень переиспользования для тестирования ядер разных операционных систем превышает 50%.

Автоматическая генерация тестов. Это главное достоинство новых инструментов; здесь они существенно опережают традиционные средства, поскольку используют не произвольные виды нотаций и методов моделирования и спецификации, а именно те, которые дают преимущества при автоматической генерации тестов. Так, утверждения позволяют сгенерировать тестовые «оракулы» - программы для автоматического анализа корректности результата; различные виды конечных автоматов или их аналоги позволяют сгенерировать тестовые последовательности. К тому же, поскольку модели обычно проще, чем реализации, для них удается провести более тщательный анализ, поэтому набор тестов становится более систематическим.

Рассмотренные инструменты опробованы на реальных, масштабных проектах. Конечно, каждый проект несет в себе некоторую специфику, возможно, препятствующую исчерпывающему тестированию. Однако опыт использования данных инструментов показывает, что обычно удается достичь хороших результатов, лучших, чем результаты, полученные в аналогичных проектах при помощи ручного тестирования. Пользователи UniTesK, обычно, за приемлемый уровень качества принимают 70-80% покрытия кода целевой системы; при этом должен быть удовлетворен, как минимум, критерий покрытия всех логических ветвей в постусловиях. Для некоторых сложных программ (в том числе, для блока оптимизации компилятора GCC) был достигнут уровень покрытия 90-95%.

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

Обозначения элементов общей структуры спецификации метода:

S - Сигнатура операции

A - Спецификация доступа

- Предусловие

B - Определение ветвей функциональности

> - Постусловие

Java:
Class SqrtSpecification { S Specification static double sqrt(double x) A reads x, epsilon { = 0; } post { > if(x == 0) { B branch «Zero argument»; > return sqrt == 0; > } else { B branch «Positive argument»; > return sqrt >= 0 && > Math.abs((sqrt*sqrt-x)/x) } } } }
Си:
S specification double SQRT(double x) A reads (double)x, epsilon { = 0.; } coverage ZP { if(x == 0) { B return(ZERO, «Zero argument»); } else { B return(POS, «Positive argument»); } } post { > if(coverage(ZP, ZERO)) { > return SQRT == 0.; > } else { > return SQRT >= 0. && > abs((SQRT*SQRT - x)/x) } } }
C#:
namespace Examples { specification class SqrtSpecification { S specification static double Sqrt(double x) A reads x, epsilon { = 0; } post { > if(x == 0) { B branch ZERO («Zero argument»); > return $this.Result == 0; > } else { B branch POS («Positive argument»); > return $this.Result >= 0 && > Math.Abs(($this.Result * $this.Result - x)/x) } > } > } } }

Традиционный подход к автоматическим тестам выглядит примерно так - тестописатель изучает тестируемую систему и после этого руками пишет каждый отдельный сценарий для проверки искомой системы. Кто-то может написать тут гордое слово "handcrafted", а я называю это словом "handjob". А все потому, что обычно этот подход к созданию и написанию тестов страдает от двух проблем:

  • "Парадокс пестицида", описанный Борисом Бейзером в 1990-м году. Заключается он в том, что тесты все менее и менее эффективны в отлове багов, так как баги, для обнаружения которых эти тесты написаны, уже найдены и починены. Если же этого не происходит, то возникают серьезные вопросы к написанному коду и к рабочим процессам
  • Тесты статичны и их сложно менять, в то время как тестируемая система имеет свойство постоянно эволюционировать, обрастать новым функционалом и менять поведение старого. И тесты нужно менять каждый раз, когда функционал изменяет внешний вид программы или ее поведение. И с ростом сложности обновления тестов оправдывать чудовищные издержки на поддержку тестов становиться все сложнее.

Model-Based Testing данные проблемы практически полностью игнорирует, поскольку тесты создаются автоматически из точной модели приложения. Это сильно упрощает как поддержку уже существующих, так и генерацию новых, крайне полезных и гибких тестов.

Что такое модель?

Модель - это описание тестируемой системы. Формальная спецификация вполне сойдет. Модель должна быть сильно проще описываемой системы и как-то помогать нам понимать и предсказывать поведение тестируемого продукта.

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

Если вкратце, то можно описать так: тестируемое ПО начинает работу в каком-то состоянии ("главная страничка открыта"), принимает какой-то пользовательский ввод ("посмотреть фоточки котяток") и, в зависимости от этого ввода, переходит в новое состояние ("альбом с фоточками котяток появился"). Мы используем модели все время чтобы понять поведение того куска софта с которым работаем ("Хм... если я нахожусь тут и делаю вот это , то я окажусь вон там "). Да в общем-то все тестирование можно рассматривать как перемещение тестировщика через различные состояния системы и проверку того, что эти перемещения происходят корректно (что значит "корректно" это отдельная тема, так что пока мы ее пропустим).

Что такое Model-Based Testing?

Это довольно немолодая идея использовать формально описанные модели для того, чтобы сделать тестирование ПО более дешевым и простым занятием. Само Model-Based Testing это такая "продвинутая" техника тестирования через "черный ящик". У нее есть ряд бонусов перед традиционными методами:

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

И самое важное - формально описанные модели в комбинации с зачатками теории графов помогает легко и непринужденно генерировать сотни тестов.

Зоркий поклонник Agile может воскликнуть "эй! у нас есть BDD и оно покрывает первые три пункта и еще это спецификация!". Я же отвечу "нихрена подобного - ваши примеры станут нормальной спецификацией только тогда, когда короля Шака Зулу можно будет считать спецификацией на все человечество".

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

Короткий ликбез по теории графов

Теория графов зародилась в 1736-м году в стареньком Прусском городе Кёнингсберге. Город стоял на двух берегах реки и попутно занимал еще и пару островов посреди этой самой реки. Жители этого города от безделья пытались придумать как посетить все семь мостов не проходя ни по одному дважды. Решали на практике, во время прогулок, и в теории, во время кухонных посиделок. Долгое время никто не мог доказать или опровергнуть возможность существования данного маршрута, пока не пришел зануда Эйлер и не испортил горожанам праздник.

Эйлер придумал изобразить каждый кусок суши как вершину графа, а мосты - ребрами графа.

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

С тех пор граф, в котором все вершины имеют четное количество ребер называется "Эйлеровым Графом". А полный обход этого графа носит гордое имя "Эйлерова пути".

И после этого жителям Кёнингсберга пришлось найти себе другое развлечение. Только один китайский математик Мэй-Ку Куан все морочил себе голову этими мостами. А беспокоил его следующий вопрос:

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

А это уже сильно похоже на проблему, с которой встречаются почтальоны. Допустим, каждая вершина это почтовый ящик, куда нужно вкинуть писем. И, допустим, наш постальон должен вкинуть писем в каждый ящик не совершая лишних движений.

Куан предложил считать повторное пересечение моста добавлением еще одного ребра графа. Добавление ребер должно привести к тому, что у всех вершин графа будет четное количество ребер. Эту процедуру принято называть "Эйлеризацией" графа. И после того как граф "Эйлеризован" мы можем построить Эйлеров путь по нему.

И в честь Куана эту задачку назвали "задачей китайского почтальона".

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

Тут мы введем еще один термин - орграф. Или ориентированный граф. Это такой граф, ребра которого можно пересекать только в указанном направлении. Направленные же ребра так же называются "дугами".

И если в случае Эйлерова Пути или Проблемы Китайского Почтальона мы оперировали дугами касающимися вершин, то тут приходится принимать во внимание еще и направление движения. И доля "Эйлеризации" такого графа нам требуется чтобы количество входящих в вершину дуг равнялось количеству исходящих. И считая каждую входящую дугу как "+1", а исходящую как "-1" мы можем вычислять "полярность" каждой вершины орграфа. Например вершина в двумя входящими и одной исходящей дугой имеет полярность "2 - 1 = 1".

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

Причем тут тестирование?

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

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

С другой стороны, исполнение всех возможных действий это хорошо, но даже самый недалекий тест-менеджер понимает, что это банальное "покрытие состояний" в терминах тестирования сырого кода. Но у множителей есть одно неприятное свойство - у них, как правило, очень много "следующих" состояний у каждой вершины. Что же нам делать, если мы хотим проверить все возможные комбинации действий? Решения задач вроде задачи Китайского Почтальона не подходят, поскольку они гарантируют только посещение каждой дуги, но никак не посещение всех возможных комбинаций дуг.

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

Решение предложил некий де Брюийн. Алгоритм выглядит примерно так:

  • Рисуем сбоку граф, где каждое ребро исходного графа является вершиной.
  • Там где у исходного графа дуга "1" входит в вершину, откуда выходит дуга "2" рисуем в свежеиспеченном графе дугу из вершины "1" в вершину "2".
  • Эйлеризуем полученный граф.
  • Рисуем Эйлеров путь на данном графе.

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

Про то, зачем сюда добавляют Цепи Маркова, и как обычно решается распараллеливание таких тестов я напишу позже. А пока подведем краткие итоги.

Итого

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

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

И, поскольку Теория Графов позволяет нам работать непосредственно с моделью:

  • Новые обходы можно автоматически генерировать при изменении модели
  • Наши тесты могут легко и непринужденно меняться в рамках одной и той же модели
  • Различные алгоритмы обхода могут удовлетворять различным потребностям тестирования
  • Полученные алгоритмы обхода легко можно переиспользовать в совершенно новой среде

Тестовая модель - это логическая структура, описывающая функциональность системы и/или поведения пользователя, по которой генерируются тест-кейсы. Построение тестовой модели начинается с построения структуры, а затем утвержденная структура наполняется тест-кейсами.

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

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

Управление тестовой моделью - непрерывный процесс на протяжении всего жизненного цикла продукта.

Покрытие тестовой модели

Для контроля покрытия всех требований можно использовать матрицы трассировки, которые определяют покрытие требований тестовыми сценариями (см. пример).
Перед тем как тест-кейсы будут описаны, структура тестовой модели должна быть утверждена с заказчиком.

Качество сценариев

Для управления качеством сценариев необходимо контролировать не только уровень описания тест-кейсов, но и их качество.

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

Возможные уровни описания тест-кейсов:

На 4-м уровне согласование с заказчиком может быть заменено на согласование .

Критерии качества описания тест-кейсов могут быть следующими:

  • Тест-кейсы необходимо писать по требованиям

Тестирование - это процесс проверки соответствия продукта предъявляемым к нему требованиям. Поэтому в части общего описания тест-кейса (в тест-трекинговых системах обычно употребляется термин «Summary») необходимо ссылаться на конкретное требование в связке с фрагментами текста требований. Таким образом, для всех участников проекта будет понятно, на основании чего написан данный тест-кейс.

  • Используйте детальные предусловия

Как сэкономить время на выполнении тест-кейсов?

Установите правила форматирования для всех тест-кейсов. Так тест-кейс будет удобен для понимания и чтения для любого участника проекта. Например, на проекте можно ввести следующие правила:

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

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

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

Процесс контроля качества сценариев можно вести с помощью Test Model Control – специально заготовленного шаблона.

Актуализация тестовой модели

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

Для актуализации можно вести «Матрицу требований» (Requirement Traceability Matrix): после каждого изменения в определенном требовании из тест-трекинговой системы делается выборка всех связанных с этим требованием тестовых сценариев, и проводится их обновление.

Средства управления тестовой моделью:

  • TestRail
  • TestLink
  • Jira+Zephyr
  • Microsoft Test Manager (MTM)
  • Excel

Тестирование – это процесс, позволяющий оценить качество производимого продукта. Качественный программный продукт должен отвечать предъявляемым к нему требованиям как функциональным, так и нефункциональным. ПС должна реализовывать все требуемые ВИ и не иметь дефектов – отличий реально существующих свойств или поведения от требуемых. Кроме того, ПС должна обладать свойствами надежности (должны отсутствовать зависания, аварийные отказы и пр.), безопасности, обеспечивать нужную производительность, быть удобной в эксплуатации, расширяемой и т. д. Таким образом, тестирование представляет собой процесс анализа ПС, направленный на выявление дефектов и на оценку свойств ПC.

Цели процесса тестирования

Целью тестирования является оценка качества программного продукта путем

  • Проверки взаимодействия компонентов;
  • Проверки правильности интеграции компонентов;
  • Проверки точности реализации всех требований и выявления дефектов.

Особенности процесса тестирования в RUP

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

Каждый найденный дефект регистрируется в базе данных проекта с описанием ситуации, в которой он найден. Аналитик определяет, действительно ли это дефект и не является ли он повтором обнаруженного ранее дефекта. Найденному дефекту присваивается приоритет , определяющий важность исправления. Конструктор, ответственный за разработку подсистемы, компоненты или класса, или другой исполнитель, назначенный руководителем, приступает к устранению дефекта. Порядок исправления дефектов регулируется их приоритетами. Тестировщик повторяет выполнение тестов и убеждается (или не убеждается) в устранении дефекта.

Разработчик тестов отвечает за планирование, разработку и реализацию тестов. Он создает план и модель тестирования, методики испытаний (см. ниже) и выполняет оценку результатов тестирования.

Тестировщик (испытатель) отвечает за выполнение системного тестирования. В его обязанности входит настройка и выполнение тестов, оценки выполнения теста, восстановление после ошибок, регистрация выявленных дефектов.

Артефакты

В процессе тестирования создаются следующие документы:

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

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

  • Контрольная задача – набор тестовых данных, условий выполнения тестов и ожидаемых результатов.
  • Методика испытаний – документ, содержащий указания по настройке и выполнению контрольных задач, а также по оценке получаемых результатов.
  • Сценарий тестирования – это упрощенное описание теста, включая исходные данные, условия и последовательности выполнения действий и ожидаемые результаты.
  • Тестовый скрипт является программой, выполняемой при автоматическом тестировании с помощью инструментальных средств тестирования.
  • Описание взаимодействия тестов представляет собой диаграмму последовательностей или коопераций, отражающую упорядоченный во времени поток сообщений между компонентами тестов и объектом тестирования.

Результаты тестирования и данные, полученные в процессе выполнения тестов.

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

Дефекты – это описания обнаруженных при проведении тестирования фактов несоответствия системы предъявляемым требованиям. Они представляют собой вид запросов на внесение изменений.

Работы по тестированию выполняются в каждой итерации во всех фазах, но цели и задачи в разных фазах проекта существенно различные.

Фаза вхождения в проект. В этой фазе выполняется подготовка к тестированию. Она включает:

  • Создание плана тестирования, содержащего требования к тестам и стратегии тестирования. Может создаваться единый план для всех видов тестирования (функциональное, нагрузочное и т. д.) или отдельные планы для каждого вида.
  • Анализ объема тестирования.
  • Формулирование критериев качества и завершения тестирования.
  • Установку и подготовки к работе инструментальных средств тестирования.
  • Формулирование требований к проекту разработки ПС, определяемых потребностями тестирования.

Фаза развития. В итерациях этой фазы начинается построение модели тестирования и связанных с ней артефактов. Поскольку в этой фазе уже присутствует модель ВИ можно начинать проектировать сценарии тестирования. В то же время нецелесообразно выполнение тестов, поскольку обычно в этой фазе еще не существует завершенных фрагментов ПС. Выполняются следующие деятельности:

  • Разработка сценариев тестирования.
  • Создание заготовок тестовых скриптов.
  • Разработка контрольных задач.
  • Разработка методики испытаний.
  • Разработка модели рабочей нагрузки.

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

  • Создание плана тестирования для каждой итерации.
  • Уточнение и дополнение модели тестирования.
  • Выполнение тестов.
  • Описание обнаруженных дефектов.
  • Описание результатов тестирования.
  • Оценка результатов тестирования.

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

Фаза развертывания. В итерациях этой фазы выполняется тестирование всей ПС как программного продукта. Выполняемые деятельности аналогичны деятельностям предыдущей фазы. Выявление дефектов определяет необходимость внесения изменений и повторного тестирования. Итерационный процесс повторяется до тех пор, пока не будут выполнены критерии завершения тестирования.

Оценка результатов тестирования производится на основе метрик тестирования, позволяющих определить качество тестируемой ПС и самого процесса тестирования.

Инструментальная поддержка

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

2024 psiholog112.ru. Интернет. Безопасность. Полезные советы. Программы. Система.