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

Тестирование, основанное на ошибках

Цель тестирования,
основанного на ошибках, — проектирование
тестов, ориентированных на обнаружение
предполагаемых ошибок [46]. Разработчик
выдвигает гипотезу о предполагаемых
ошибках. Для проверки его предположений
разрабатываются тестовые варианты.

В качестве примера
рассмотрим булево выражение

if
(X
and
not Y
or
Z).

Инженер по
тестированию строит гипотезу о
предполагаемых ошибках выражения:

  • операция
    not
    сдвинулась влево от нужного места (она
    должна применяться к Z);

  • вместо
    and
    должно быть or;

  • вокруг
    not
    Y
    or
    Z
    должны быть круглые скобки.

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

Обсудим
первую предполагаемую ошибку. Значения
(X
=
false,
Y
= false,
Z
= false)
устанавливают указанное выражение в
false.
Если вместо not
Y
должно быть not
Z,
то
выражение принимает неправильное
значение, которое приводит к неправильному
ветвлению. Аналогичные рассуждения
применяются к генерации тестов по двум
другим ошибкам.

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

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

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

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

Тестирование, основанное на сценариях

Тестирование,
основанное на ошибках, оставляет в
стороне два важных типа ошибок:

  • некорректные
    спецификации;

  • взаимодействия
    между подсистемами.

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

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

Тестирование,
основанное на сценариях, ориентировано
на действия пользователя, а не на действия
программной системы [47]. Это означает
фиксацию задач, которые выполняет
пользователь, а затем применение их в
качестве тестовых вариантов. Задачи
пользователя фиксируются с помощью
элементов Use
Case.

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

Рассмотрим,
например, проектирование тестов,
основанных на сценариях, для текстового
редактора.

Рабочие
сценарии опишем в
виде
спецификаций элементов Use
Case.

Элемент
Use
Case:
Исправлять черновик.

Предпосылки:
обычно
печатают черновик, читают его и
обнаруживают ошибки, которые не видны
на экране. Данный элемент Use
Case
описывает события, которые при этом
происходят.

1. Печатать весь
документ.

2. Прочитать
документ, изменить определенные страницы.

3. После внесения
изменения страница перепечатывается.

4. Иногда
перепечатываются несколько страниц.

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

  • метод для печати
    отдельной страницы;

  • метод для печати
    диапазона страниц.

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

Элемент
Use
Case:
Печатать новую копию.

Предпосылки:
кто-то
просит пользователя напечатать копию
документа.

1. Открыть документ.

2. Напечатать
документ.

3. Закрыть документ.

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

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

Элемент
Use
Case:
Печатать новую копию.

  1. Открыть документ.

  2. Выбрать в меню
    пункт Печать.

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

  4. Нажать кнопку
    Печать.

  5. Закрыть документ.

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

Разработчик может
опустить эту зависимость в тестовом
варианте, но, вероятно, проблема
обнаружится в ходе тестирования. И тогда
разработчик будет выкрикивать: «Я
предполагал, я предполагал это учесть!!!».

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Орлов С.А. Технология разработки программного обеспечения — файл n1.doc

приобрести
Орлов С.А. Технология разработки программного обеспечения
скачать (1886.8 kb.)
Доступные файлы (1):

n1.doc

Необходимость и важность тестирования ПО трудно переоценить. Вместе с тем следует отметить, что тестирование является сложной и трудоемкой деятельностью. Об этом свидетельствует содержание глав 6, 7 и 8 глав, в которых описывались классические основы тестирования, разработанные в расчете (в основном) на процедурное ПО. В этой главе рассматриваются вопросы объектно-ориентированного тестирования [17], [18], [42], [50], [51]. Существует мнение, что объектно-ориентированное тестирование мало чем отличается от процедурно-ориентированного тестирования. Конечно, многие понятия, подходы и способы тестирования у них общие, но в целом это мнение ошибочно. Напротив, особенности объектно-ориентированных систем должны вносить и вносят существенные изменения как в последовательность этапов, так и в содержание этапов тестирования. Сгруппируем эти изменения по трем направлениям:

  • расширение области применения тестирования;
  • изменение методики тестирования;
  • учет особенностей объектно-ориентированного ПО при проектировании тестовых вариантов.

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

Расширение области применения объектно-ориентированного тестирования

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

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

Критерии тестирования моделей: правильность, полнота, согласованность [18], [51].

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

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

Для оценки согласованности нужно исследовать каждый класс и его взаимодействия с другими классами. Для упрощения такого исследования удобно использовать модель Класс— Обязанность— Сотрудничество CRC (Class— Responsibility — Collaboration). Основной элемент этой модели — CRC-карта [9], [76]. Кстати, CRC-карты — любимый инструмент проектирования в ХР-процессах.

По сути, CRC-карта — это расчерченная карточка размером 6 на 10 сантиметров. Она помогает установить задачи класса и выявить его окружение (классы-собеседники). Для каждого класса создается отдельная карта.

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

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

Для оценки модели (диаграммы) классов на основе CRC-карт рекомендуются следующие шаги [50].

  1. Выполняется перекрестный просмотр CRC-карты и диаграммы сотрудничества (последовательности) объектов. Цель — проверить наличие сотрудников, согласованность информации в обеих моделях.
  2. Исследуются обязанности CRC-карты. Цель — определить, предусмотрена ли в карте сотрудника обязанность, которая делегируется ему из данной карты. Например, в табл. 16.1 показана CRC-карта Банкомат. Для этой карты выясняем, выполняется ли обязанность Читать карту клиента, которая требует использования сотрудника Карта клиента. Это означает, что класс Карта клиента должен иметь операцию, которая позволяет ему быть прочитанным.

Таблица 16.1. CRC-карта Банкомат

Имя класса: Банкомат

Обязанности:

Сотрудники:
Читать карту клиента

Идентификация клиента

Проверка счета

Выдача денег

Выдача квитанции

Захват карты

Карта клиента

База данных клиентов

База данных счетов

Блок денег

Блок квитанций

Блок карт

  1. Организуется проход по каждому соединению CRC-карты. Проверяется корректность запросов, выполняемых через соединения. Такая проверка гарантирует, что каждый сотрудник, предоставляющий услугу, получает обоснованный запрос. Например, если произошла ошибка и класс База данных клиентов получает от класса Банкомат запрос на Состояние счета, он не сможет его выполнить — ведь База данных клиентов не знает состояния их счетов.
  2. Определяется, требуются ли другие классы, или правильно ли распределены обязанности по классам. Для этого используют проходы по соединениям, исследованные на шаге 3.
  3. Определяется, нужно ли объединять часто запрашиваемые обязанности. Например, в любой ситуации используют пару обязанностей — Читать карту клиента и Идентификация клиента. Их можно объединить в новую обязанность Проверка клиента, которая подразумевает как чтение его карты, так и идентификацию клиента.
  4. Шаги 1-5 применяются итеративно, к каждому классу и на каждом шаге эволюции объектно-ориентированной модели.

Изменение методики при объектно-ориентированном тестировании

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

Особенности тестирования объектно-ориентированных «модулей»

При рассмотрении объектно-ориентированного ПО меняется понятие модуля. Наименьшим тестируемым элементом теперь является класс (объект). Класс содержит несколько операций и свойств. Поэтому сильно изменяется содержание тестирования модулей.

В данном случае нельзя тестировать отдельную операцию изолированно, как это принято в стандартном подходе к тестированию модулей. Любую операцию приходится рассматривать как часть класса.

Например, представим иерархию классов, в которой операция ОР() определена для суперкласса и наследуется несколькими подклассами. Каждый подкласс использует операцию ОР(), но она применяется в контексте его приватных свойств и операций. Этот контекст меняется, поэтому операцию ОР() надо тестировать в контексте каждого подкласса. Таким образом, изолированное тестирование операции ОР(), являющееся традиционным подходом в тестировании модулей, не имеет смысла в объектно-ориентированной среде.

Выводы:

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

Тестирование объектно-ориентированной интеграции

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

Р. Байндер предлагает две методики интеграции объектно-ориентированных систем [16]:

  • тестирование, основанное на потоках;
  • тестирование, основанное на использовании.

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

Д. МакГрегор считает, что одним из шагов объектно-ориентированного тестирования интеграции должно быть кластерное тестирование [50]. Кластер сотрудничающих классов определяется исследованием CRC-модели или диаграммы сотрудничества объектов. Тестовые варианты для кластера ориентированы на обнаружение ошибок сотрудничества.

Объектно-ориентированное тестирование правильности

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

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

Для подтверждения правильности может проводиться обычное тестирование «черного ящика».

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

Проектирование объектно-ориентированных тестовых вариантов

Традиционные тестовые варианты ориентированы на проверку последовательности: ввод исходных данных — обработка — вывод результатов — или на проверку внутренней управляющей (информационной) структуры отдельных модулей. Объектно-ориентированные тестовые варианты проверяют состояния классов. Получение информации о состоянии затрудняют такие объектно-ориентированные характеристики, как инкапсуляция, полиморфизм и наследование.

Инкапсуляция

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

Полиморфизм

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

y=functionA(x).

В стандартном ПО достаточно рассмотреть одну реализацию поведения, которая обеспечивает вычисление функции. В объектно-ориентированном ПО придется рассматривать поведение реализации Базовый_класс :: functionA(х), Производный_клacc :: functionA(x), Наследиик_Производного_класса :: functionA(х). Здесь двойным двоеточием от имени операции отделяется имя класса, в котором размещена операция (это обозначение UML). Таким образом, в объектно-ориентированном контексте каждый раз при вызове functionA(x) следует рассматривать набор различных поведений. Конечно, подход к тестированию базовых и производных классов в основном одинаков. Разница состоит только в учете используемых системных ресурсов.

Наследование

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

Рассмотрим следующий случай. Положим, что операция Дочерний_класс::унаследована() вызывает операцию переопределен(). К чему это приводит? Поскольку реализация операции переопределен() изменена, операция Дочерний_класс::унаследована() может не соответствовать этой новой реализации. Поэтому нужны новые тесты, хотя содержание операции унаследована() не изменено.

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

