gadget59.ru лекции
Тестирование ПО · Лекция 2 · 26 слайдов

Классы эквивалентности и граничные значения в тестировании

Классы эквивалентности и граничные значения

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

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

📦 Классы эквивалентности 📏 Граничные значения ✂️ Сокращение тестов 🔍 Поиск багов
Это вторая лекция из цикла. Она посвящена тест-дизайну — искусству придумывать тесты так, чтобы их было мало, а пользы — много.
Формат: лекция + практика. В конце — задания, которые нужно будет выполнить на занятии.

План лекции

Сегодня мы разберём два метода тест-дизайна, которые используются в 90% проектов.

  • 1 Проблема «бесконечного» тестирования
  • 2 Что такое класс эквивалентности
  • 3 Как выделять классы эквивалентности
  • 4 Валидные и невалидные классы
  • 5 Пример: тестирование возраста
  • 6 Что такое граничные значения
  • 7 Почему границы — самое важное
  • 8 Пример: тестирование диапазона
  • 9 Комбинирование методов
  • 10 Типичные ошибки
  • 11 Итоги и практика
Если вы пропустили первую лекцию — вернитесь. Без понимания, что такое тестирование и «чёрный ящик», эта тема будет непонятна.

Проблема «бесконечного» тестирования

Представьте, что у нас есть функция сложения двух целых чисел. Диапазон допустимых значений — от -2 147 483 648 до 2 147 483 647.

Сколько возможных комбинаций?
4 294 967 296 × 4 294 967 296 = 18 446 744 073 709 551 616

Это 18 квинтиллионов комбинаций. Даже если проверять по одной комбинации в секунду, потребуется более 500 миллиардов лет.

Аналогия. Представьте, что вам нужно проверить все яблоки в саду. Но их миллиарды. Вы не сможете съесть каждое. Что делать? Взять несколько яблок из разных корзин и проверить их. Если они хорошие — скорее всего, и остальные тоже.
Тестировать всё — невозможно. Нужно выбирать представителей. Именно для этого и придумали классы эквивалентности и граничные значения.

Что такое класс эквивалентности

Класс эквивалентности (equivalence class) — это группа входных данных, которые программа должна обрабатывать одинаково.

Если два значения принадлежат одному классу, то, проверив одно из них, мы можем с большой вероятностью сказать, что и второе будет обработано так же.
Аналогия. Представьте, что у вас есть три корзины с фруктами: яблоки, груши и апельсины. Вам нужно проверить, что все фрукты спелые. Достаточно попробовать одно яблоко, одну грушу и один апельсин. Не нужно пробовать все 1000 яблок, если они из одной корзины.

Для функции сложения можно выделить такие классы:

  • Оба числа положительные.
  • Оба числа отрицательные.
  • Одно положительное, другое отрицательное.
  • Одно из чисел — ноль.
Вместо 18 квинтиллионов проверок — всего 4 теста (по одному на каждый класс).

Валидные и невалидные классы

Классы эквивалентности делятся на две группы.

✅
Валидные (допустимые)
Данные, с которыми программа должна работать правильно. Например, числа в допустимом диапазоне.
❌
Невалидные (недопустимые)
Данные, которые программа должна отвергать с сообщением об ошибке. Например, буквы вместо цифр или числа вне диапазона.
Важно проверять оба типа. Плохой тестировщик проверяет только «правильные» данные. Хороший — ещё и «неправильные», потому что именно на них программа чаще всего «ломается».
// Пример для функции «возраст от 0 до 120» Валидные классы: 0 ≤ age ≤ 120 Невалидные классы: age < 0, age > 120, age = "abc"

Пример: тестируем возраст

Допустим, у нас есть функция, которая принимает возраст человека. Требование: возраст от 0 до 120 лет.

Выделяем классы эквивалентности

КлассДиапазонТипПример 1age < 0невалидный-5 20 ≤ age ≤ 120валидный25 3age > 120невалидный150
Достаточно трёх тестов: -5, 25, 150. Если все три пройдены — функция работает для всех значений из этих классов.
Обратите внимание: мы проверили и «правильные», и «неправильные» данные. Это важно.

Что такое граничные значения

Граничное значение (boundary value) — это значение на границе диапазона. Именно там чаще всего возникают ошибки.

Аналогия. Представьте забор. Внутри забора — безопасно, снаружи — опасно. Где чаще всего происходят неприятности? На самой границе! То же самое в программировании: ошибки чаще всего прячутся на границах диапазонов.

Для диапазона 0 ≤ age ≤ 120 граничные значения:

ЗначениеЧислоПочему важно Минимум - 1-1за границей, должно быть отвергнуто Минимум0граница, должно быть принято Минимум + 11сразу внутри, должно быть принято Максимум - 1119сразу внутри, должно быть принято Максимум120граница, должно быть принято Максимум + 1121за границей, должно быть отвергнуто

Почему границы — самое важное

Статистика говорит: большинство ошибок в программах возникает именно на границах диапазонов.

