Рекомендация: Анализ классов эквивалентности
Анализ классов эквивалентности - это метод для минимизации количества тестовых сценариев. В этой рекомендации описан данный метод и его способы его применения.
Взаимосвязи
Основное описание

Введение

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

Тестирование, основанное на анализе классов эквивалентности (синонимы: разбиение на области эквивалентности, анализ области) - это анализ тестирования методом "черного ящика". Цель анализа - сократить до минимума общее число циклов тестирования и обнаружить при этом максимальное возможное количество ошибок [MYE79]. Этот метод позволяет разделить ряд входных и выходных данных на конечное число классов эквивалентности и выбрать характерное тестовое значение для каждого класса. Результаты тестирования характерного значения класса считаются "эквивалентными" другим значениям того же класса. Если при тестировании характерного значения ошибки не были найдены, предполагается, что все другие "эквивалентные" значения также не будут содержать ошибки.

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

  1. Комбинации независимых переменных
  2. Зависимые переменные, основанные на иерархических отношениях
  3. Зависимые переменные, основанные на временных отношениях
  4. Кластерные отношения, основанные на моделях рынка
  5. Моделируемые составные отношения

Стратегии

Существуют разные стратегии и методы для проведения тестирования с разбиением на классы эквивалентности. Некоторые примеры приведены ниже:

Разбиение на классы эквивалентности

Теория разбиения на классы эквивалентности, предложенная Гленфордом Майерсом (Glenford Myers) [MYE79], направлена на сокращение общего числа необходимых тестовых сценариев путем разбиения входных условий на конечное число классов эквивалентности. Создается два типа классов: допустимые входные данные программы рассматриваются как допустимый класс эквивалентности, а все остальные входные данные заносятся в недопустимый класс эквивалентности.

Ниже приведены рекомендации по определению классов эквивалентности:

  1. Если входное условие указывает диапазон значений (например, программа "принимает значения от 10 до 100"), то определяются один допустимый класс эквивалентности (от 10 до 100) и два недопустимых (меньше 10 и больше 100).
  2. Если входное условие указывает набор значений (например, "ткань может быть разных цветов: красного, белого, черного, зеленого, коричневого"), то определяются один допустимый класс (с допустимыми значениями) и один недопустимый (со всеми недопустимыми значениями). Каждое значение допустимого класса нужно обрабатывать отдельно.
  3. Если входное условие содержит выражение долженствования (например, "строка ввода должна содержать прописные символы"), то определяются один допустимый класс (прописные символы) и один недопустимый класс (все остальные варианты ввода кроме прописных символов).
  4. Все действия, выполненные "задолго" до выполнения задачи, считаются классом эквивалентности. Все действия, выполненные незадолго до завершения программы, считаются еще одним классом. Все действия, выполненные непосредственно перед запуском программой другой операции, также считаются отдельным классом.
  5. Если программа настроена на работу с памятью объемом от 64 Мб до 256 Мб, то этот диапазон считается классом эквивалентности. Любой другой объем, больше, чем 256 Мб или меньше, чем 64 Мб, считается недопустимым классом.
  6. Разбиение выходных событий на классы связано с входными данными программы. Несмотря на то, что некоторым входным классам эквивалентности могут соответствовать выходные события того же типа, рекомендуется входные классы рассматривать отдельно.

Анализ граничных значений

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

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