Родительский_класс::переопределена() и Дочерний_класс::переопределена() —это две разные операции с различными спецификациями и реализациями. Каждая из них проверяется самостоятельным набором тестов. Эти тесты нацелены на вероятные ошибки: ошибки интеграции, ошибки условий, граничные ошибки и т. д. Однако сами операции, как правило, похожи. Наборы их тестов будут перекрываться. Чем лучше качество объектно-ориентированного проектирования, тем больше перекрытие. Таким образом, новые тесты надо формировать только для тех требований к операции Дочерний_класс::переопределена(), которые не покрываются тестами для операции Родительский_класс::переопределена().

Выводы:

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

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

Способы тестирования «черного ящика» также применимы к объектно-ориентированным системам. Полезную входную информацию для тестирования «черного ящика» и тестирования состояний обеспечивают элементы Use Case.

Тестирование, основанное на ошибках

Цель тестирования, основанного на ошибках, — проектирование тестов, ориентированных на обнаружение предполагаемых ошибок [46]. Разработчик выдвигает гипотезу о предполагаемых ошибках. Для проверки его предположений разрабатываются тестовые варианты.

В качестве примера рассмотрим булево выражение

if (X and not Y or Z).

Инженер по тестированию строит гипотезу о предполагаемых ошибках выражения:

  • операция not сдвинулась влево от нужного места (она должна применяться к Z);
  • вместо and должно быть or;
  • вокруг not Y or Z должны быть круглые скобки.

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

Обсудим первую предполагаемую ошибку. Значения (X = false, Y = false, Z = false) устанавливают указанное выражение в false. Если вместо not Y должно быть not Z, то выражение принимает неправильное значение, которое приводит к неправильному ветвлению. Аналогичные рассуждения применяются к генерации тестов по двум другим ошибкам.

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

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

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

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

Тестирование, основанное на сценариях

Тестирование, основанное на ошибках, оставляет в стороне два важных типа ошибок:

  • некорректные спецификации;
  • взаимодействия между подсистемами.

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

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

Тестирование, основанное на сценариях, ориентировано на действия пользователя, а не на действия программной системы [47]. Это означает фиксацию задач, которые выполняет пользователь, а затем применение их в качестве тестовых вариантов. Задачи пользователя фиксируются с помощью элементов Use Case.

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

Рассмотрим, например, проектирование тестов, основанных на сценариях, для текстового редактора.

Рабочие сценарии опишем в виде спецификаций элементов Use Case.

Элемент Use Case: Исправлять черновик.

Предпосылки: обычно печатают черновик, читают его и обнаруживают ошибки, которые не видны на экране. Данный элемент Use Case описывает события, которые при этом происходят.

1. Печатать весь документ.

2. Прочитать документ, изменить определенные страницы.

3. После внесения изменения страница перепечатывается.

4. Иногда перепечатываются несколько страниц.

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

  • метод для печати отдельной страницы;
  • метод для печати диапазона страниц.

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

Элемент Use Case: Печатать новую копию.

Предпосылки: кто-то просит пользователя напечатать копию документа.

1. Открыть документ.

2. Напечатать документ.

3. Закрыть документ.

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

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

Элемент Use Case: Печатать новую копию.

  1. Открыть документ.
  2. Выбрать в меню пункт Печать.
  3. Проверить, что печаталось, и если печатался диапазон страниц, то выбрать опцию Печатать целый документ.
  4. Нажать кнопку Печать.
  5. Закрыть документ.

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

Разработчик может опустить эту зависимость в тестовом варианте, но, вероятно, проблема обнаружится в ходе тестирования. И тогда разработчик будет выкрикивать: «Я предполагал, я предполагал это учесть!!!».

Тестирование поверхностной и глубинной структуры

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

Глубинная структура отражает внутренние технические подробности объектно-ориентированной системы (на уровне проектных моделей и программного текста). Тесты глубинной структуры исследуют зависимости, поведение и механизмы взаимодействия, которые создаются в ходе проектирования подсистем и объектов.

В качестве базиса для тестирования глубинной структуры используются модели анализа и проектирования. Например, разработчик исследует диаграмму взаимодействия (невидимую извне) и спрашивает: «Проверяет ли тест сотрудничество, отмеченное на диаграмме?»

Диаграммы классов обеспечивают понимание структуры наследования, которая используется в тестах, основанных на ошибках. Рассмотрим операцию ОБРАБОТАТЬ (Ссылка_на_РодительскийКласс). Что произойдет, если в вызове этой операции указать ссылку на дочерний класс? Есть ли различия в поведении, которые должны отражаться в операции ОБРАБОТАТЬ? Эти вопросы инициируют создание конкретных тестов.

Способы тестирования содержания класса

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

Стохастическое тестирование класса

При стохастическом тестировании исходные данные для тестовых вариантов генерируются случайным образом. Обсудим методику, предложенную С. Кирани и В.Тсай[43].

Рассмотрим класс Счет, который имеет следующие операции: Открыть, Установить, Положить, Снять, Остаток, Итог, ОграничитьКредит, Закрыть.

Каждая из этих операций применяется при определенных ограничениях:

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

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

Открыть ► Установить ► Положить ► Снять ► Закрыть.

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

Открыть ► Установить ► Положить ► [Остаток●Снять●Итог●ОграничитьКредит●Положить]n Снять ► Закрыть.

Здесь приняты дополнительные обозначения: точка означает операцию И/ИЛИ, пара квадратных скобок — группировку, а показатель степени — количество повторений группировки.

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

Тестовый вариант N:

Открыть ► Установить ► Положить ► Остаток ► Снять ►Итог ► Снять ► Закрыть.

Тестовый вариант М:

Открыть ► Установить ► Положить ► Итог ► ОграничитьКредит ► Снять ► Остаток ► Снять ► Закрыть.

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

Тестирование разбиений на уровне классов

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

Обычно используют одну из трех категории разбиения [43]. Категории образуются операциями класса.

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

Тестовый вариант 1:

Открыть ►Установить ►Положить Положить Снять ►Снять ►Закрыть.

Тестовый вариант 2:

Открыть Установить ►Положить Остаток ►Итог ►ОграничитьКредит Снять Закрыть.

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

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

1) операции, которые используют ограничение кредита;

2) операции, которые изменяют ограничение кредита;

3) операции, которые не используют и не изменяют ограничение кредита.

Для каждой категории создается тестовая последовательность.

Третий способ — разбиение на категории по функциональности. Основывается на общности функций, которые выполняют операции. Например, операции в классе Счет могут быть разбиты на категории:

  • операции инициализации (Открыть, Установить);
  • вычислительные операции (Положить, Снять);
  • запросы (Остаток, Итог, ОграничитьКредит);
  • операции завершения (Закрыть).

Способы тестирования взаимодействия классов

Для тестирования сотрудничества классов могут использоваться различные способы [43]:

  • стохастическое тестирование;
  • тестирование разбиений;
  • тестирование на основе сценариев;
  • тестирование на основе состояний.

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

Банк:
ПроверитьСчет( ); ЗапросДепозита ( ); РазрешитьКарту( );
ПроверитьРIN( ); ИнфоСчета( ); СнятьРазрешен( );
ПроверитьПолис( ); ОткрытьСчет( ); ЗакрытьСчет( ).
ЗапросСнятия( ); НачальнДепозит( );
Банкомат:
КартаВставлена( ); Положить( ); СостояниеСчета( );
Пароль( ); Снять( ); Завершить( ).
ИнтерфейсБанкомата:
ПроверитьСостояние( ); ВыдатьНаличные( ); ЧитатьИнфоКарты( );
СостояниеПоложить( ); ПечатьСостСчета( ); ПолучитьКолвоНалич( ).
Счет:
ОграничКредит( ); Остаток) ); Положить( );
ТипСчета( ); Снять( ); Закрыть( ).
ПодтверждениеПравильности:
ПодтвРIN( ); ПодтвСчет( ).

Диаграмма сотрудничества объектов банковской системы представлена на рис. 16.1. На этой диаграмме отображены связи между объектами, стрелки передачи сообщений подписаны именами вызываемых операций.

Рис. 16.1. Диаграмма сотрудничества банковской системы

Стохастическое тестирование

Стохастические тестовые варианты генерируются следующей последовательностью шагов.

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

В качестве примера приведем последовательность операций для класса Банк, вызываемых классом Банкомат:

ПроверитьСчет ПроверитьРIN ►[[ПроверитьПолис ►

ЗапросСнятия]●ЗапросДепозита●ИнфоСчета]n.
ПРИМЕЧАНИЕ

Здесь приняты следующие обозначения: стрелка означает операцию следования, точка — операцию И/ИЛИ, пара квадратных скобок — группировку операций классов, показатель степени — количество повторений группировки из операций классов.
Случайный тестовый вариант для класса Банк может иметь вид

Тестовый вариант N: ПроверитьСчет ПроверитьРШ ЗапросДепозита.

Для выявления сотрудников, включенных в этот тест, рассматриваются сообщения, связанные с каждой операцией, записанной в ТВ N. Для выполнения заданий ПроверитьСчет и ПроверитьРТМ Банк должен сотрудничать с классом ПодтверждениеПравильности. Для выполнения задания ЗапросДепозита Банк должен сотрудничать с классом Счет. Отсюда новый ТВ, который проверяет отмеченные сотрудничества:

Тестовый вариант М: ПроверитьСчетБанк (ПодтвСчетПодтвПрав) ►ПроверитьРINБанк (ПодтвРШПодтвПрав) ►ЗапросДепозитаБанк ►(ПоложитьСчет).

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

Тестирование разбиений

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

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

Тестирование на основе состояний

В качестве источника исходной информации используют диаграммы схем состояний, фиксирующие динамику поведения класса. Данный способ позволяет получить набор тестов, проверяющих поведение класса и тех классов, которые сотрудничают с ним [43]. В качестве примера на рис. 16.2 показана диаграмма схем состояний класса Счет.

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

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

