Тестовая модель. Современные технологии тестирования. Пересмотреть позитивные проверки

Nokia 31.03.2019
Nokia

ER-диаграммы

Логическая модель

Общим способом представления логической модели БД является построение ER-диаграмм (Entity-Relationship - сущность-связь). В этой модели сущность определяется как дискретный объект, для которого сохраняются элементы данных, а связь описывает отношение между двумя объектами.

В примере менеджера турфирмы имеются 5 основных объектов:

Туристы

Путевки

Отношения между этими объектами могут быть определены простыми терминами:

Каждый турист может купить одну или несколько (много) путевок.

Каждой путевке соответствует ее оплата (оплат может быть и несколько, если путевка, например, продана в кредит).

Каждый тур может иметь несколько сезонов.

Путевка продается на один сезон одного тура.

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

Рисунок 3.2. ER-диаграмма для приложения БД менеджера турфирмы

Далее модель развивается путем определения атрибутов для каждого объекта. Атрибуты объекта - это элементы данных, относящиеся к определенному объекту, которые должны сохраняться. Анализируем составленный словарь данных, выделяем в нем объекты и их атрибуты, расширяем словарь при необходимости. Атрибуты для каждого объекта в рассматриваемом примере представлены в таблице 2.

Таблица 3.2. Объекты и атрибуты БД

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

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



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

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

Для проектируемой БД расширим атрибуты объектов кодовыми полями в качестве первичных ключей и используем эти коды в отношениях БД для ссылки на объекты БД следующим образом (табл. 3).

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

Таблица 3.3. Объекты и атрибуты БД с расширенными кодовыми полями

ER -диаграммы

Общим способом представления логической модели БД является построение ER-диаграмм (Entity-Relationship - сущность-связь). В этой модели сущность определяется как дискретный объект, для которого сохраняются элементы данных, а связь описывает отношение между двумя объектами.

В примере менеджера турфирмы имеются 5 основных объектов:

Туристы

Путевки

Отношения между этими объектами могут быть определены простыми терминами:

Каждый турист может купить одну или несколько (много) путевок.

Каждой путевке соответствует ее оплата (оплат может быть и несколько, если путевка, например, продана в кредит).

Каждый тур может иметь несколько сезонов.

Путевка продается на один сезон одного тура.

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

Рис. 2. ER-диаграмма для приложения БД менеджера турфирмы

Объекты, атрибуты и ключи

Далее модель развивается путем определения атрибутов для каждого объекта. Атрибуты объекта - это элементы данных, относящиеся к определенному объекту, которые должны сохраняться. Анализируем составленный словарь данных, выделяем в нем объекты и их атрибуты, расширяем словарь при необходимости. Атрибуты для каждого объекта в рассматриваемом примере представлены в таблице 2.

Таблица 2. Объекты и атрибуты БД

Объект

Туристы

Путевки

Туры

Сезоны

Оплаты

Название

Дата начала

Дата оплаты

Дата конца

Отчество

Информация

Атрибуты

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

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

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

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

Для проектируемой БД расширим атрибуты объектов кодовыми полями в качестве первичных ключей и используем эти коды в отношениях БД для ссылки на объекты БД следующим образом (табл. 3).

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

Таблица 3. Объекты и атрибуты БД с расширенными кодовыми полями

Объект

Туристы

Путевки

Туры

Сезоны

Оплаты

Атрибуты

Код туриста

Код путевки

Код сезона

Код оплаты

Код туриста

Название

Дата начала

Дата оплаты

Код сезона

Дата конца

Отчество

Информация

Код путевки

Нормализация

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

Процесс нормализации состоит в пошаговом построении БД в нормальной форме (НФ).

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

2. Вторая нормальная форма (2НФ) создается тогда, когда удалены все частичные зависимости из отношений БД. Если в отношениях не имеется никаких составных ключей, то этот уровень нормализации легко достигается.

3. Третья нормальная форма (3НФ) БД требует удаления всех транзитивных зависимостей.