📊
Около 70%
ошибок возникает на границах и «почти на границах» значений.
🎯
3 значения
достаточно проверить, чтобы покрыть границу: минимум, максимум и «чуть-чуть за».
Причина: программисты часто используют строгие неравенства < и >, когда нужно нестрогое <= и >= (или наоборот). Это классическая ошибка «на единицу» (off-by-one).
// Правильно: if (age >= 0 && age <= 120) { ... } // Ошибка «на единицу»: if (age > 0 && age < 120) { ... } // отсекает 0 и 120

Пример: тестируем диапазон

Функция принимает оценку от 1 до 5. Нужно проверить, что она работает правильно.

Шаг 1. Выделяем классы эквивалентности

КлассДиапазонТип 1mark < 1невалидный 21 ≤ mark ≤ 5валидный 3mark > 5невалидный

Шаг 2. Добавляем граничные значения

ЗначениеЧислоОжидаем минимум - 10ошибка минимум1принято минимум + 12принято максимум - 14принято максимум5принято максимум + 16ошибка
Всего 6 тестов — и мы покрыли весь диапазон и его границы. Это гораздо эффективнее, чем проверять все числа от -100 до 100.

Комбинирование методов

На практике классы эквивалентности и граничные значения используют вместе.

1. Выделяем классы эквивалентности
↓
2. Выбираем по одному значению из каждого класса
↓
3. Добавляем граничные значения
↓
4. Получаем минимальный, но полный набор тестов
Классы эквивалентности отвечают на вопрос «что проверять?».
Граничные значения отвечают на вопрос «где искать ошибки в первую очередь?».

Пример: тестируем деление

Функция деления a / b. Делитель b не должен быть равен нулю.

Классы эквивалентности для b

КлассЗначениеТип 1b = 0невалидный 2b > 0валидный 3b < 0валидный

Граничные значения

ЗначениеЧислоОжидаем -1-1принято 00ошибка 11принято
Три теста — и мы проверили все классы и все границы. Именно так работают профессиональные тестировщики.

Типичные ошибки новичков

1. Тестировать только «правильные» данные
Забывают про невалидные классы. А именно там чаще всего прячутся баги.
2. Игнорировать границы
Проверяют только середину диапазона. А ошибки — на краях.
3. Путать строгие и нестрогие неравенства
Считают, что 0 ≤ age ≤ 120 — это то же самое, что 0 < age < 120. Это не так.
4. Забывать про ноль
Ноль — это особое значение. Он часто ведёт себя не так, как другие числа.
5. Не проверять отрицательные числа
Если программа должна принимать отрицательные числа, это нужно проверить.

Практическое задание

Примените методы на практике.

Задание 1

Для функции «скидка на покупку от 1000 до 5000 рублей» выделите классы эквивалентности и граничные значения.

Задание 2

Для функции «пароль длиной от 8 до 20 символов» составьте минимальный набор тестов.

Задание 3

Почему для функции деления важно проверить именно b = 0? Что произойдёт, если этого не сделать?

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

Шпаргалка

Сохраните этот слайд — здесь все основные понятия лекции.

ТерминЧто значит Класс эквивалентностигруппа значений, обрабатываемых одинаково Валидный классдопустимые данные Невалидный класснедопустимые данные Граничное значениезначение на границе диапазона Ошибка «на единицу»путаница между < и <= Тест-дизайнискусство придумывать эффективные тесты

Итоги лекции

Подведём итоги. Вот что вы теперь знаете.

  • ✅ Тестировать всё невозможно. Нужно выбирать представителей.
  • ✅ Класс эквивалентности — группа значений, обрабатываемых одинаково.
  • ✅ Классы бывают валидные (допустимые) и невалидные (недопустимые).
  • ✅ Граничные значения — значения на границе диапазона. Там чаще всего возникают ошибки.
  • ✅ Методы комбинируются: сначала классы, потом границы.
  • ✅ Ошибка «на единицу» — классическая проблема, которую ловят граничные значения.
В следующей лекции мы разберём тест-кейсы, чек-листы и баг-репорты — как оформлять результаты тестирования так, чтобы их поняли разработчики.

Домашнее задание

Задания для самостоятельной работы. Первые два обязательны, остальные — для оценки «отлично».

  1. Для функции «возраст от 18 до 65 лет» выделите классы эквивалентности и граничные значения.
  2. Для функции «оценка от 1 до 5» составьте полный набор тестов (классы + границы).
  3. Объясните своими словами, почему граничные значения важнее, чем проверка «середины» диапазона.
  4. Приведите пример ошибки «на единицу» из реальной жизни.
  5. Найдите в интернете пример бага, который был найден именно с помощью граничных значений.
Если задание кажется сложным — разбейте его на части. Сначала классы, потом границы, потом вывод.

Что дальше?

В этом блоке по тестированию у нас ещё несколько материалов.

  • Лекция 3: тест-кейсы, чек-листы, баг-репорты.
  • Практика 1: тестирование калькулятора «чёрным ящиком».
  • Практика 2: модульное тестирование в Visual Studio (C#) или pytest (Python).
Тест-дизайн — это навык, который отличает новичка от профессионала. Умение придумывать эффективные тесты ценится в любой IT-команде.

Спасибо за внимание!

📏

Хороший тестировщик — это «ленивый» тестировщик

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

📦 Классы эквивалентности 📏 Граничные значения 🎯 Тест-дизайн 🚀 практика