Тестовый вариант 1: Открыть ►УстановитьСчет Положить (начальное) ►Снять (конечное) Закрыть.

Отметим, что эта последовательность аналогична минимальной тестовой последовательности. Добавим к минимальной последовательности дополнительные тестовые варианты:

Тестовый вариант 2: Открыть УстановитьСчет Положить (начальное) ►Положить Остаток Кредит ►Снять (конечное) ►Закрыть

Тестовый вариант 3: Открыть Установить ►Положить (начальное) ►Положить Снять ИнфоСчета Снять (конечное) ►Закрыть

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

Возможна другая методика исследования состояний.— «преимущественно в ширину».

В этой методике:

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

Рассмотрим объект Карта клиента (рис. 16.3). Начальное состояние карты Не определена, то есть не установлен номер карты. После чтения карты (в ходе диалога с банкоматом) объект переходит в состояние Определена. Это означает, что определены банковские идентификаторы Номер Карты и Дата Истечения Срока. Карта клиента переходит в состояние Предъявляется на рассмотрение, когда проводится ее авторизация, и в состояние Разрешена, когда авторизация подтверждается. Переход карты клиента из одного состояния в другое проверяется отдельным тестовым вариантом.

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

Предваряющее тестирование при экстремальной разработке

Предваряющее тестирование и рефакторинг (реорганизация) — основной способ разработки при экстремальном программировании.

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

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

Для демонстрации такого подхода рассмотрим пример конкретной разработки. Будем опираться на технику, описанную Робертом Мартином (с любезного разрешения автора)*.

* Robert C. Martin. RUP/XP Guidelines: Test-first Design and Refactoring. — Rational Software White Paper, 2000.
Создадим программу для регистрации посещений кафе-кондитерской. Каждый раз, когда лакомка посещает кафе, вводится количество купленных булочек, их стоимость и текущий вес любителя (любительницы) сладостей. Система отслеживает эти значения и выдает отчеты. Программу будем писать на языке Java.

Для экстремального тестирования удобно использовать среду Junit, авторами которой являются Кент Бек и Эрик Гамма (Kent Beck и Erich Gamma). Прежде всего создадим среду для хранения тестов модулей. Это очень важно для предваряющего тестирования: вначале пишется тестовый вариант, а только потом — код программы. Необходимый код имеет следующий вид:
Листинг 16.1. ТестЛакомки. java

import junit.framework.*;

public class ТестЛакомки extends TestCase

{

public ТестЛакомки (String name)

{

super(name);

}

}

Видно, что при использовании среды Junit класс-контейнер тестовых вариантов должен быть наследником от класса TestCase. Кстати, условимся весь новый код выделять полужирным шрифтом.

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

import junit.framework.*;

public class ТестЛакомки extends TestCase

{

public ТестЛакомки (String name)

{

super(name);

}

public void тестСоздатьПосещениеКафе()

{

ПосещениеКафе v = new-ПосещениеКафе();

}

}

Для компиляции этого фрагмента подключим класс ПосещениеКафе.
Листинг 16.3. ТестЛакомки.jаvа и ПосещениеКафе.jаvа

ТестЛакомки.jаvа

import junit. framework.*;

import ПосещениеКафе;

public class ТестЛакомки extends TestCase

{

public ТестЛакомки (String name)

{

super(name);

}

public void тестСоздатьПосещениеКафе()

{

ПосещениеКафе v = new ПосещениеКафе();

}

}

ПосещениеКафе.java

public class ПосещениеКафе

{

}

Этот код компилируется, тест проходит, и мы готовы добавить необходимую функциональность.
Листинг 16.4. ТестЛакомки.jауа и ПосещениеКафе.jауа

ТестЛакомки.java

import junit.framework.*;

import ПосещениеКафе;

import java.util.Date

public class ТестЛакомки extends TestCase

{

public TecтЛакомки(String name)

{

super(name):

}

public void тестСоздатьПосещениеКафе()

{

Date дата = new Date();

double булочки = 7.0; // 7 булочек

double стоимость = 12.5 * 7;

// цена 1 булочки — 12.5 руб.

double вес = 60.0; // взвешивание лакомки

double дельта = 0.0001; // точность

ПосещениеКафе v =

new ПосещениеКафе(дата, булочки, стоимость, вес);

assertEquals(дата, v.получитьДату( ));

assertEquals(12.5 * 7, v.получитьСтоииость(), дельта);

assertEquals(7.0, v.получитьБулочки(), дельта);

assertEquals(60.0, v.получитьВес(), дельта);

assertEquals(12.5, v.получитьЦену(). дельта);

}

}

ПосещениеКафе.java

import Java.uti1.Date;

public class ПосещениеКафе

{

private Date егоДата;

private double егоБулочки;

private double егоСтоимость;

private double eroBec;

public ПосещениеКафе(Date дата, double булочки,

double стоимость, double вес)

{

егоДата = дата;

егоБулочки = булочки;

егоСтоимость = стоимость;

егоВес = вес;

}

public Date получитьДату() {return егоДата;}

public double получитьБулочки() {return егоБулочки;}

public double получитьСтоимость() {return егоСтоимость;}

public double получитьЦену(){return егоСтоимость/егоБулочки;}

public double получитьВес() {return eroBec;}

}

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

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

Далее определимся с хранением объектов класса ПосещениеКафе. Очевидно, что свойство егоВес характеризует лакомку. Таким образом, объект ПосещениеКафе записывает часть состояния лакомки па момент посещения кафе. Следовательно, нужно создать объект Лакомка и содержать объекты класса ПосещениеКафе в нем.
Листинг 16.5. ТестЛакомки.java и Лакомка.java

ТестЛакомки.java

import junit.framework.*;

import ПосещениеКафе;

import java.util.Date

public class ТестЛакомки extends TestCase

{

public TecтЛакомки(String name)

{

super(name);

}

public void тестСоздатьЛакомку()

{

Лакомка g = new Лакомка();

assertEquals(0, д.получитьЧислоПосещений());

}

}

Лакомка.Java

public class Лакомка

{

public int получитьЧислоПосещений()

{

return 0;

}

}

Листинг 16.5 показывает начальный шаг. Мы написали новую тестовую функцию тестСоздатьЛакомку. Эта функция создает объект класса Лакомка и затем убеждается, что хранимое количество посещений равно 0. Конечно, реализация метода получитьЧислоПосещений неверна, но она обеспечивает прохождение теста. Это позволит нам в будущем выполнить рефакторинг (для улучшения решения).

Введем в класс Лакомку объект-контейнер, хранящий данные о разных посещениях (как элементы списка в массиве изменяемого размера). Для его создания используем класс-контейнер Array List из библиотеки Java 2. В будущем нам потребуются три метода контейнера: add (добавить элемент в контейнер), get (получить элемент из контейнера), size (вернуть количество элементов в контейнере).
Листинг 16.6. ЛАKOMKА.java

import java.util.ArrayList;

public class Лакомка

{

private ArrayList егоПосещения = new ArrayList();

// создание объекта егоПосещения — контейнера посещений

public int получитьЧислоПосещений ()

{

return егоПосещения.size();

// возврат количества элементов в контейнере

// оно равно количеству посещений кафе

}

}

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

На следующем шаге следует определить, как к Лакомке добавляется посещение кафе. Так будет выглядеть простейший тестовый вариант:
Листинг 16.7. TecтЛакомки.java

public void тестДобавитьПосещение()

{

double булочки = 7.0; // 7 булочек

double стоимость = 12.5 * 7; // цена 1 булочки = 12.5 руб.

double вес = 60.0; // взвешивание лакомки

double дельта = 0.0001; // точность

Лакомка g = new Лакомка();

g.добавитьПосещениеКафе(булочки, стоимость, вес);

assertEquals(1, g.получитьЧислоПосещений());

}

В этом тесте объект класса ПосещениеКафе не создается. Очевидно, что создавать объект и добавлять его в список должен метод добавитьПосещениеКафе объекта Лакомка.
Листинг 16.8. Лакомка.jауа

public void добавитьПосещениеКафе((double булочки, double стоимость, double вес)

{

ПосещениеКафе v =

new ПосещениеКафе(new Date(), булочки, стоимость, вес);

егоПосещения.add(v);

// добавление эл-та v в контейнер посещений

}

Опять прогоняются все тесты. Анализ программного кода в функциях тестДобавитьПосещение и тестСоздатьПосещениеКафе показывает, что он частично дублируется. Обе функции создают одинаковые локальные переменные и инициализируют их одинаковыми значениями. Чтобы избавиться от дублирования, проведем рефакторинг тестируемой программы и сделаем локальные переменные свойствами класса.
Листинг 16.9. ТестЛакомки.jауа

import junit.framework.*;

import ПосещениеКафе;

import java.util.Date;

public class ТестЛакомки extends TestCase

{

private double булочки — 7.0; // 7 булочек

private double стоимость = 12.5 * 7;

// цена 1 булочки = 12.5 p.

private double вес = 60.0; // взвешивание лакомки

private double дельта = 0.0001; // точность

public ТестЛакомки(String name)

{

super(name);

}

public void тестСоздатьПосещениеКафе()

{

Date дата = new Date();

ПосещениеКафе v = new ПосещениеКафе(дата. булочки.

стоимость, вес);

assertEquals(date, v.получитьДату());

assertEquals(12.5 * 7. v.получитьСтоимость(). дельта);

assertEquals(7.0. v.получитьБулочки(). дельта);

assertEquals(60.0. v.получитьВес(), дельта);

assertEquals(12.5. v.получитьЦену(). дельта):

}

public void тестСоздатьЛакомку()

{

Лакомка g = new Лакомка ();

assertEquals(0. g.получитьЧислоПосещений());

}

public void тестДобааитьПосещение()

{

Лакомка g = new Лакомка();

g.добавитьПосещениеКафе(булочки. стоимость, вес);

assertEquals(1. g.получитьЧислоПосещениРК));

}

}

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