Рекомендации по выбору граничных значений:

  1. Если допустимое значение плавающей переменной составляет от -1.0 до 1.0, протестируйте значения -1.0, 1.0, -1.001 и 1.001.
  2. Если диапазон допустимых значений входных данных составляет целое число от 10 до 100, протестируйте 9, 10, 100, 101.
  3. Если программа настроена на работу с прописными символами, протестируйте граничные значения для A и Z. Протестируйте @ и [, потому что в коде ASCII символ @ предшествует A, а символ [ следует сразу за Z.
  4. Если входные или выходные данные программы представляют собой упорядоченный набор, протестируйте первый и последний элементы набора.
  5. Если сумма входных данных выражена числом (n), протестируйте программу, где сумма равна n-1, n или n+1.
  6. Если программа поддерживает список, протестируйте значения из этого списка. Все остальные значения считаются недопустимыми.
  7. При считывании из файла или записи в файл протестируйте первый и последний символы файла.
  8. Наименьшая денежная единица - один цент или его эквивалент. Если программа поддерживает некий диапазон от a до b, протестируйте a -0.01 и b +0.01.
  9. Если для переменной указано несколько диапазонов значений, каждый диапазон считается отдельным классом. Если подмножества значений из этих диапазонов не пересекаются, протестируйте крайние значения, а также граничные значения над верхней границей и под нижней границей.

Специальные значения

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

  1. В случае с целыми числами нужно обязательно протестировать ноль, если он входит в допустимый класс эквивалентности.
  2. При тестировании времени необходимо для каждого элемента (час, минута и секунда) протестировать значения 59 и 0, независимо от ограничения, установленного для входной переменной. Помимо граничных значений входной переменной необходимо всегда тестировать значения -1, 0, 59 и 60.
  3. При тестировании даты (год, месяц и день) необходимо добавить тестовые сценарии, например, для количества дней в конкретном месяце, количества дней в феврале в високосном году или количества дней в невисокосном году.

Метод "Разбиение на категории"

Остранд и Болсер (Ostrand and Balcer) [16] разработали метод разбиения, который позволяет испытателям анализировать спецификацию системы, создавать тестовые сценарии и управлять ими. Если большинство стратегий сфокусированы на работе с исходным кодом, метод Остранда и Болсера также предполагает использование данных спецификации и проектирования.

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

Ниже перечислены шаги для применения метода "разбиение на категории":

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

    1. Определите параметры и условия среды, от которых зависит выполнение функции. Параметры - это входные данные функциональной единицы. Условия среды - это состояния системы, от которых зависит выполнение функциональной единицы.
    2. Определите характеристики параметров и условий среды.
    3. Разбейте характеристики на категории, от которых зависит поведение системы.

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

  2. Разделите категории на варианты. Варианты - это ситуации, которые могут неожиданно возникнуть. В каждом варианте содержится тот же тип данных, что и в категории.

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

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

Дополнительная информация и ссылки

  1. Glenford J. Myers, The Art of Software Testing, John Wiley & Sons, Inc., New York, 1979.
  2. White L. J. and Cohen E. I., A domain strategy for computer program testing, IEEE Transaction on Software Engineering, Vol. SE-6, No. 3, 1980.
  3. Lori A. Clarke, Johnhette Hassell, and Debra J Richardson, A Close Look at Domain Testing, IEEE Transaction on Software Engineering, 8-4, 1992.
  4. Steven J. Zeil, Faten H. Afifi and Lee J. White, Detection of Linear Detection via Domain Testing, ACM Transaction on Software Engineering and Methodology, 1-4, 1992.
  5. BingHiang Jeng, Elaine J. Weyuker, A Simplified Domain-Testing Strategy, ACM Transaction on Software Engineering and Methodology, 3-3, 1994.
  6. Paul C. Jorgensen, Software Testing - A Craftsman's Approach, CRC Press LLC, 1995.
  7. Martin R. Woodward and Zuhoor A. Al-khanjari, Testability, fault, and the domain-to-range ratio: An eternal triangle, ACM Press New York, NY, 2000.
  8. Dick Hamlet, On subdomains: Testing, profiles, and components, SIGSOFT: ACM Special Interest Group on Software Engineering, 71-16, 2000.
  9. Cem Kaner, James Bach, and Bret Pettichord, Lessons learned in Software Testing, John Wiley & Sons, Inc., New York, 2002.
  10. Andy Podgurski and Charles Yang, Partition Testing, Stratified Sampling, and Cluster Analysis, SIGSOFT: ACM Special Interest Group on Software Engineering, 18-5, 1993.
  11. Debra J. Richardson and Lori A. Clarke, A partition analysis method to increase program reliability, SIGSOFT: ACM Special Interest Group on Software Engineering, 1981.
  12. Lori A. Clarke, Johnette Hassell, and Debra J Richardson, A system to generate test data and symbolically execute programs, IEEE Transaction on Software Engineering, SE-2, 1976.
  13. Boris Beizer, Black-Box Testing - Techniques for Functional testing of Software and System, John Wiley & Sons, Inc., 1995.
  14. Steven J. Zeil, Faten H. Afifi and Lee J. White, Testing for Liner Errors in Nonlinear computer programs, ACM Transaction on Software Engineering and Methodology, 1-4, 1992.
  15. William E. Howden, Functional Program Testing, IEEE Transactions on Software Engineering, Vol. SE-6, No. 2, 1980.
  16. Thomas J. Ostrand and Marc J. Balcer, The Category-Partition method for specifying and generating functional tests, Communications of ACM 31, 1988.
  17. Cem Kaner, Jack Falk and Hung Quoc Nguyen, Testing Computer Software, John Wiley & Sons, Inc., 1999.