4. Четвертая нормальная форма (4НФ) создается при удалении всех многозначных зависимостей.

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

Обратите внимание, что они существуют только относительно различных видов зависимостей атрибутов БД. Есть зависимости - нужно стоить НФ БД, нет зависимостей - БД и так находится в НФ. Но последний вариант практически не встречается в реальных приложениях.

Итак, какие же транзитивные и многозначные зависимости присутствуют в нашем примере БД менеджера турфирмы?

Давайте проанализируем отношение «Туристы». Рассмотрим зависимости между атрибутами «Код туриста», «Фамилия», «Имя», «Отчество» и «Паспорт» (рис. 3). Каждый турист, представленный в отношении сочетанием «Фамилия- Имя-Отчество», имеет на время поездки только один паспорт, при этом полные тезки должны иметь разные номера паспортов. Поэтому атрибуты «Фамилия- Имя-Отчество» и «Паспорт» образуют в отношении туристы составной ключ.

Рис. 3. Пример транзитивной зависимости

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

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

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

В этом разделе мы рассмотрим самые базовые понятия и принципы, которые используются в процессе тестирования. Мы узнаем, что же, собственно, собой представляет тестирование, зачем оно нужно и кто им занимается. Рассмотрим цели, принципы и основные этапы тестирования. Почувствуем, каким должен быть психологический настрой настоящего тестировщика и развенчаем напоследок несколько мифов о тестировании. Уверены, Вам будет интересно.
Начнем с того, что же такое «тестирование». Для начала, давайте абстрагируемся от сухих академических определений и посмотрим на это понятие с точки зрения повседневного использования.
Когда мы что-то тестируем, то задаем себе простой вопрос: «работает ли это так, как мы ожидаем?» или, другими словами: соответствует ли реальное поведение объекта тестирования нашим ожиданиям? Если ответ положительный – замечательно, если нет, – мы обмануты в своих ожиданиях, а значит что-то нужно исправлять.
Тестирование необходимо потому, что все мы совершаем ошибки. Некоторые из них могут быть незначительными, в то время как другие – иметь самые разрушительные последствия. Все, что производится человеком, может содержать ошибки (так уж мы, люди, устроены). Именно поэтому любой продукт нуждается в проверке – тестировании, прежде чем его можно будет эффективно и безопасно использовать.
То же самое справедливо и для программного обеспечения (англ. Software).
Программное обеспечение (Software) – компьютерные программы, функции, а также сопровождающая их документация и данные, имеющие отношение к эксплуатации компьютерной системы.
Компьютерные технологии все глубже проникают в нашу повседневную жизнь. Программное обеспечение управляет работой множества окружающих нас вещей – от мобильных телефонов и компьютеров до стиральных машин и кредитных карт. В любом случае, все мы сталкивались с теми или иными ошибками в программах: текстовый редактор, намертво зависший при работе над дипломным проектом, банкомат, «съевший» карточку или просто сайт, который никак не загрузится – все это отнюдь не облегчает нам жизнь.
Однако не все ошибки одинаково опасны – для разных программных систем уровни риска могут отличаться.
Риск (risk):
– фактор, который может привести к негативным последствиям в будущем; как правило, выражается через вероятность наступления таких последствий и их влияние на систему.
– то, что еще не произошло, и может вообще не произойти; потенциальная проблема.
Кроме того, уровень риска будет зависеть от вероятности наступления негативных последствий.
К примеру, одна и та же незначительная ошибка, скажем опечатка, может иметь совершенно разные уровни риска для разных программ:
– опечатка в описании интересов на персональной страничке в социальной сети вряд ли будет иметь существенные последствия, разве что вызовет улыбку у Ваших друзей;
– такая же простая опечатка, допущенная в описании деятельности крупной компании, размещенном на ее сайте, уже опасна, так как косвенно свидетельствует о непрофессионализме ее сотрудников;
– опечатка в коде программы, которая подсчитывает уровни облучения при работе рентгеновского аппарата (например, 100 вместо 10) может иметь самые печальные последствия – вред, нанесенный здоровью и безопасности людей, выльется в потерю доверия к компании и судебные иски со многими нулями.

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) } > } > } } }

  • Тестирование веб-сервисов
  • Самый лучший способ оценить, хорошо ли мы протестировали продукт – проанализировать пропущенные дефекты. Те, с которыми столкнулись наши пользователи, внедренцы, бизнес. По ним можно многое оценить: что мы проверили недостаточно тщательно, каким областям продукта стоит уделить больше внимания, какой вообще процент пропусков и какова динамика его изменений. С этой метрикой (пожалуй, самой распространённой в тестировании) всё хорошо, но… Когда мы выпустили продукт, и узнали о пропущенных ошибках, может быть уже слишком поздно: на “хабре” появилась про нас гневная статья, конкуренты стремительно распространяют критику, клиенты потеряли к нам доверие, руководство недовольно.

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

    Зачем оценивать?

    Любые метрики оценки – трата времени. В это время можно тестировать, заводить баги, готовить автотесты. Какую такую магическую пользу мы получаем благодаря метрикам тестового покрытия, чтобы пожертвовать временем на тестирование?
    1. Поиск своих слабых зон. Естественно, это нам нужно? не чтобы просто погоревать, а чтобы знать, где требуются улучшения. Какие функциональные области не покрыты тестами? Что мы не проверили? Где наибольшие риски пропуска ошибок?
    2. Редко по результатам оценки покрытия мы получаем 100%. Что улучшать? Куда идти? Какой сейчас процент? Как мы его повысим какой-либо задачей? Как быстро мы дойдём до 100? Все эти вопросы приносят прозрачности и понятности нашему процессу , а ответы на них даёт оценка покрытия.
    3. Фокус внимания. Допустим, в нашем продукте около 50 различных функциональных зон. Выходит новая версия, и мы начинаем тестировать 1-ю из них, и находим там опечатки, и съехавшие на пару пикселей кнопки, и прочую мелочь… И вот время на тестирование завершено, и эта функциональность проверена детально… А остальные 50? Оценка покрытия позволяет нам приоритезировать задачи исходя из текущих реалий и сроков.

    Как оценивать?

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

    Оцениваем покрытие требований тестами

    Допустим, у вас в команде есть аналитики, и они не зря тратят своё рабочее время. По результатам их работы созданы требования в RMS (Requirements Management System) – HP QC, MS TFS, IBM Doors, Jira (с доп. плагинами) и т.д. В эту систему они вносят требования, соответствующие требованиям к требованиям (простите за тавтологию). Эти требования атомарны, трассируемы, конкретны… В общем, идеальные условия для тестирования. Что мы можем сделать в таком случае? При использовании скриптового подхода – связывать требования и тесты. Ведём в той же системе тесты, делаем связку требование-тест, и в любой момент можем посмотреть отчёт, по каким требованиям тесты есть, по каким – нет, когда эти тесты были пройдены, и с каким результатом.
    Получаем карту покрытия, все непокрытые требования покрываем, все счастливы и довольны, ошибок не пропускаем…

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

    Проблема: требования не атомарны.

    Аналитики тоже иногда грешат винегретом в голове, и обычно это чревато проблемами со всем проектом. Например, вы разрабатываете текстовый редактор, и у вас могут быть в системе (в числе прочих) заведены два требования: «должно поддерживаться html-форматирование» и «при открытии файла неподдерживаемого формата, должно появляться всплывающее окно с вопросом». Сколько тестов требуется для базовой проверки 1-го требования? А для 2-го? Разница в ответах, скорее всего, примерно в сто раз!!! Мы не можем сказать, что при наличии хотя бы 1-го теста по 1-му требованию, этого достаточно – а вот про 2-е, скорее всего, вполне.

    Таким образом, наличие теста на требование нам вообще ничего не гарантирует! Что значит в таком случае наша статистика покрытия? Примерно ничего! Придётся решать!

    1. Автоматический расчёт покрытия требований тестами в таком случае можно убрать – он смысловой нагрузки всё равно не несёт.
    2. По каждому требованию, начиная с наиболее приоритетных, готовим тесты. При подготовке анализируем, какие тесты потребуются этому требованию, сколько будет достаточно? Проводим полноценный тест-анализ, а не отмахиваемся «один тест есть, ну и ладно».
    3. В зависимости от используемой системы, делаем экспорт/выгрузку тестов по требованию и… проводим тестирование этих тестов! Достаточно ли их? В идеале, конечно, такое тестирование нужно проводить с аналитиком и разработчиком этой функциональности. Распечатайте тесты, заприте коллег в переговорке, и не отпускайте, пока они не скажут «да, этих тестов достаточно» (такое бывает только при письменном согласовании, когда эти слова говорятся для отписки, даже без анализа тестов. При устном обсуждении ваши коллеги выльют ушат критики, пропущенных тестов, неправильно понятых требований и т.д. – это не всегда приятно, но для тестирования очень полезно!)
    4. После доработки тестов по требованию и согласования их полноты, в системе этому требованию можно проставить статус «покрыто тестами». Эта информация будет значить значительно больше, чем «тут есть хотя бы 1 тест».

    Конечно, такой процесс согласования требует немало ресурсов и времени, особенно поначалу, до наработки практики. Поэтому проводите по нему только высокоприоритетные требования, и новые доработки. Со временем и остальные требования подтянете, и все будут счастливы! Но… а если требований нет вообще?

    Проблема: требований нет вообще.

    Они на проекте отсутствуют, обсуждаются устно, каждый делает, что хочет/может и как он понимает. Тестируем так же. Как результат, получаем огромное количество проблем не только в тестировании и разработке, но и изначально некорректной реализации фич – хотели совсем другого! Здесь я могу посоветовать вариант «определите и задокументируйте требования сами», и даже пару раз в своей практике использовала эту стратегию, но в 99% случаев таких ресурсов в команде тестирования нет – так что пойдём значительно менее ресурсоёмким путём:
    1. Создаём фичелист (feature list). Сами! В виде google-таблички, в формате PBI в TFS – выбирайте любой, лишь бы не текстовый формат. Нам ещё статусы собирать надо будет! В этот список вносим все функциональные области продукта, и постарайтесь выбрать один общий уровень декомпозиции (вы можете выписать объекты ПО, или пользовательские сценарии, или модули, или веб-страницы, или методы API, или экранные формы…) – только не всё это сразу! ОДИН формат декомпозиции, который вам проще и нагляднее всего позволит не пропустить важное.
    2. Согласовываем ПОЛНОТУ этого списка с аналитиками, разработчиками, бизнесом, внутри своей команды… Постарайтесь сделать всё, чтобы не потерять важные части продукта! Насколько глубоко проводить анализ – решать вам. В моей практике всего несколько раз были продукты, на которые мы создали более 100 страниц в таблице, и это были продукты-гиганты. Чаще всего, 30-50 строк – достижимый результат для последующей тщательной обработки. В небольшой команде без выделенных тест-аналитиков большее число элементов фичелиста будет слишком сложным в поддержке.
    3. После этого, идём по приоритетам, и обрабатываем каждую строку фичелиста как в описанном выше разделе с требованиями. Пишем тесты, обсуждаем, согласовываем достаточность. Помечаем статусы, по какой фиче тестов хватает. Получаем и статус, и прогресс, и расширение тестов за счёт общения с командой. Все счастливы!

    Но… Что делать, если требования ведутся, но не в трассируемом формате?

    Проблема: требования не трассируемы.

    На проекте есть огромное количество документации, аналитики печатают со скоростью 400 знаков в минуту, у вас есть спецификации, ТЗ, инструкции, справки (чаще всего это происходит по просьбе заказчика), и всё это выступает в роли требований, и на проекте уже все давно запутались, где какую информацию искать?
    Повторяем предыдущий раздел, помогая всей команде навести порядок!
    1. Создаём фичелист (см. выше), но без детального описания требований.
    2. По каждой фиче собираем воедино ссылки на ТЗ, спецификации, инструкции, и прочие документы.
    3. Идём по приоритетам, готовим тесты, согласовываем их полноту. Всё то же самое, только благодаря объединению всех документов в одну табличку повышаем простоту доступа к ним, прозрачные статусы и согласованность тестов. В итоге, у нас всё супер, и все счастливы!

    Но… Ненадолго… Кажется, за прошлую неделю аналитики по обращениям заказчиков обновили 4 разные спецификации!!!

    Проблема: требования всё время меняются.

    Конечно, хорошо бы тестировать некую фиксированную систему, но наши продукты обычно живые. Что-то попросил заказчик, что-то изменилось во внешнем к нашему продукту законодательстве, а где-то аналитики нашли ошибку анализа позапрошлого года… Требования живут своей жизнью! Что же делать?
    1. Допустим, у вас уже собраны ссылки на ТЗ и спецификации в виде фичелиста-таблицы, PBI, требований, заметок в Wiki и т.д. Допустим, у вас уже есть тесты на эти требования. И вот, требование меняется! Это может означать изменение в RMS, или задачу в TMS (Task Management System), или письмо в почте. В любом случае, это ведёт к одному и тому же следствию: ваши тесты неактуальны! Или могут быть неактуальны. А значит, требуют обновления (покрытие тестами старой версии продукта как-то не очень считается, да?)
    2. В фичелисте, в RMS, в TMS (Test Management System – testrails, sitechco, etc) тесты должны быть обязательно и незамедлительно помечены как неактуальные! В HP QC или MS TFS это можно делать автоматически при обновлении требований, а в google-табличке или wiki придётся проставлять ручками. Но вы должны видеть сразу: тесты неактуальны! А значит, нас ждёт полный повторный путь: обновить, провести заново тест-анализ, переписать тесты, согласовать изменения, и только после этого пометить фичу/требование снова как «покрыто тестами».

    В этом случае мы получаем все бенефиты оценки тестового покрытия, да ещё и в динамике! Все счастливы!!! Но…
    Но вы так много внимания уделяли работе с требованиями, что теперь вам не хватает времени либо на тестирование, либо на документирование тестов. На мой взгляд (и тут есть место религиозному спору!) требования важнее тестов, и уж лучше так! Хотя бы они в порядке, и вся команда в курсе, и разработчики делают именно то, что нужно. НО НА ДОКУМЕНТИРОВАНИЕ ТЕСТОВ ВРЕМЕНИ НЕ ОСТАЁТСЯ!

    Проблема: не хватает времени документировать тесты.

    На самом деле, источником этой проблемы может быть не только нехватка времени, но и ваш вполне осознанный выбор их не документировать (не любим, избегаем эффекта пестицида, слишком часто меняется продукт и т.д.). Но как оценивать покрытие тестами в таком случае?
    1. Вам всё равно нужны требования, как полноценные требования или как фиче-лист, поэтому какой-то из вышеописанных разделов, в зависимости от работы аналитиков на проекте, будет всё равно необходим. Получили требования / фичелист?
    2. Описываем и устно согласовываем вкратце стратегию тестирования, без документирования конкретных тестов! Эта стратегия может быть указана в столбце таблицы, на странице вики или в требовании в RMS, и она должна быть опять же согласована. В рамках этой стратегии проверки будут проводиться по-разному, но вы будете знать: когда это последний раз тестировалось и по какой стратегии? А это уже, согласитесь, тоже неплохо! И все будут счастливы.

    Но… Какое ещё «но»? Какое???

    Говорите, все обойдём, и да пребудут с нами качественные продукты!



    Рекомендуем почитать

    Наверх