Очередная задача — после добавления к Лакомке объектов ПосещениеКафе у Лакомки можно запрашивать генерацию отчетов. Сначала напишем тесты, начнем с простейшего теста.
Листинг 16.10. TecтЛакомки.java

public void тестОтчетаОдногоПосещения()

{

Лакоика g = new Лакоика();

g.добавитьПосещениеКафе(булочки. стоимость, вес);

Отчет r = g.создатьОтчет();

assertEquals(0. r.получитьИзменениеВеса(), дельта);

assertEqualз(булочки, г.получитьПотреблениеБулочек(),

дельта);

assertEquals(0, r.получитьВесНаБулочку(), дельта);

assertEquals(стоимость. r.получитьСтоимостьБулочек(),

дельта);

}

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

Значения, возвращаемые методами-селекторами, следует проанализировать. Для вычисления изменения веса (или приращения веса на одну булочку) одного посещения кафе недостаточно. Чтобы вычислить эти значения, необходимы, как минимум, два посещения, С другой стороны, одного визита достаточно, чтобы сосчитать потребление и стоимость булочек.

Разумеется, тестовый вариант не компилируется. Поэтому необходимо добавить соответствующие методы и классы. Сначала добавим код, обеспечивающий компиляцию, но не обеспечивающий выполнение тестов.
Листинг 16.11. Лакомка.java, TecтЛакомки.java и Отчет.jаvа

Лакомка.java

public Отчет создатьОтчет()

{

return new Отчет();

}

ТестЛакомки.java

public void тестОтчетаОдногоПосещения()

{

Лакомка g = new Лакомка();

g.добавитьПосещениеКафе(булочки, стоимость, вес);

Отчет r = g.создатьОтчет();

assertEquals(0, r.получитьИзменениеВеса(), дельта);

assertEquals(булочки. r.получитьПотреблениеБулочек(),

дельта);

assertEquals(0. r.получитьВесНаБулочку(), дельта);

assertEquals(cтоимость,. r.получитьСтоимостьБулочек(),.

дельта);

}

Отчет.java

public class Отчет

{

public double получитьИзменениеВеса()

{return егоИзменениеВеса;}

public double получитьВесНаБулочку()

{return егоВесНаБулочку;}

public double получитьСтоииостьБулочек()

{return егоСтоимостьБулочек;}

public double получитьЛотреблениеБулочек()

{return егоПотреблениеБулочек;}

private double егоИзменениеВеса;

private double егоВесНаБулочку;

private double егоСтоимостьБулочек;

private double егоПотреблениеБулочек;

}

Код в листинге 16.11 компилируется и запускается, но его недостаточно для того, чтобы прошли тесты. Нужен рефакторинг кода. Для начала сделаем минимально возможные изменения.
Листинг 16.12. Лакомка.java и Отчет.java

Лакомка.java

public Отчет создатьОтчет()

{

Отчет r = new Отчет();

ПосещениеКафе v = (ПосещениеКафе) егоПосещения. Get(0);

// занести в v первый элемент из контейнера посещений

r.устВесНаБулочку(0);

r.устИзменениеВеса(0);

r.устСтоимостьБулочек(v.получитьСтоимость());

r.устПотреблениеБулочек(v.получитьБулочки()):

return r;

}

Отчет.java

public void устВесНаБулочку (double wpb)

{егоВесНаБулочку = wpb;}

public void устИзменениеВес(double kg)

{егоИзменениеВеса = kg;}

public void устСтоимостьБулочек(double ct)

(егоСтоимостьБулочек = ct;}

public void устПотреблениеБулочек (double b)

{егоПотреблениеБулочек = b;}

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

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

Для завершения кода продумаем тесты для Лакомки без посещений и с несколькими посещениями кафе. Начнем с теста и кода для варианта без посещений.
Листинг 16.13. TecтЛакомки.java и Лакомка.jауа

ТестЛакомки.java

public void тестОтчетаБезПосещений()

{

Лакомка g = new Лакомка();

Отчет r= g.создатьОтчет();

assertEquals(0, r.получитьИзменениеВеса(). дельта);

assertEquals(0, r.получитьПотреблениеБулочек(), дельта);

assertEquals(0, r.получитьВесНаБулочку()), дельта;

assertEquals(0, r.получитьСтоимостьБулочек(), дельта);

}

Лакомка.Java

public Отчет создатьОтчет()

{

Отчет r = new Отчет();

if (егоПосещения.size() = 0)

{

r.устВесНаБулочку(0);

r.устИзиенениеВеса(0);

r.устСтоимостьБулочек(0);

r.устПотреблениеБулочек(0);

}

else

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(0);

// занести в v первый элемент из контейнера посещений

r.устВесНаБулочку(0);

r.устИзменениеВеса(0);

r.устСтоимостьБулочек(v.получитьСтоимость());

r. устПотреблениеБулочек (v.получитьБулочки ()):

}

return r;

}

Теперь начнем создавать тестовый вариант для нескольких посещений.
Листинг 16.14. ТестЛакомки.jауа

public void тестОтчетаНесколькихПосещений()

{

Лакомка g = new Лакомка();

g.добавить(ПосещениеКафе(7. 87.5, 60.7);

g.добавитьПосещениеКафе(14. 175, 62.1);

g.добавитьПосещениеКафе(28, 350. 64.9);

Отчет r= g.создатьОтчет();

assertEquals(4.2, r.получитьИзменениеВеса(), дельта);

assertEquals(49. r.получитьПотреблениеБулочек(), дельта);

assertEquals(0.086, r.получитьВесНаБулочку(), дельта);

assertEquals(612.5, r.получитьСтоииостьБулочек(), дельта);

}

Мы установили число посещений для Лакомки равным трем. Предполагается, что цена булочки составляет 12,5 руб., а изменение веса — 0,1 кг на одну булочку. Таким образом, за 175 руб. лакомка покупает и съедает 14 булочек, полнея на 1,4 кг.

Но здесь какая-то ошибка. Скорость изменения веса должна определяться коэффициентом 0,1 кг на одну булочку. А если разделить 4,2 (изменение веса) на 49 (количество булочек), то получаем коэффициент 0,086. В чем причина несоответствия?

После размышлений становится понятно, что вес лакомки регистрируется на выходе из кафе. Поэтому приращение веса и потребление булочек во время первого посещения не учитывается. Изменим исходные данные теста.
Листинг 16.15. ТестЛакомки.jауа

public void тестОтчетаНесколькихПосещений()

{

Лакомка g = new Лакомка();

g.добавитьПосещениеКафе(7. 87.5. 60.7);

g.добавитьПосещениеКафе(14. 175. 62.1);

g.добавитьПосещениеКафе(28. 350. 64.9);

Отчет r — g.создатьОтчет();

assertEquals(4.2, r.получитьИзменениеВеса(), дельта);

assertEquals(42, r.получитьПотреблениеБулочек(), дельта);

assertEquals(0.1, r.получитьВесНаБулочку(), дельта);

assertEquals(612.5, r.получитьСтоимостьБулочек(), дельта);

}

Этот тест корректен. Никогда не известно, с чем встретишься при написании тестов. Можно быть уверенным лишь в том, что, определяя понятия дважды (при написании тестов и кода), вы найдете больше ошибок, чем при простом написании кода.

Теперь добавим код, обеспечивающий прохождение теста из листинга 16.15.
Листинг 16.16. Лакомка.java

public Отчет создатьОтчет()

{

Отчет r = new Отчет ();

if (егоПосещения.size() = 0)

{

r.устВесНаБулочку(0);

r.устИзменениеВеса(0);

r.устСтоимостьБулочек(0);

r.устПотреблениеБулочек(0);

}

else if (егоПосещения.size() = 1)

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(0);

// занести в v первый элемент из контейнера посещений

r.устВесНаБулочку(0);

r.устИзменениеВеса(0);

r.устСтоимостьБулочек(v.получитьСтоимость());

r.устПотреблениеБулочек(v.получитьБулочки());

}

else

{

double первыйЗамер = 0;

double последнийЗамер = 0;

double общаяСтоиность = 0;

double потреблениеБулочек = 0;

for (int i = 0; i < егоПосещения.size(); i++)

// проход по всем элементам контейнера посещений

{

ПосещениеКафе v = (ПосещениеКафе)

егоПосещения.get(i);

// занести в v 1-й элемент из контейнера посещений

if (i = = 0)

{

первыйЗамер = v.получитьВес();

// занести в первыйЗамер вес при 1-м посещении

потреблениеБулочек -= v.получитьБулочки();

}

if (i= = егоПосещения.size()- 1) последнийЗамер =

v.получитьВес();

// занести в последнийЗамер вес при послед, посещении

общаяСтоимость += v.получитьСтоиность();

потреблениеБулочек += v.получитьБулочки();

}

double изменение = последнийЗамер — первыйЗамер;

r.устВесНаБулочкуСизменение/потреблениеБулочек);

r.устИзненениеВеса(иэненение);

r.устСтоиностьБулочек(общаяСтоиность):

r.устПотреблениеБулочек(потреблениеБулочек);

}

return r;

}

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

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

public Отчет создатьОтчет()

{

Отчет r = new Отчет();

double первыйЗамер = 0;

double последнийЗамер = 0;

double общаяСтоимость = 0;

double потреблениеБулочек = 0;

for (int i= 0; i< егоПосещения.size(); i++)

// проход по всем элементам контейнера посещений

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

// занести в v i-й элемент из контейнера посещений

if (i = = 0)

{

первыйЗамер = v. ПолучитьВес();

//занести в первыйЗамер вес при 1-м посещении

потреблениеБулочек -= v.получитьБулочки();

}

if (i= = егоПосещения.size()- 1) последнийЗамер =

v. получитьВес();

// занести в последнийЗамер вес при послед. посещении

общаяСтоимость += v.получитьСтоимость();

потреблениеБулочек += v.получитьБулочки();

}

double изменение = последнийЗамер – первыйЗамер;

r.устВесНаБулочку(изменение/потреблениеБулочек);

r.устИзменениеВеса(изменение);

r.устСтоимостьБулочек(общаяСтоимость);

r.устПотреблениеБулочекСпотреблениеБулочек);

return r;

}

Теперь попытаемся сделать функцию короче и понятнее. Переместим фрагменты кода так, чтобы их можно было вынести в отдельные функции.
Листинг 16.18. Лакомка.java

public Отчет создатьОтчет()

{

Отчет г = new Отчет();

double изменение = 0;

double общаяСтоимость = 0;

double потреблениеБулочек =0;

double первыеБулочки = 0; double wpb =0;

if (егоПосещения.size() > 0)

{

ПосещениеКафе первоеПосещение =

(ПосещениеКафе) егоПосещения.get(0);

ПосещениеКафе последнееПосещение = (ПосещениеКафе)

егоПосещения.get(егоПосещения.size() — 1);

double первыйЗамер = первоеПосещение.получитьВес();

double последнийЗамер =

последнееПосещение. ПолучитьВес();

изменение = последнийЗамер – первыйЗамер;

первыеБулочки = первоеПосещение.получитьБулочки();

for (int i = 0; i < егоПосещения.size(); i++)

{

ПосещениеКафе v = (ПосещениеКафе)

егоПосещения.get(i);

общаяСтоимость += v.получитьСтоимость();

потреблениеБулочек += v.получитьБулочки();

}

потреблениеБулочек -= первыеБулочки;

if (потреблениеБулочек > 0)

wpb = изменение / потреблениеБулочек;

}

r.устВесНаБулочку(wpb );

r.устИзменениеВеса(изненение);

r.устСтоимостьБулочек(общаяСтоиность);

r.устПотреблениеБулочек(потреблениеБулочек);

return r;

}

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

if (егоПосещения.size() > 0)

{

ПосещениеКафе первоеПосещение =

(ПосещениеКафе) егоПосещения.get(0);

ПосещениеКафе последнееПосещение = (ПосещениеКафе)

егоПосещения.get(егоПосещения.size() — 1):

double первыйЗамер = первоеПосещение.получитьВес();

double последнийЗамер = последнееПосещение.получитьВес();

изменение = последнийЗамер – первыйЗамер;

первыеБулочки = первоеПосещение.получитьБулочки();

for (int i =0; i < егоПосещения.size(); i++)

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

потреблениеБулочек += v.получитьБулочки();

}

for (int i =0; i < егоПосещения.size(); i++)

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

общаяСтоимость += v.получитьСтоимость();

}

потреблениеБулочек -= первыеБулочки;

if (потреблениеБулочек > 0)

wpb = изменение / потреблениеБулочек;

}

Выполним тестирование. На следующем шаге поместим каждый цикл в отдельный приватный метод.
Листинг 16.20. Лакомка.java

public Отчет создатьОтчет()

{

Отчет г = new Отчет();

double изменение = 0;

double общаяСтоимость = 0;

double потреблениеБулочек = 0;

double первыеБулочки =0;

double wpb = 0;

if (егоПосещения. Size() > О)

{

ПосещениеКафе первоеПосещение =

(ПосещениеКафе) егоПосещения.get(0);

ПосещениеКафе последнееЛосещение = (ПосещениеКафе)

егоПосещения.get(егоПосещения.size() — 1);

double первыйЗамер = первоеПосещение.получитьВес();

double последнийЗамер =

последнееПосещение.получитьВес();

изменение — последнийЗамер – первыйЗамер;

первыеБулочки = первоеПосещение.получитьБулочки();

потреблениеБулочек = вычПотреблениеБулочек();

общаяСтоимость = вычОбщуюСтоимость();

потреблениеБулочек -= первыеБулочки;

if (потреблениеБулочек > 0)

wpb = изменение / потреблениеБулочек;

}

r.устВесНаБулочку(wpb);

r.устИзменениеВеса(изменение);

r.устСтоимостьБулочек(общаяСтоимость);

r.устПотреблениеБулочек(потреблениеБулочек);

return r;

}

private double вычОбщуюСтоимость()

{

double общаяСтоииость = 0;

for (int i = 0; i < егоПосещения.size(); i++);

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

общаяСтоимость += v.получитьСтоимость();

}

return общаяСтоимость;

}

private double вычПотреблениеБулочек()

{

double потреблениеБулочек = 0;

for (int i — 0; i < егоПосещения.size(); i++)

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

потреблениеБулочек += v.получитьБулочки();

}

return потреблениеБулочек;

}

После соответствующего тестирования перенесем обработку вариантов потребления булочек в метод вычПотреблениеБулочек.
Листинг 16.21. Лакомка.java

public Отчет создатьОтчет()

{

if (егоПосещения.size() > 0)

{

ПосещениеКафе первоеПосещение =

(ПосещениеКафе) егоПосещения.get(0);

ПосещениеКафе последнееПосещение — (ПосещениеКафе)

егоПосещения.get(егоПосещения.size() — 1);

double первыйЗамер = первоеПосещение.получитьВес();

double последнийЗамер =

последнееПосещение.получитьВес();

изменение = последнийЗамер — первыйЗамер;

потреблениеБулочек = вычПотреблениеБулочек();

общаяСтоимость — вычОбщуюС тонкость ();

if (потреблениеБулочек > 0)

wpb = изменение / потреблениеБулочек;

}

return r;

}

private double вычОбщуюСтоимость()

{

double общаяСтоимость = 0;

for (int i= 0; i < егоПосещения.size(); i++);

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

общаяСтоимость += v.получитьСтоимость();

}

return общаяСтоимость;

}

private double вычПотреблениеБулочек()

{

double потреблениеБулочек = 0;

if (егоПосещения.size() > 0)

{

for (int i = 1; i < егоПосещения.size(); i++)

{

ПосещениеКафе v = (ПосещениеКафе)

егоПосещения.get(i);

потреблениеБулочек += v.получитьБулочки();

}

}

return потреблениеБулочек;

}

Заметим, что функция вычПотреблениеБулочек теперь суммирует потребление булочек, начиная со второго посещения. И опять выполняем тестирование. На следующем шаге выделим функцию для расчета изменения веса.
Листинг 16.22. Лакомка.java

public Отчет создатьОтчет()

{

Отчет r = new Отчет ();

double изменение = 0;

double общаяСтоимость = 0;

double потреблениеБулочек = 0;

double первыеБулочки = 0;

double wpb = 0;

if (егоПосещения.size() > 0)

{

изменение = вычИзменение();

потреблениеБулочек = вычПотреблениеБулочек();

общаяСтоимость = вычОбщуюСтоимость();

if (потреблениеБулочек > 0)

wpb = изменение / потреблениеБулочек;

}

r.устВесНаБулочку(wpb);

r.устИзменениеВеса(изменение);

r.устСтоимостьБулочек(общаяСтоимость);

r.устПотреблениеБулочек(потреблениеБулочек):

return r;

}

private double вычИзменение()

{

double изменение = 0;

if (егоПосещения.size() > 0)

{

ПосещениеКафе первоеПосещение =

(ПосещениеКафе) егоПосещения.get(0);

ПосещениеКафе последнееПосещение = (ПосещениеКафе)

егоПосещения.get;(егоПосещения.sizе() — 1);

double первыйЗамер = первоеПосещение.получитьВес();

double последнийЗамер =

последнееПосещение. получитьВес();

изменение = последнийЗамер — первыйЗамер;

}

return изменение;

}

После очередного запуска тестов переместим условия в главном методе создатьОтчет и подчистим лишние места.
Листинг 16.23. Лакомка.java

public Отчет создатьОтчет()

{

double изменение = вычИзменение();

double потреблениеБулочек = вычПотреблениеБулочек();

double общаяСтоимость = вычОбщуюСтоимость();

double wpb = 0;

if (потреблениеБулочек > 0)

wpb = изменение / потреблениеБулочек;

Отчет г = new Отчет ();

r.устВесНаБулочку(wpb);

r.устИзменениеВеса(изменение);

r.устСтоимостьБулочек(общаяСтоимость);

r.устПотреблениеБулочек(потреблениеБулочек);

return r;

}

private double вычИзменение()

{

double изменение = 0;

if (eroПосещения.size() > 1)

{

ПосещениеКафе первоеПосещение =

(ПосещениеКафе) егоПосещения.get(0);

ПосещениеКафе последнееПосещение = (ПосещениеКафе)

егоПосещения.get(егоПосещения.size() — 1);

double первыйЗамер = первоеПосещение.получитьВес(0;

double последнийЗамер =

последнееПосещение. получитьВес();

изменение = последнийЗамер – первыйЗамер;

}

return изменение;

}

private double вычОбщуюСтоимость()

{

double общаяСтоимость =0;

for (int i= 0; i < егоПосещения.size(); i++);

{

ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(i);

общаяСтоимость += v.получитьСтоимость();

}

return общаяСтоимость;

}

private double вычПотреблениеБулочек()

{

double потреблениеБулочек = 0;

if (егоПосещения.size() > 1)

{

for (int i = 1; i < егоПосещения.size(); i++)

{

ПосещениеКафе v = (ПосещениеКафе)

егоПосещения.get(i);

потреблениеБулочек += v.получитьБулочки();

}

}

return потреблениеБулочек;

}

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

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

Контрольные вопросы

  1. Что такое CRC-карта? Как ее применить для тестирования визуальных моделей?
  2. Поясните особенности тестирования объектно-ориентированных модулей.
  3. В чем состоит суть методики тестирования интеграции объектно-ориентированных систем, основанной на потоках?
  4. Поясните содержание методики тестирования интеграции объектно-ориентированных систем, основанной на использовании.
  5. В чем заключаются особенности объектно-ориентированного тестирования правильности?
  6. К чему приводит учет инкапсуляции, полиморфизма и наследования при проектировании тестовых вариантов?
  7. Поясните содержание тестирования, основанного на ошибках.
  8. Поясните содержание тестирования, основанного на сценариях.
  9. Чем отличается тестирование поверхностной структуры от тестирования глубинной структуры системы?
  10. В чем состоит стохастическое тестирование класса?
  11. Охарактеризуйте тестирование разбиений на уровне классов. Как в этом случае получить категории разбиения?
  12. Поясните на примере разбиение на категории по состояниям.
  13. Приведите пример разбиения на категории по свойствам.
  14. Перечислите известные вам методы тестирования взаимодействия классов. Поясните их содержание.
  15. Приведите пример стохастического тестирования взаимодействия классов.
  16. Приведите пример тестирования взаимодействия классов путем разбиений.
  17. Приведите пример тестирования взаимодействия классов на основе состояний. В чем заключается особенность методики «преимущественно в ширину»?
  18. Поясните суть предваряющего тестирования.
  19. Какую роль в процессе экстремальной разработки играет рефакторинг?

ГЛАВА 16. Объектно-ориентированное тестирование

Процесс разработки — Тестирование, основанное на ошибках
Индекс материала
Процесс разработки
Рабочие потоки процесса
Технические артефакты
Идентификация риска
Анализ риска
Планирование управления риском
Этап НАЧАЛО (Inception)
Этап РАЗВИТИЕ (Elaboration)
Этап КОНСТРУИРОВАНИЕ (Construction)
Этап ПЕРЕХОД (Transition)
Этап НАЧАЛО
Этап РАЗВИТИЕ
Этап КОНСТРУИРОВАНИЕ
ХР-реализация
ХР-итерация
Элемент ХР-разработки
Коллективное владение кодом
Взаимодействие с заказчиком
Объектно-ориентированное тестирование
Особенности тестирования объектно-ориентированных «модулей»
Объектно-ориентированное тестирование правильности
Тестирование, основанное на ошибках
Тестирование, основанное на сценариях
Тестирование поверхностной и глубинной структуры
Тестирование разбиений на уровне классов
Стохастическое тестирование
Тестирование разбиений
Листинг 16.1.
Листинг 16.5.
Листинг 16.10
Листинг 16.15.
Листинг 16.20.
Автоматизация конструирования визуальной модели программной системы
Создание диаграммы последовательности
Создание диаграммы классов
Создание компонентной диаграммы
Заключение
Все страницы

Страница 22 из 37

Тестирование, основанное на ошибках

Цель тестирования, основанного на ошибках, — проектирование тестов, ориентированных на обнаружение предполагаемых ошибок [46]. Разработчик выдвигает гипотезу о предполагаемых ошибках. Для проверки его предположений разрабатываются тестовые варианты.

В качестве примера рассмотрим булево выражение

if (X and not Y or Z).

Инженер по тестированию строит гипотезу о предполагаемых ошибках выражения:

q       операция not сдвинулась влево от нужного места (она должна применяться к Z);

q       вместо and должно быть or;

q       вокруг not Y or Z должны быть круглые скобки.

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

Обсудим первую предполагаемую ошибку. Значения (X = false, Y = false, Z = false) устанавливают указанное выражение в false. Если вместо not Y должно быть not Z, то выражение принимает неправильное значение, которое приводит к неправильному ветвлению. Аналогичные рассуждения применяются к генерации тестов по двум другим ошибкам.

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

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

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

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

Неправильное исходное положение => включение в движение синергистов

Выполнение первой фазы

тестирования с максимальной силой => быстрое утомление мышцы

Врач работает в уступающем режиме

(концентрическое сокращение) => тонус не изменяется

Врач работает в подавляющем режиме

(эксцентрическое сокращение) => тонус снижается

Пациент задерживает дыхание,

касается участков тела => проводится терапевтическая локализация

Врач касается суставов пациента => проводится терапевтическая локализация

ФАКТОРЫ, РЕАЛИЗУЮЩИЕ ТОНУС МЫШЦ.

Периферический уровень

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

Сегментарный уровень

• функциональный блок

• компрессия корешка

• дуральная торзия

• венозный застой

• лимфостаз

• меридианный дисбаланс

Таламическнй уровень.

• висцеральный орган

• нейрологический зуб

Центральный уровень

• эмоциональный дисбаланс

• эндокринные нарушения

• обменные процессы

АССОЦИИРОВАННАЯ МЫШЦА

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

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

Клиника — определяется вторичным укорочением и гиперактивностью антогониста.

Терапевтическая локализация —

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

при локализации на саногенный очаг дисфункции не реагирует (отрицательная реакция).

Провокация — обычно не используется.

ИНДИКАТОРНАЯ МЫШЦА.

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

Терапевтическая локализация —

при расположении руки, магнита, камертона над патогенным очагом формирует функциональную слабость.

Провокация —

А. Механическая — смещение диагностируемого позвонка, органа.

• во всех направлениях вызывает слабость мышцы (органическое поражение, МТ противопоказана).

• во всех направлениях не вызывает слабость мышцы (ошибка ТЛ).

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

    Растянутая мышца
Укороченная мышца Функциональный блок

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

  Атипичный моторный паттерн

  Неоптимальная динамика

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

    Восстановление в суставах линейного смещения, соответ­ствующего остановленному угловому движению тела по­звонка,

    Восстановление длины связок, устранение в них триггерных точек,

  Растяжение (раскручивание) твердой мозговой оболочки,

    Восстановление симметричности длины надкостницы с правой и левой стороны.

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

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

• в одном направлении вызывает слабость мышцы (МТ показана в данном направлении с учетом rebound — mechanism).

В. Дыхательная — проводится в сочетании с механическим смещением, вызывающим слабость мышцы.

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

• на одну фазу дыхания исчезает мышечная слабость (используется при МТ).

• на обе фазы дыхания исчезает мышечная слабость (ошибка диагностики).

Характеристика болевого синдрома расслабленной мышцы

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

Диагностика формирования мышечного дисбаланса с позиции первичности мышечного укорочения или расслабления

характе­ристика
патогенез

  визуаль­ные критерии

    формирование атипичного моторного паттерна

    коррекция

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

  формируется как реакция мышцы на гиперафферрентацию, снижение активности мери­диана и др., и сопровождается ее гипервозбудимостью.

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

    устранение гиперафферентации укороченной мышцы, и ее постизометрическая релаксация.

6. МЕТОДЫ ДИАГНОСТИКИ В ПРИКЛАДНОЙ КИНЕЗИОЛОГИИ

Терапевтическая локализация

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

Провокация

Увеличение активности имеющегося очага поражения посредством раздражения:

1. Механическое раздражение —

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

2. Химическое раздражение — локализация на кожу, слизистые оболочки химических веществ (токсинов, пищевых добавок).

3. Эмоциональное раздражение —

проговаривание вслух или мысленно слов, дат, воспроизведение событий.

ВАРИАНТЫ ФУНКЦИОНАЛЬНЫХ БЛОКОВ

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

НЕЙРОВАСКУЛЯРНЫЕ ТОЧКИ

НЕЙРОЛИМФАТИЧЕСКИЕ ТОЧКИ

7. СХЕМА АССОЦИИРОВАНЫХ СВЯЗЕЙ МЫШЦ

8. СТРУКТУРНАЯ СОСТАВЛЯЮЩАЯ ЗДОРОВЬЯ. КОМПРЕССИОННЫЙ СИНДРОМ ПОЗВОНОЧНИКА

ДИАГНОСТИКА КОРЕШКОВОЙ КОМПРЕССИИ.

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

Объективный статус:

• снижение чувствительности и сухожильных рефлексов соответствующих для компремированного корешка.

• в нейтральном положении возможна слабость соответствующих мышц стопы (кисти)

• провокация движения соответствующим отделам позвоночника в направлении флексии, экстензии, латерофлексии, ротации

• данная провокация изменения силы тестируемых мышц бедра и стопы (плеча, кисти)

ОСОБЕННОСТИ ФОРМИРОВАНИЯ МЫШЕЧНОЙ СЛАБОСТИ ПРИ КОМПРЕССИИ КОРЕШКОВ.

1. Выявляется слабость всех мышц, иннервируемых данным корешком и расположенных ниже компрессии.

2. Терапевтическая локализация малоэффективна. Вместо нее используется компрессия (положение сидя, давление на голову).

3. Последовательность возникновения неврологического поражения:

• снижение тонуса мышц

• гиперстезия — гипостезия

• болевые ощущения

4. Сила мышц изменяется при положении «сидя — лежа». При движении в одну из сторон — флексия, латерофлексия, экстензия, ротация.

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

СООТВЕТСТВИЕ НАПРАВЛЕНИЯ ПРОВОКАЦИИ ПАТОБИОМЕХАНИЧЕСКОМУ ИЛИ ПАТОМОРФОЛОГИЧЕСКОМУ ИЗМЕНЕНИЮ СТРУКТУР ПОЗВОНОЧНИКА.

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

АЛГОРИТМ ДИАГНОСТИКИ КОМПРЕССИИ КОРЕШКОВ

1. Исследование в положении сидя.

2. Проведение провокации — флексия, экстензия, латерофлексия, ротация.

3. Исследование в положении лежа.

4. Повторное проведение провокации в направлении вызывающем слабость мышц при тестировании сидя.

5. Определение направления движения туловища увеличивающего и/или уменьшающего силу иннервируемых мышц.

КОМПРЕССИЯ ШЕЙНЫХ КОРЕШКОВ

Уровень поражения
 
Наименование мышцы
 
С5
 
надостная (Сд) дельтовидная (Сд)
 
С6
 
плечелучевая мышца плеча, двуглавая мышца, лучевой разгибатель кисти, локтевой разгибатель кисти
 
С7
 
треглавая мышца плеча, лучевой флексор кисти
 
С8
 
локтевой флексор кисти
 
Th1
 
червеобразные мышцы
 

BICEPS BRACHII & BRACHIALIS

Иннервация BICEPS – мышечно-кожный нерв, С5, 6

BRACHIALIS — мышечно-кожный нерв, лучевой нерв, С5, 6

Питание – бетаин, НСl, доуденальный экстракт, хлорофил.

Меридиан — желудок Орган – желудок

CORABRACHIALIS

Иннервация — мышечно-кожный нерв, С6, 7

Питание – lung glundilar, Vit. C. Меридиан — легкие Орган – легкие

BRACHIRADIALIS

Иннервация — лучевой нерв, С5, 6

Иннервация — лучевой нерв, С5, 6, 7, 8

Тестирование – давление на дорсальную поверхность кисти, вдоль второй пястной кости

в направлении сгибания и незначительно к локтевой стороне

Иннервация — лучевой нерв, С6, 7, 8

Тестирование – давление на дорсальную поверхность кисти вдоль постороне мизинца в направлении сгибания к лучевой стороне

TRICEPS BRACHII

Иннервация — лучевой нерв, С6, 7, 8, T1

Питание – возможно splin glundilars

Меридиан – поджелудочная железа

Орган – селезенка

Иннервация: Медиальный ненв С6, 7, 8

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

Тестирование: Давление на возвышение большого пальца в направлении разгибания и локтевой кости

ТЕСТИРУЕМЫЕ МЫШЦЫ

ПРИ ДИАГНОСТИКЕ КОМПРЕССИИ СПИННЫХ КОРЕШКОВ

Порядковый номер корешка Наименование мышцы
 
L1(2) косые мышцы, живота поперечная мышца живота, квадратная мышца поясницы, пояснично-подвздошная, портняжная мышца
L2(3) четырехглавая мышца, приводящие мышцы бедра, пояснично – подвздошная, портняжная мышца
L4 передняя большеберцовая четырехглавая бедра приводящая бедра
L5 разгибатель большого пальца, задняя большеберцовая, экстензоры бедра, большая ягодичная, средняя ягодичная, грушевидная
S1 длинная малоберцовая, короткая малоберцовая, третичная малоберцовая, экстензоры бедра, большая (средняя) ягодичная мышца, грушевидная
S2 длинный флексор большого пальца, флексоры пальцев (II-Y)

ABDOMINALS

Питание – витамин Е, концентрат двенадцатиперстной кишки или нуклепротеиновый экстракт

Меридиан – тонкий кишечник

Орган — тонкий кишечник

QUADRATUS LUMBORUM

Иннервация – поясничное сплетение Т12, L1, 2, 3

Питание – витамины Е, С и А. Меридиан – толстый кишечник. Орган – аппендикс

QUDRICIPS – Rectus Femoris

Иннервация – бедренный нерв, L1, 2, 3

Питание – витамины Д.

Меридиан – тонкий кишечник. Орган – тонкий кишечник

ADDUCTORS

Иннервация – бедренный и запирательный нервы

Питание – экстракт эндокринных желез, витамин Е, омега 3, цинк

Меридиан – перикард. Орган – репродуктивные органы

TIBIALIS ATERIOR

Питание –витамин A

Меридиан – мочевой пузырь

Орган – мочевой пузырь

TIBIALIS POSTERIOR

Иннервация – большеберцовый нерв, L4, 5, S1

Питание –витамин A Меридиан – желчный пузырь.

Орган – желчный пузырь

EXTENSOR HALLUCIS LONGUS/BREVIS

Иннервация

длинный разгибатель 1-го пальца — малоберцовый нерв, L4, 5, S1

короткий разгибатель 1-го пальца — малоберцовый нерв, L5, S1

PERONEUS LONGUS/BREVIS

Питание – кальций, комплекс витамина В, избегать чавелевых кислот (ревент, шпинат)

Меридиан – мочевой пузырь.

Орган – мочевой пузырь

PERONEUS TETRIS

FLEXOR HALLICIS LONGUS

Иннервация: Longus — Большеберцовый нерв, L5, S1,2.

Brevis — Большеберцовый нерв, L5 S1.

Тестирование: Давление оказывается на последнее сочленение большого пальца в попытке произвести разгибание в суставе.

Питание: Сырокостный концентрат. Меридиан: Circulation sex.

Орган: Ни один из имеющихся, однако отмечены корреляции с синдромом тарзального туннеля.

FLEXOR DIGITORUM BREVIS

АЛГОРИТМ ЛЕЧЕНИЯ КОМПРЕССИИ КОРЕШКОВ

1. Расположение тела пациента в направлении движения, провоцирующем слабость иннервирующих мышц.

2. Определение максимальной болезненности одного из остистых отростков исследуемого позвоночного двигательного сегмента.

3. Устранение категорий таза;

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

4. Повышение внутричерепного давления;

• тестирование сильной индикаторной мышцы (экстензоры бедра)

• ягулярная компрессия — слабость экстензоров бедра указывает на сторону для воздействия на сакротуберальную связку

5. Растяжение сакротуберальной связки в направлении уменьшающем боль в области ключично — вертебральной связки в сочетании с ягулярной компрессией и выполнением 4-5 глубоких дыхательных движений.

6. Коррегирование остальных дисфункций таза в следующей последовательности:

• устранение — дисфункции крестца, позвоночника;

• сублюксации L5-C1, L4-C2, L3-С3

7. Устранение дисфункций соответствующего ПДС:

• исходное расположение пациента в направлении ротации и латерофлексии уменьшающих слабость мышцы;

• проведение линейного толчка кранио-вентро-латерально или каудо-дорзо-латерально (с учетом rebaund — mechanizm)

8. Повторное тестирование силы иннервирующих мышц и их реакции на провокацию.

АЛГОРИТМ ДИАГНОСТИКИ ФУНКЦИОНАЛЬНОЙ ПАТОЛОГИИ ПРИ НЕОПТИМАЛЬНОЙ ДИНАМИКЕ.

(Среди провоцирующих факторов преобладает ходьба, движения).

А. Визуально определяется:

• основное направление движения, провоцирующее боль.

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

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

В. Пальпаторно определяется:

• место расположения положительной терапевтической локализации.

С. Методом провокации определяется:

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

9. ХИМИЧЕСКАЯ СОСТАВЛЯЮЩАЯ ЗДОРОВЬЯ

Критерии нормореакции

Отсутствие фугкционально расслабленных мышц. Отсутствие гипертоничности мышц — ТЛ на точке К 27.

не ослабляет индикаторную мышцу Отсутствие аллергических реакций.

Критерии химических функциональных нарушений в организме

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

Мышца
 
Вещества
 
дельтовидная
 
витамин С, РНК
 
мышца, напрягающая широ­кую фасцию бедра
 
железо, ацидофилин, бифидобактерии, лактобактерии
 
экстензоры бедра
 
витамин Е. кальций, бетаин
 
ключичная порция большой, грудной мышцы
 
витамин В, B12
 
широчайшая мышца спины
 
витамин А
 
трапециевидная
 
витамин А, С, кальций
 
подлопаточная
 
витамин В., С, Е, калий, магний
 
четырехглавая
 
витамины группы В, витамин D
 
малоберцовые
 
витамины группы В, кальций
 
подвздошно-поясничная
 
витамины А, Е
 
грушевидная
 
витамины А, Е
 
ягодичные
 
витамин Е
 
малая круглая
 
йод, марганец, железо, витамин А, селен, водоросли
 
портняжная
 
витамин С, В5, жень­шень, цинк, иногда — NaCI
 
подколенная
 
витамин А
 
грудинная порция большой грудной мышцы
 
витамин А, желчь
 
большая круглая
 
К, Na, цинк, водоросли
 
надостная
 
РНК
 

АЛГОРИТМ ДИАГНОСТИКИ НАРУШЕНИЙ ХИМИЧЕСКИХ ПРОЦЕССОВ

1. Определение мышцы-индикатора.

2. Проведение химической провокации:

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

3. Поиск патогенетически значимого органа.

4. Терапевтическая локализация на висцеральные органы и поиск органа, терапевтическая локализация на который вызвало функциональное изменение силы мышцы.

5. Диагностика причины (механической, химической, энергетической), вызвавшей нарушение органа и ее коррекция.

Зона для тестирования химических веществ

АЛГОРИТМ ТЕСТИРОВАНИЯ НА НЕДОСТАТОК ВЕЩЕСВ

1. Определение функционально слабой или гипертоничной мышцы

2. Химическая провокация

-химическое вещество располагается на животе или производится диагностика по зонам Ридлера

-устраняется функциональная слабость мышцы — вещество в недостатке

-определение дозы и кратности применения данного вещества

3. Определение органа, нарушающего усвоение вещества

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

4. Поиск причины функционального нарушения органа

-структурные нарушения (дисфункция, диспозия, нарушения крово-лимфообращения)

-химические — потребность в ферментах, витаминах, минералах

— энергетические (меридианный, эмоциональный дисбаланс)

АЛГОРИТМ ТЕСТИРОВАНИЯ НА ИЗБЫТОК ВЕЩЕСТВ (ТОКСИЧНОСТЬ)

1. Определение индикаторной мышцы

2. Химическая провокация

химическое вещество (витамины, минералы) располагается на живете под южным полюсом магнита

— диагностика зон Риддлера

— ослабление мышцы-индикатора — вещество в избытке

3. Определение патогенетического детоксифицирующего органа с одновременно проводимой терапевтической локализацией на выделительных органах. Усиление мышцы-индикатора — подтверждение патогенетической значимости органа.

4. Поиск причины функционального нарушения органа.

структурные нарушения (дисфункция, диспозиция, нарушение крово-лимфообращения)

— химические нарушения (потребность в добавках — витамины, минералы, интоксикации, инфекции)

— энергетические нарушения (меридианный дисбаланс, чакры, эмоции)

ДИАГНОСТИКА ТОКСИЧЕСКИХ ВЕЩЕСТВ И ИНФЕКЦИИ.

1. Диагностика дисфункции органов детоксикации (печень, почки, толстый кишечник, легкие)

— функциональная слабость ассоциированной мышцы

— слабость мышцы-индикатора при терапевтической локализации на органе

2. Коррекция причины дисфункции органа

3. Химическая провокация

— расположение химических провокаторов на коже под южным полюсом магнита (кофеин, парацетомол, фенол, ацетальдегид, перекись водорода, глютамин)

— ослабление индикаторной мышцы — признак нарушения определённого этапа детоксикации

4. Коррекция

биомеханические нарушения

— химические нарушения

— энергетические нарушения

ВЛИЯНИЕ ХИМИЧЕСКИХ НАРУШЕНИЙ НА ДРУГИЕ СОСТАВЛЯЮЩИЕ ЗДОРОВЬЯ.

1. Влияние на энергетические процессы.

память о перенесенном химическом повреждении (печень, толстый кишечник, почки, легкие)

— канально-меридианный дисбаланс (опосредованно через дисфункцию висцерального органа, дисфункцию мышц на пути следования меридиана)

— чакральные нарушения (опосредованно через органы, расположенные в области чакр)

2. Влияние на биомеханику

слабость мышц, вследствие дефицита витаминов, минералов

— нарушение образования соединительной ткани (хрящи, надкостница, связки, кости, мышцы, фасции)

— дефицит аминокислот, витаминов, минералов, интоксикации

— висцеральные органы (интоксикация, дефицит)

— на нервную регуляцию (интоксикация, дефицит)

Варианты нарушений биохимических процессов.

I. Недостаток веществ (витаминов, минералов, аминокислот, полиненасыщенных жирных кислот).

1. Недостаток поступления.

2. Нарушение процессов всасывания.

3. Нарушение процессов усвоения.

4. Нарушения транспортировки в системе лимфы или крови.

5. Нарушение поступления к месту назначения.

6. Патологическое усиление выведения.

II. Избыток веществ (Vitt A, Zn, Си, К, Мд, Са, дисбаланс полиненасыщенных жирных кислот).

1. Избыточное поступление.

2. Нарушение процессов выведения или эллеминации.

III. Наличие токсических веществ.

1. Химикаты (нитраты, пестициды, гербециды, консерванты продуктов).

2. Токсические металлы (Нg-зубная амальгама, рыба в зоне промстоков; Al-тара для напитков, аэрозоли, фармпрепараты; Cd-яркие красители).

3. Радиоактивные вещества, жёсткое излучение.

4. Аллергии.

IV. Инфицированность (острая и хроническая).

1. Грибковая.

2. Вирусная.

3. Паразитарная.

4. Бактериальная.

V. Память о перенесенной травме (общая и местная).

1. Структурная.

2. Химическая.

3. Биологическая.

4. Эмоциональная.

5. Клеточная.

НАРУШЕНИЯ ОБМЕНА ОСНОВНЫХ НУТРИЕНТОВ

ОСНОВНЫЕ ПРИЧИНЫ НАРУШЕНИЯ ОБМЕНА АМИНОКСИЛОТ, УГЛЕВОДОВ.

1. Нарушение работы энтероцитов

1.1. Химические нарушения

воспаление тонкого кишечника (инфекция, бактерии)

1.2. Биомеханические нарушения

спазм висцеральной мускулатуры, спаечный процесс;

— нарушение кровоснабжения

— нарушение лимфооттока

(ассоциированные мышцы — прямая мышца бедра и мышцы живота)

1.3. Энергетические нарушения

меридиан тонкого кишечника

— нарушение желудочной чакры

2. Нарушение работы поджелудочной железы (цинк, витамины гр. В)

2.1. Химические нарушения

токсические нарушения

— инфекционные нарушения (вирусы)

2.2. Биомеханические нарушения

нарушение крово-лимфообращения

— дисфункция, диспозиция органа

(ассоциированные мышцы: широчайшая мышца спины, трехглавая мышца плеча; функциональный блок — Thvi-vii)

2.3. Энергетические нарушения

меридиан селезенки — поджелудочная железа

— нарушение желудочной чакры

ОСНОВНЫЕ ПРИЧИНЫ НАРУШЕНИЯ МЕТАБОЛИЗМА ЖИРОВ

1. Нарушение работы энтероцитов

2. Нарушение работы поджелудочной железы

3. Нарушение работы печени, желчевыводящих путей

химические: дефицит витамина С, таурин, фосфотидилхолин, полиненасыщенные жиры

— токсические

— инфекционные

— биомеханические (дисфункция, диспозиция желчного пузыря, сфинктера Одди, спазм диафрагмы

4. Ассоциированные мышцы: большая грудная мышца, ромбовидная мышца; функциональный блок Thiv

5. Энергетические дисфункции: нарушение меридиана печени; нарушение желудочной и сердечной чакры; эмоции (гнев)

Использование точек начала и конца меридианов диагностике химических нарушений

Lg19 тирозин, Be, фолиевая кислота, Fe, Сu, тирозиназа, В3

V1 триптофан, фолиевая кислота, Fe, Be, В3

VB1 холин, пантотеновая кислота

GI20 глицин, В2, В6, фолиевая кислота, Mn, Zn, глютаминовая кислота, пантотеновая кислота

TR23 нарушение углеводного обмена, B6, B5, C, Zn, Сu, Сг, Fe, тирозиназа, фолиевая кислота

Е1 гистамин, кинин, аргинин, пролин, глицин,серин, фенилаланин, Вб, Zn

Связь определённых мышц с нутриентами

1. Tuaмин (B1)

    2. Рибофлавин (В2)
3. Ниацин (Вз)

  4. Пиридоксин

5. Фолиевая кислота (Р)
6. Витамин А

7. Витамин С

8. Zn

9. К

10. Сr

11. Fe
 

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

ДИАГНОСТИКА ДЕФИЦИТА АМИНОКИСЛОТ

Использован материал Семинара Шелдона С. Дила, проведенного в Санкт-Петербурге в 1998 году.

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

Соответствие недостатка аминокислот дисфункции акупунктурной системы.

Особенности тестирования объектно-ориентированных программных систем 

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

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

Объектно-ориентированные программы неизбежно добавляют специфические проблемы к технологии тестирования. Эти проблемы определяются двумя основными аспектами:

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

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

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

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

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

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

Объектно-ориентированная технология привносит свои особенности в процесс тестирования систем. Формулируется несколько вопросов, которые необходимо разрешить для успешного проведения тестирования: 

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

Решение подобных вопросов выполняется путем разработки новых подходов и модернизации старых, специально для тестирования объектно-ориентированных систем

Методы тестирования объектно-ориентированных систем Выбор базового компонента для тестирования

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

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

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

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

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

Тестирование полиморфизма. Каждый возможный вариант полиморфного вызова метода должен быть протестирован. Примером такого случая является класс А, содержащий метод МА, вызывающий в свою очередь полиморфный метод МАV. Тогда для любого производного класса В, переопределяющего метод MAV, должен быть выполнен тест по вызову метода МА. 

Тестирование с учетом внутренней структуры. Такой метод обычно именуют «white-box testing» (метод «прозрачного ящика»). Тестирование выполняется путем рассмотрения структуры и определения возможных тестовых последовательностей. Существует два варианта подобного тестирования: тестирование, основанное на интерфейсе класса и тестирование, основанное на методах класса. В первом случае набор тестов составляется так, чтобы проверить функционирование интерфейсных свойств объекта, таких как сообщения и исключения. Основными методами составления тестов является анализ графа передачи управления в рамках методов объекта, и анализ потока данных.

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

Тестирование, основанное на состояниях объекта. При тестировании на основе состояний, набор тестов определяется на основе моделирования класса как конечного автомата. Результаты выполнения методов касса рассматриваются как переходы между состояниями класса. Автоматная модель класса определяет последовательность смены состояний, которую и следует проверить в ходе тестирования. Основой для составления автоматной модели класса могут служить диаграммы использования, также допустимо определение допустимых состояний методом «white box» (т.е. на основе анализа программного кода). Подобное тестирование не лишено сложностей. Класс может быть ориентирован на любую последовательность вызова методов и в этом случае тестирование состояний будет неэффективно. Управление сменой состояний объекта может быть рассредоточено по всему приложению. Такое «совместное» управление делает изолированное тестирование классов очень сложным. Выходом может является составление глобальной автоматной модели приложения, с целью определения в ней взаимодействия классов. 

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

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

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

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

Перед тем как приступить к описанию графовой модели объектно-ориентированной программы, остановимся отдельно на одном существенном аспекте разработки программного обеспечения на языке объектно-ориентированного программирования (ООП), например, C++ или С#. Разработка программного обеспечения высокого качества для MS Windows или любой другой операционной системы, использующей стандарт «look and feel», с применением только вновь созданных классов практически невозможна. Программист должен будет затратить массу времени на решение стандартных задач по созданию пользовательского интерфейса. Чтобы избежать работы над давно решенными вопросами, во всех современных компиляторах предусмотрены специальные библиотеки классов. Такие библиотеки включают в себя практически весь программный интерфейс операционной системы и позволяют задействовать при программировании средства более высокого уровня, чем просто вызовы функций. Базовые конструкции и классы могут быть переиспользованы при разработке нового программного проекта. За счет этого значительно сокращается время разработки приложений. В качестве примера подобной системы можно привести библиотеку Microsoft Foundation Class для компилятора MS Visual C++ «.

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

В объектно-ориентированном программировании — часто используется Mock-объект (от англ. mock object, буквально: «объект-пародия», «объект-имитация», а также «подставка») — тип объектов, реализующих заданные аспекты моделируемого программного окружения. например эммуляцию интернет соединения или работу с базами данных.

Mock-объект представляет собой фиктивную реализацию реального класса, предназначенную исключительно для тестирования.

Использование

Mock-объекты активно используются в разработке через тестирование.

Обычно Mock-и создаются для симулирования работы с:

  • хранилищами данных (СУБД)
  • внешними API
  • другими классами приложения, реализующими бизнес-логику, но не тестируемыми в данном конкретном тесте.

Источник:

  • Тест телефона на ошибки
  • Тестирование оперативной памяти на наличие ошибок
  • Тест ссд на ошибки программа
  • Тестирование на компьютере 10 теоретических вопросов допускается 1 ошибка на знание закона об оружии
  • Тестирование eth2 connection ошибка